aboutsummaryrefslogtreecommitdiff
path: root/src/share
diff options
context:
space:
mode:
authornever <none@none>2010-07-08 14:29:44 -0700
committernever <none@none>2010-07-08 14:29:44 -0700
commit4afd1332c1ef732077ea78ff0902d94545ffeaef (patch)
tree0cd1b529a3ba95208aa92aa88e221529801b2682 /src/share
parent6b90d24ba548ba05384992578dafc58af85b2194 (diff)
downloadjdk8u_hotspot-4afd1332c1ef732077ea78ff0902d94545ffeaef.tar.gz
6965184: possible races in make_not_entrant_or_zombie
Reviewed-by: kvn
Diffstat (limited to 'src/share')
-rw-r--r--src/share/vm/classfile/classLoader.cpp3
-rw-r--r--src/share/vm/code/codeBlob.cpp6
-rw-r--r--src/share/vm/code/codeCache.cpp23
-rw-r--r--src/share/vm/code/codeCache.hpp6
-rw-r--r--src/share/vm/code/nmethod.cpp195
-rw-r--r--src/share/vm/code/nmethod.hpp108
-rw-r--r--src/share/vm/code/vtableStubs.cpp3
-rw-r--r--src/share/vm/includeDB_core14
-rw-r--r--src/share/vm/interpreter/interpreter.cpp5
-rw-r--r--src/share/vm/runtime/globals.hpp3
-rw-r--r--src/share/vm/runtime/init.cpp2
-rw-r--r--src/share/vm/runtime/java.cpp4
-rw-r--r--src/share/vm/runtime/sharedRuntime.cpp1
-rw-r--r--src/share/vm/runtime/stubCodeGenerator.cpp3
-rw-r--r--src/share/vm/runtime/sweeper.cpp147
-rw-r--r--src/share/vm/runtime/sweeper.hpp10
-rw-r--r--src/share/vm/runtime/vmStructs.cpp1
-rw-r--r--src/share/vm/runtime/vtune.hpp55
18 files changed, 226 insertions, 363 deletions
diff --git a/src/share/vm/classfile/classLoader.cpp b/src/share/vm/classfile/classLoader.cpp
index c0c521222..cd2432f21 100644
--- a/src/share/vm/classfile/classLoader.cpp
+++ b/src/share/vm/classfile/classLoader.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -832,7 +832,6 @@ objArrayOop ClassLoader::get_system_packages(TRAPS) {
instanceKlassHandle ClassLoader::load_classfile(symbolHandle h_name, TRAPS) {
- VTuneClassLoadMarker clm;
ResourceMark rm(THREAD);
EventMark m("loading class " INTPTR_FORMAT, (address)h_name());
ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion);
diff --git a/src/share/vm/code/codeBlob.cpp b/src/share/vm/code/codeBlob.cpp
index 2b8410105..33b267be7 100644
--- a/src/share/vm/code/codeBlob.cpp
+++ b/src/share/vm/code/codeBlob.cpp
@@ -210,6 +210,7 @@ AdapterBlob* AdapterBlob::create(CodeBuffer* cb) {
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
blob = new (size) AdapterBlob(size, cb);
+ CodeCache::commit(blob);
}
// Track memory usage statistic after releasing CodeCache_lock
MemoryService::track_code_cache_memory_usage();
@@ -281,7 +282,6 @@ RuntimeStub* RuntimeStub::new_runtime_stub(const char* stub_name,
tty->print_cr("Decoding %s " INTPTR_FORMAT, stub_id, stub);
Disassembler::decode(stub->instructions_begin(), stub->instructions_end());
}
- VTune::register_stub(stub_id, stub->instructions_begin(), stub->instructions_end());
Forte::register_stub(stub_id, stub->instructions_begin(), stub->instructions_end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
@@ -356,7 +356,6 @@ DeoptimizationBlob* DeoptimizationBlob::create(
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
}
- VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
@@ -414,7 +413,6 @@ UncommonTrapBlob* UncommonTrapBlob::create(
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
}
- VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
@@ -474,7 +472,6 @@ ExceptionBlob* ExceptionBlob::create(
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
}
- VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
@@ -533,7 +530,6 @@ SafepointBlob* SafepointBlob::create(
tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
}
- VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
diff --git a/src/share/vm/code/codeCache.cpp b/src/share/vm/code/codeCache.cpp
index 54767b369..485aff812 100644
--- a/src/share/vm/code/codeCache.cpp
+++ b/src/share/vm/code/codeCache.cpp
@@ -93,6 +93,8 @@ class CodeBlob_sizes {
CodeHeap * CodeCache::_heap = new CodeHeap();
int CodeCache::_number_of_blobs = 0;
+int CodeCache::_number_of_adapters = 0;
+int CodeCache::_number_of_nmethods = 0;
int CodeCache::_number_of_nmethods_with_dependencies = 0;
bool CodeCache::_needs_cache_clean = false;
nmethod* CodeCache::_scavenge_root_nmethods = NULL;
@@ -176,8 +178,14 @@ void CodeCache::free(CodeBlob* cb) {
verify_if_often();
print_trace("free", cb);
- if (cb->is_nmethod() && ((nmethod *)cb)->has_dependencies()) {
- _number_of_nmethods_with_dependencies--;
+ if (cb->is_nmethod()) {
+ _number_of_nmethods--;
+ if (((nmethod *)cb)->has_dependencies()) {
+ _number_of_nmethods_with_dependencies--;
+ }
+ }
+ if (cb->is_adapter_blob()) {
+ _number_of_adapters--;
}
_number_of_blobs--;
@@ -191,9 +199,16 @@ void CodeCache::free(CodeBlob* cb) {
void CodeCache::commit(CodeBlob* cb) {
// this is called by nmethod::nmethod, which must already own CodeCache_lock
assert_locked_or_safepoint(CodeCache_lock);
- if (cb->is_nmethod() && ((nmethod *)cb)->has_dependencies()) {
- _number_of_nmethods_with_dependencies++;
+ if (cb->is_nmethod()) {
+ _number_of_nmethods++;
+ if (((nmethod *)cb)->has_dependencies()) {
+ _number_of_nmethods_with_dependencies++;
+ }
}
+ if (cb->is_adapter_blob()) {
+ _number_of_adapters++;
+ }
+
// flush the hardware I-cache
ICache::invalidate_range(cb->instructions_begin(), cb->instructions_size());
}
diff --git a/src/share/vm/code/codeCache.hpp b/src/share/vm/code/codeCache.hpp
index 4197b9b10..8c63cd6ef 100644
--- a/src/share/vm/code/codeCache.hpp
+++ b/src/share/vm/code/codeCache.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,6 +43,8 @@ class CodeCache : AllStatic {
// 4422213 or 4436291 for details.
static CodeHeap * _heap;
static int _number_of_blobs;
+ static int _number_of_adapters;
+ static int _number_of_nmethods;
static int _number_of_nmethods_with_dependencies;
static bool _needs_cache_clean;
static nmethod* _scavenge_root_nmethods; // linked via nm->scavenge_root_link()
@@ -105,6 +107,8 @@ class CodeCache : AllStatic {
static nmethod* first_nmethod();
static nmethod* next_nmethod (CodeBlob* cb);
static int nof_blobs() { return _number_of_blobs; }
+ static int nof_adapters() { return _number_of_adapters; }
+ static int nof_nmethods() { return _number_of_nmethods; }
// GC support
static void gc_epilogue();
diff --git a/src/share/vm/code/nmethod.cpp b/src/share/vm/code/nmethod.cpp
index 0942849af..3f95285af 100644
--- a/src/share/vm/code/nmethod.cpp
+++ b/src/share/vm/code/nmethod.cpp
@@ -397,11 +397,6 @@ void nmethod::add_handler_for_exception_and_pc(Handle exception, address pc, add
//-------------end of code for ExceptionCache--------------
-void nmFlags::clear() {
- assert(sizeof(nmFlags) == sizeof(int), "using more than one word for nmFlags");
- *(jint*)this = 0;
-}
-
int nmethod::total_size() const {
return
code_size() +
@@ -419,8 +414,32 @@ const char* nmethod::compile_kind() const {
return NULL;
}
-// %%% This variable is no longer used?
-int nmethod::_zombie_instruction_size = NativeJump::instruction_size;
+// Fill in default values for various flag fields
+void nmethod::init_defaults() {
+ _state = alive;
+ _marked_for_reclamation = 0;
+ _has_flushed_dependencies = 0;
+ _speculatively_disconnected = 0;
+ _has_unsafe_access = 0;
+ _has_method_handle_invokes = 0;
+ _marked_for_deoptimization = 0;
+ _lock_count = 0;
+ _stack_traversal_mark = 0;
+ _unload_reported = false; // jvmti state
+
+ NOT_PRODUCT(_has_debug_info = false);
+ _oops_do_mark_link = NULL;
+ _jmethod_id = NULL;
+ _osr_link = NULL;
+ _scavenge_root_link = NULL;
+ _scavenge_root_state = 0;
+ _saved_nmethod_link = NULL;
+ _compiler = NULL;
+
+#ifdef HAVE_DTRACE_H
+ _trap_offset = 0;
+#endif // def HAVE_DTRACE_H
+}
nmethod* nmethod::new_native_nmethod(methodHandle method,
@@ -580,25 +599,16 @@ nmethod::nmethod(
debug_only(No_Safepoint_Verifier nsv;)
assert_locked_or_safepoint(CodeCache_lock);
- NOT_PRODUCT(_has_debug_info = false);
- _oops_do_mark_link = NULL;
+ init_defaults();
_method = method;
_entry_bci = InvocationEntryBci;
- _jmethod_id = NULL;
- _osr_link = NULL;
- _scavenge_root_link = NULL;
- _scavenge_root_state = 0;
- _saved_nmethod_link = NULL;
- _compiler = NULL;
// We have no exception handler or deopt handler make the
// values something that will never match a pc like the nmethod vtable entry
_exception_offset = 0;
_deoptimize_offset = 0;
_deoptimize_mh_offset = 0;
_orig_pc_offset = 0;
-#ifdef HAVE_DTRACE_H
- _trap_offset = 0;
-#endif // def HAVE_DTRACE_H
+
_stub_offset = data_offset();
_consts_offset = data_offset();
_oops_offset = data_offset();
@@ -616,17 +626,9 @@ nmethod::nmethod(
_exception_cache = NULL;
_pc_desc_cache.reset_to(NULL);
- flags.clear();
- flags.state = alive;
- _markedForDeoptimization = 0;
-
- _lock_count = 0;
- _stack_traversal_mark = 0;
-
code_buffer->copy_oops_to(this);
debug_only(verify_scavenge_root_oops());
CodeCache::commit(this);
- VTune::create_nmethod(this);
}
if (PrintNativeNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
@@ -674,15 +676,9 @@ nmethod::nmethod(
debug_only(No_Safepoint_Verifier nsv;)
assert_locked_or_safepoint(CodeCache_lock);
- NOT_PRODUCT(_has_debug_info = false);
- _oops_do_mark_link = NULL;
+ init_defaults();
_method = method;
_entry_bci = InvocationEntryBci;
- _jmethod_id = NULL;
- _osr_link = NULL;
- _scavenge_root_link = NULL;
- _scavenge_root_state = 0;
- _compiler = NULL;
// We have no exception handler or deopt handler make the
// values something that will never match a pc like the nmethod vtable entry
_exception_offset = 0;
@@ -708,17 +704,9 @@ nmethod::nmethod(
_exception_cache = NULL;
_pc_desc_cache.reset_to(NULL);
- flags.clear();
- flags.state = alive;
- _markedForDeoptimization = 0;
-
- _lock_count = 0;
- _stack_traversal_mark = 0;
-
code_buffer->copy_oops_to(this);
debug_only(verify_scavenge_root_oops());
CodeCache::commit(this);
- VTune::create_nmethod(this);
}
if (PrintNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
@@ -783,21 +771,13 @@ nmethod::nmethod(
debug_only(No_Safepoint_Verifier nsv;)
assert_locked_or_safepoint(CodeCache_lock);
- NOT_PRODUCT(_has_debug_info = false);
- _oops_do_mark_link = NULL;
+ init_defaults();
_method = method;
- _jmethod_id = NULL;
+ _entry_bci = entry_bci;
_compile_id = compile_id;
_comp_level = comp_level;
- _entry_bci = entry_bci;
- _osr_link = NULL;
- _scavenge_root_link = NULL;
- _scavenge_root_state = 0;
_compiler = compiler;
_orig_pc_offset = orig_pc_offset;
-#ifdef HAVE_DTRACE_H
- _trap_offset = 0;
-#endif // def HAVE_DTRACE_H
_stub_offset = instructions_offset() + code_buffer->total_offset_of(code_buffer->stubs()->start());
// Exception handler and deopt handler are in the stub section
@@ -824,15 +804,6 @@ nmethod::nmethod(
_exception_cache = NULL;
_pc_desc_cache.reset_to(scopes_pcs_begin());
- flags.clear();
- flags.state = alive;
- _markedForDeoptimization = 0;
-
- _unload_reported = false; // jvmti state
-
- _lock_count = 0;
- _stack_traversal_mark = 0;
-
// Copy contents of ScopeDescRecorder to nmethod
code_buffer->copy_oops_to(this);
debug_info->copy_to(this);
@@ -844,8 +815,6 @@ nmethod::nmethod(
CodeCache::commit(this);
- VTune::create_nmethod(this);
-
// Copy contents of ExceptionHandlerTable to nmethod
handler_table->copy_to(this);
nul_chk_table->copy_to(this);
@@ -991,11 +960,6 @@ void nmethod::print_nmethod(bool printmethod) {
}
-void nmethod::set_version(int v) {
- flags.version = v;
-}
-
-
// Promote one word from an assembly-time handle to a live embedded oop.
inline void nmethod::initialize_immediate_oop(oop* dest, jobject handle) {
if (handle == NULL ||
@@ -1142,6 +1106,8 @@ void nmethod::cleanup_inline_caches() {
// This is a private interface with the sweeper.
void nmethod::mark_as_seen_on_stack() {
assert(is_not_entrant(), "must be a non-entrant method");
+ // Set the traversal mark to ensure that the sweeper does 2
+ // cleaning passes before moving to zombie.
set_stack_traversal_mark(NMethodSweeper::traversal_count());
}
@@ -1210,7 +1176,7 @@ void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) {
// for later on.
CodeCache::set_needs_cache_clean(true);
}
- flags.state = unloaded;
+ _state = unloaded;
// Log the unloading.
log_state_change();
@@ -1236,21 +1202,21 @@ void nmethod::log_state_change() const {
if (LogCompilation) {
if (xtty != NULL) {
ttyLocker ttyl; // keep the following output all in one block
- if (flags.state == unloaded) {
+ if (_state == unloaded) {
xtty->begin_elem("make_unloaded thread='" UINTX_FORMAT "'",
os::current_thread_id());
} else {
xtty->begin_elem("make_not_entrant thread='" UINTX_FORMAT "'%s",
os::current_thread_id(),
- (flags.state == zombie ? " zombie='1'" : ""));
+ (_state == zombie ? " zombie='1'" : ""));
}
log_identity(xtty);
xtty->stamp();
xtty->end_elem();
}
}
- if (PrintCompilation && flags.state != unloaded) {
- print_on(tty, flags.state == zombie ? "made zombie " : "made not entrant ");
+ if (PrintCompilation && _state != unloaded) {
+ print_on(tty, _state == zombie ? "made zombie " : "made not entrant ");
tty->cr();
}
}
@@ -1261,8 +1227,9 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
bool was_alive = false;
- // Make sure the nmethod is not flushed in case of a safepoint in code below.
+ // Make sure neither the nmethod nor the method is flushed in case of a safepoint in code below.
nmethodLocker nml(this);
+ methodHandle the_method(method());
{
// If the method is already zombie there is nothing to do
@@ -1282,7 +1249,7 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
// Enter critical section. Does not block for safepoint.
MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
- if (flags.state == state) {
+ if (_state == state) {
// another thread already performed this transition so nothing
// to do, but return false to indicate this.
return false;
@@ -1293,17 +1260,37 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
if (!is_osr_method() && !is_not_entrant()) {
NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
SharedRuntime::get_handle_wrong_method_stub());
- assert (NativeJump::instruction_size == nmethod::_zombie_instruction_size, "");
}
- was_alive = is_in_use(); // Read state under lock
+ if (is_in_use()) {
+ // It's a true state change, so mark the method as decompiled.
+ // Do it only for transition from alive.
+ inc_decompile_count();
+ }
// Change state
- flags.state = state;
+ _state = state;
// Log the transition once
log_state_change();
+ // Remove nmethod from method.
+ // We need to check if both the _code and _from_compiled_code_entry_point
+ // refer to this nmethod because there is a race in setting these two fields
+ // in methodOop as seen in bugid 4947125.
+ // If the vep() points to the zombie nmethod, the memory for the nmethod
+ // could be flushed and the compiler and vtable stubs could still call
+ // through it.
+ if (method() != NULL && (method()->code() == this ||
+ method()->from_compiled_entry() == verified_entry_point())) {
+ HandleMark hm;
+ method()->clear_code();
+ }
+
+ if (state == not_entrant) {
+ mark_as_seen_on_stack();
+ }
+
} // leave critical region under Patching_lock
// When the nmethod becomes zombie it is no longer alive so the
@@ -1311,18 +1298,17 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
// state will be flushed later when the transition to zombie
// happens or they get unloaded.
if (state == zombie) {
+ // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event
+ // and it hasn't already been reported for this nmethod then report it now.
+ // (the event may have been reported earilier if the GC marked it for unloading).
+ post_compiled_method_unload();
+
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
flush_dependencies(NULL);
} else {
assert(state == not_entrant, "other cases may need to be handled differently");
}
- if (state == not_entrant) {
- Events::log("Make nmethod not entrant " INTPTR_FORMAT, this);
- } else {
- Events::log("Make nmethod zombie " INTPTR_FORMAT, this);
- }
-
if (TraceCreateZombies) {
tty->print_cr("nmethod <" INTPTR_FORMAT "> code made %s", this, (state == not_entrant) ? "not entrant" : "zombie");
}
@@ -1330,47 +1316,6 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
// Make sweeper aware that there is a zombie method that needs to be removed
NMethodSweeper::notify(this);
- // not_entrant only stuff
- if (state == not_entrant) {
- mark_as_seen_on_stack();
- }
-
- if (was_alive) {
- // It's a true state change, so mark the method as decompiled.
- // Do it only for transition from alive.
- inc_decompile_count();
- }
-
- // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event
- // and it hasn't already been reported for this nmethod then report it now.
- // (the event may have been reported earilier if the GC marked it for unloading).
- if (state == zombie) {
- post_compiled_method_unload();
- }
-
-
- // Zombie only stuff
- if (state == zombie) {
- VTune::delete_nmethod(this);
- }
-
- // Check whether method got unloaded at a safepoint before this,
- // if so we can skip the flushing steps below
- if (method() == NULL) return true;
-
- // Remove nmethod from method.
- // We need to check if both the _code and _from_compiled_code_entry_point
- // refer to this nmethod because there is a race in setting these two fields
- // in methodOop as seen in bugid 4947125.
- // If the vep() points to the zombie nmethod, the memory for the nmethod
- // could be flushed and the compiler and vtable stubs could still call
- // through it.
- if (method()->code() == this ||
- method()->from_compiled_entry() == verified_entry_point()) {
- HandleMark hm;
- method()->clear_code();
- }
-
return true;
}
@@ -2109,7 +2054,6 @@ address nmethod::continuation_for_implicit_exception(address pc) {
void nmethod_init() {
// make sure you didn't forget to adjust the filler fields
- assert(sizeof(nmFlags) <= 4, "nmFlags occupies more than a word");
assert(sizeof(nmethod) % oopSize == 0, "nmethod size must be multiple of a word");
}
@@ -2345,7 +2289,6 @@ void nmethod::print() const {
tty->print("((nmethod*) "INTPTR_FORMAT ") ", this);
tty->print(" for method " INTPTR_FORMAT , (address)method());
tty->print(" { ");
- if (version()) tty->print("v%d ", version());
if (is_in_use()) tty->print("in_use ");
if (is_not_entrant()) tty->print("not_entrant ");
if (is_zombie()) tty->print("zombie ");
diff --git a/src/share/vm/code/nmethod.hpp b/src/share/vm/code/nmethod.hpp
index f6e8bc38c..67a87a64a 100644
--- a/src/share/vm/code/nmethod.hpp
+++ b/src/share/vm/code/nmethod.hpp
@@ -78,29 +78,8 @@ class PcDescCache VALUE_OBJ_CLASS_SPEC {
// nmethods (native methods) are the compiled code versions of Java methods.
-
-struct nmFlags {
- friend class VMStructs;
- unsigned int version:8; // version number (0 = first version)
- unsigned int age:4; // age (in # of sweep steps)
-
- unsigned int state:2; // {alive, zombie, unloaded)
-
- unsigned int isUncommonRecompiled:1; // recompiled because of uncommon trap?
- unsigned int isToBeRecompiled:1; // to be recompiled as soon as it matures
- unsigned int hasFlushedDependencies:1; // Used for maintenance of dependencies
- unsigned int markedForReclamation:1; // Used by NMethodSweeper
-
- unsigned int has_unsafe_access:1; // May fault due to unsafe access.
- unsigned int has_method_handle_invokes:1; // Has this method MethodHandle invokes?
-
- unsigned int speculatively_disconnected:1; // Marked for potential unload
-
- void clear();
-};
-
-
-// A nmethod contains:
+//
+// An nmethod contains:
// - header (the nmethod structure)
// [Relocation]
// - relocation information
@@ -131,8 +110,6 @@ class nmethod : public CodeBlob {
friend class CodeCache; // non-perm oops
private:
// Shared fields for all nmethod's
- static int _zombie_instruction_size;
-
methodOop _method;
int _entry_bci; // != InvocationEntryBci if this nmethod is an on-stack replacement method
jmethodID _jmethod_id; // Cache of method()->jmethod_id()
@@ -147,6 +124,11 @@ class nmethod : public CodeBlob {
AbstractCompiler* _compiler; // The compiler which compiled this nmethod
+ // offsets for entry points
+ address _entry_point; // entry point with class check
+ address _verified_entry_point; // entry point without class check
+ address _osr_entry_point; // entry point for on stack replacement
+
// Offsets for different nmethod parts
int _exception_offset;
// All deoptee's will resume execution at this location described by
@@ -175,23 +157,31 @@ class nmethod : public CodeBlob {
// pc during a deopt.
int _orig_pc_offset;
- int _compile_id; // which compilation made this nmethod
- int _comp_level; // compilation level
+ int _compile_id; // which compilation made this nmethod
+ int _comp_level; // compilation level
- // offsets for entry points
- address _entry_point; // entry point with class check
- address _verified_entry_point; // entry point without class check
- address _osr_entry_point; // entry point for on stack replacement
+ // protected by CodeCache_lock
+ bool _has_flushed_dependencies; // Used for maintenance of dependencies (CodeCache_lock)
+ bool _speculatively_disconnected; // Marked for potential unload
+
+ bool _marked_for_reclamation; // Used by NMethodSweeper (set only by sweeper)
+ bool _marked_for_deoptimization; // Used for stack deoptimization
+
+ // used by jvmti to track if an unload event has been posted for this nmethod.
+ bool _unload_reported;
+
+ // set during construction
+ unsigned int _has_unsafe_access:1; // May fault due to unsafe access.
+ unsigned int _has_method_handle_invokes:1; // Has this method MethodHandle invokes?
+
+ // Protected by Patching_lock
+ unsigned char _state; // {alive, not_entrant, zombie, unloaded)
- nmFlags flags; // various flags to keep track of nmethod state
- bool _markedForDeoptimization; // Used for stack deoptimization
enum { alive = 0,
not_entrant = 1, // uncommon trap has happened but activations may still exist
zombie = 2,
unloaded = 3 };
- // used by jvmti to track if an unload event has been posted for this nmethod.
- bool _unload_reported;
jbyte _scavenge_root_state;
@@ -270,15 +260,15 @@ class nmethod : public CodeBlob {
bool make_not_entrant_or_zombie(unsigned int state);
void inc_decompile_count();
- // used to check that writes to nmFlags are done consistently.
- static void check_safepoint() PRODUCT_RETURN;
-
// Used to manipulate the exception cache
void add_exception_cache_entry(ExceptionCache* new_entry);
ExceptionCache* exception_cache_entry_for_exception(Handle exception);
// Inform external interfaces that a compiled method has been unloaded
- inline void post_compiled_method_unload();
+ void post_compiled_method_unload();
+
+ // Initailize fields to their default values
+ void init_defaults();
public:
// create nmethod with entry_bci
@@ -393,11 +383,11 @@ class nmethod : public CodeBlob {
address verified_entry_point() const { return _verified_entry_point; } // if klass is correct
// flag accessing and manipulation
- bool is_in_use() const { return flags.state == alive; }
- bool is_alive() const { return flags.state == alive || flags.state == not_entrant; }
- bool is_not_entrant() const { return flags.state == not_entrant; }
- bool is_zombie() const { return flags.state == zombie; }
- bool is_unloaded() const { return flags.state == unloaded; }
+ bool is_in_use() const { return _state == alive; }
+ bool is_alive() const { return _state == alive || _state == not_entrant; }
+ bool is_not_entrant() const { return _state == not_entrant; }
+ bool is_zombie() const { return _state == zombie; }
+ bool is_unloaded() const { return _state == unloaded; }
// Make the nmethod non entrant. The nmethod will continue to be
// alive. It is used when an uncommon trap happens. Returns true
@@ -410,37 +400,33 @@ class nmethod : public CodeBlob {
bool unload_reported() { return _unload_reported; }
void set_unload_reported() { _unload_reported = true; }
- bool is_marked_for_deoptimization() const { return _markedForDeoptimization; }
- void mark_for_deoptimization() { _markedForDeoptimization = true; }
+ bool is_marked_for_deoptimization() const { return _marked_for_deoptimization; }
+ void mark_for_deoptimization() { _marked_for_deoptimization = true; }
void make_unloaded(BoolObjectClosure* is_alive, oop cause);
bool has_dependencies() { return dependencies_size() != 0; }
void flush_dependencies(BoolObjectClosure* is_alive);
- bool has_flushed_dependencies() { return flags.hasFlushedDependencies; }
- void set_has_flushed_dependencies() {
+ bool has_flushed_dependencies() { return _has_flushed_dependencies; }
+ void set_has_flushed_dependencies() {
assert(!has_flushed_dependencies(), "should only happen once");
- flags.hasFlushedDependencies = 1;
+ _has_flushed_dependencies = 1;
}
- bool is_marked_for_reclamation() const { return flags.markedForReclamation; }
- void mark_for_reclamation() { flags.markedForReclamation = 1; }
- void unmark_for_reclamation() { flags.markedForReclamation = 0; }
+ bool is_marked_for_reclamation() const { return _marked_for_reclamation; }
+ void mark_for_reclamation() { _marked_for_reclamation = 1; }
- bool has_unsafe_access() const { return flags.has_unsafe_access; }
- void set_has_unsafe_access(bool z) { flags.has_unsafe_access = z; }
+ bool has_unsafe_access() const { return _has_unsafe_access; }
+ void set_has_unsafe_access(bool z) { _has_unsafe_access = z; }
- bool has_method_handle_invokes() const { return flags.has_method_handle_invokes; }
- void set_has_method_handle_invokes(bool z) { flags.has_method_handle_invokes = z; }
+ bool has_method_handle_invokes() const { return _has_method_handle_invokes; }
+ void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; }
- bool is_speculatively_disconnected() const { return flags.speculatively_disconnected; }
- void set_speculatively_disconnected(bool z) { flags.speculatively_disconnected = z; }
+ bool is_speculatively_disconnected() const { return _speculatively_disconnected; }
+ void set_speculatively_disconnected(bool z) { _speculatively_disconnected = z; }
int comp_level() const { return _comp_level; }
- int version() const { return flags.version; }
- void set_version(int v);
-
// Support for oops in scopes and relocs:
// Note: index 0 is reserved for null.
oop oop_at(int index) const { return index == 0 ? (oop) NULL: *oop_addr_at(index); }
diff --git a/src/share/vm/code/vtableStubs.cpp b/src/share/vm/code/vtableStubs.cpp
index 2b1e3b356..3a4c5e536 100644
--- a/src/share/vm/code/vtableStubs.cpp
+++ b/src/share/vm/code/vtableStubs.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,6 @@ void* VtableStub::operator new(size_t size, int code_size) {
}
_chunk = blob->instructions_begin();
_chunk_end = _chunk + bytes;
- VTune::register_stub("vtable stub", _chunk, _chunk_end);
Forte::register_stub("vtable stub", _chunk, _chunk_end);
// Notify JVMTI about this stub. The event will be recorded by the enclosing
// JvmtiDynamicCodeEventCollector and posted when this thread has released
diff --git a/src/share/vm/includeDB_core b/src/share/vm/includeDB_core
index c62eace8c..06d1217fe 100644
--- a/src/share/vm/includeDB_core
+++ b/src/share/vm/includeDB_core
@@ -964,7 +964,6 @@ classLoader.cpp threadService.hpp
classLoader.cpp timer.hpp
classLoader.cpp universe.inline.hpp
classLoader.cpp vmSymbols.hpp
-classLoader.cpp vtune.hpp
classLoader.hpp classFileParser.hpp
classLoader.hpp perfData.hpp
@@ -1004,7 +1003,6 @@ codeBlob.cpp relocInfo.hpp
codeBlob.cpp safepoint.hpp
codeBlob.cpp sharedRuntime.hpp
codeBlob.cpp vframe.hpp
-codeBlob.cpp vtune.hpp
codeBlob.hpp codeBuffer.hpp
codeBlob.hpp frame.hpp
@@ -2167,7 +2165,6 @@ interpreter.cpp sharedRuntime.hpp
interpreter.cpp stubRoutines.hpp
interpreter.cpp templateTable.hpp
interpreter.cpp timer.hpp
-interpreter.cpp vtune.hpp
interpreter.hpp cppInterpreter.hpp
interpreter.hpp stubs.hpp
@@ -2323,7 +2320,6 @@ java.cpp universe.hpp
java.cpp vmError.hpp
java.cpp vm_operations.hpp
java.cpp vm_version_<arch>.hpp
-java.cpp vtune.hpp
java.hpp os.hpp
@@ -3050,7 +3046,6 @@ nmethod.cpp nmethod.hpp
nmethod.cpp scopeDesc.hpp
nmethod.cpp sharedRuntime.hpp
nmethod.cpp sweeper.hpp
-nmethod.cpp vtune.hpp
nmethod.cpp xmlstream.hpp
nmethod.hpp codeBlob.hpp
@@ -3773,7 +3768,6 @@ sharedRuntime.cpp vframeArray.hpp
sharedRuntime.cpp vmSymbols.hpp
sharedRuntime.cpp vmreg_<arch>.inline.hpp
sharedRuntime.cpp vtableStubs.hpp
-sharedRuntime.cpp vtune.hpp
sharedRuntime.cpp xmlstream.hpp
sharedRuntime.hpp allocation.hpp
@@ -3937,7 +3931,6 @@ stubCodeGenerator.cpp disassembler.hpp
stubCodeGenerator.cpp forte.hpp
stubCodeGenerator.cpp oop.inline.hpp
stubCodeGenerator.cpp stubCodeGenerator.hpp
-stubCodeGenerator.cpp vtune.hpp
stubCodeGenerator.hpp allocation.hpp
stubCodeGenerator.hpp assembler.hpp
@@ -4458,7 +4451,6 @@ universe.cpp universe.hpp
universe.cpp universe.inline.hpp
universe.cpp vmSymbols.hpp
universe.cpp vm_operations.hpp
-universe.cpp vtune.hpp
universe.hpp growableArray.hpp
universe.hpp handles.hpp
@@ -4721,7 +4713,6 @@ vtableStubs.cpp mutexLocker.hpp
vtableStubs.cpp resourceArea.hpp
vtableStubs.cpp sharedRuntime.hpp
vtableStubs.cpp vtableStubs.hpp
-vtableStubs.cpp vtune.hpp
vtableStubs.hpp allocation.hpp
@@ -4735,11 +4726,6 @@ vtableStubs_<arch_model>.cpp sharedRuntime.hpp
vtableStubs_<arch_model>.cpp vmreg_<arch>.inline.hpp
vtableStubs_<arch_model>.cpp vtableStubs.hpp
-vtune.hpp allocation.hpp
-
-vtune_<os_family>.cpp interpreter.hpp
-vtune_<os_family>.cpp vtune.hpp
-
watermark.hpp allocation.hpp
watermark.hpp globalDefinitions.hpp
diff --git a/src/share/vm/interpreter/interpreter.cpp b/src/share/vm/interpreter/interpreter.cpp
index ac3876ef0..edef0fafc 100644
--- a/src/share/vm/interpreter/interpreter.cpp
+++ b/src/share/vm/interpreter/interpreter.cpp
@@ -99,11 +99,6 @@ void interpreter_init() {
#endif // PRODUCT
// need to hit every safepoint in order to call zapping routine
// register the interpreter
- VTune::register_stub(
- "Interpreter",
- AbstractInterpreter::code()->code_start(),
- AbstractInterpreter::code()->code_end()
- );
Forte::register_stub(
"Interpreter",
AbstractInterpreter::code()->code_start(),
diff --git a/src/share/vm/runtime/globals.hpp b/src/share/vm/runtime/globals.hpp
index 99d61e4da..d4f84c445 100644
--- a/src/share/vm/runtime/globals.hpp
+++ b/src/share/vm/runtime/globals.hpp
@@ -2541,9 +2541,6 @@ class CommandLineFlags {
"Enable String cache capabilities on String.java") \
\
/* statistics */ \
- develop(bool, UseVTune, false, \
- "enable support for Intel's VTune profiler") \
- \
develop(bool, CountCompiledCalls, false, \
"counts method invocations") \
\
diff --git a/src/share/vm/runtime/init.cpp b/src/share/vm/runtime/init.cpp
index 28426696b..df3a8bd46 100644
--- a/src/share/vm/runtime/init.cpp
+++ b/src/share/vm/runtime/init.cpp
@@ -34,7 +34,6 @@ void perfMemory_init();
// Initialization done by Java thread in init_globals()
void management_init();
-void vtune_init();
void bytecodes_init();
void classLoader_init();
void codeCache_init();
@@ -82,7 +81,6 @@ void vm_init_globals() {
jint init_globals() {
HandleMark hm;
management_init();
- vtune_init();
bytecodes_init();
classLoader_init();
codeCache_init();
diff --git a/src/share/vm/runtime/java.cpp b/src/share/vm/runtime/java.cpp
index cb4f7c007..76048dcda 100644
--- a/src/share/vm/runtime/java.cpp
+++ b/src/share/vm/runtime/java.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -432,8 +432,6 @@ void before_exit(JavaThread * thread) {
print_statistics();
Universe::heap()->print_tracing_info();
- VTune::exit();
-
{ MutexLocker ml(BeforeExit_lock);
_before_exit_status = BEFORE_EXIT_DONE;
BeforeExit_lock->notify_all();
diff --git a/src/share/vm/runtime/sharedRuntime.cpp b/src/share/vm/runtime/sharedRuntime.cpp
index 3118e7ca9..a059585ce 100644
--- a/src/share/vm/runtime/sharedRuntime.cpp
+++ b/src/share/vm/runtime/sharedRuntime.cpp
@@ -2251,7 +2251,6 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(methodHandle method) {
B->name(),
fingerprint->as_string(),
B->instructions_begin());
- VTune::register_stub(blob_id, B->instructions_begin(), B->instructions_end());
Forte::register_stub(blob_id, B->instructions_begin(), B->instructions_end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
diff --git a/src/share/vm/runtime/stubCodeGenerator.cpp b/src/share/vm/runtime/stubCodeGenerator.cpp
index 5d262472b..f9983e1c1 100644
--- a/src/share/vm/runtime/stubCodeGenerator.cpp
+++ b/src/share/vm/runtime/stubCodeGenerator.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -132,7 +132,6 @@ StubCodeMark::~StubCodeMark() {
_cdesc->set_end(_cgen->assembler()->pc());
assert(StubCodeDesc::_list == _cdesc, "expected order on list");
_cgen->stub_epilog(_cdesc);
- VTune::register_stub(_cdesc->name(), _cdesc->begin(), _cdesc->end());
Forte::register_stub(_cdesc->name(), _cdesc->begin(), _cdesc->end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
diff --git a/src/share/vm/runtime/sweeper.cpp b/src/share/vm/runtime/sweeper.cpp
index fc0bc6e30..1bd109287 100644
--- a/src/share/vm/runtime/sweeper.cpp
+++ b/src/share/vm/runtime/sweeper.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,14 +27,15 @@
long NMethodSweeper::_traversals = 0; // No. of stack traversals performed
nmethod* NMethodSweeper::_current = NULL; // Current nmethod
-int NMethodSweeper::_seen = 0 ; // No. of blobs we have currently processed in current pass of CodeCache
-int NMethodSweeper::_invocations = 0; // No. of invocations left until we are completed with this pass
+int NMethodSweeper::_seen = 0 ; // No. of nmethods we have currently processed in current pass of CodeCache
+
+volatile int NMethodSweeper::_invocations = 0; // No. of invocations left until we are completed with this pass
+volatile int NMethodSweeper::_sweep_started = 0; // Whether a sweep is in progress.
jint NMethodSweeper::_locked_seen = 0;
jint NMethodSweeper::_not_entrant_seen_on_stack = 0;
bool NMethodSweeper::_rescan = false;
bool NMethodSweeper::_do_sweep = false;
-jint NMethodSweeper::_sweep_started = 0;
bool NMethodSweeper::_was_full = false;
jint NMethodSweeper::_advise_to_sweep = 0;
jlong NMethodSweeper::_last_was_full = 0;
@@ -108,23 +109,14 @@ void NMethodSweeper::scan_stacks() {
// code cache is filling up
_last_was_full = os::javaTimeMillis();
- if (PrintMethodFlushing) {
- tty->print_cr("### sweeper: Live blobs:" UINT32_FORMAT "/Free code cache:" SIZE_FORMAT " bytes, restarting compiler",
- CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- }
- if (LogCompilation && (xtty != NULL)) {
- ttyLocker ttyl;
- xtty->begin_elem("restart_compiler live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
- CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- xtty->stamp();
- xtty->end_elem();
- }
+ log_sweep("restart_compiler");
}
}
}
}
void NMethodSweeper::possibly_sweep() {
+ assert(JavaThread::current()->thread_state() == _thread_in_vm, "must run in vm mode");
if ((!MethodFlushing) || (!_do_sweep)) return;
if (_invocations > 0) {
@@ -133,32 +125,31 @@ void NMethodSweeper::possibly_sweep() {
if (old != 0) {
return;
}
- sweep_code_cache();
+ if (_invocations > 0) {
+ sweep_code_cache();
+ _invocations--;
+ }
+ _sweep_started = 0;
}
- _sweep_started = 0;
}
void NMethodSweeper::sweep_code_cache() {
#ifdef ASSERT
jlong sweep_start;
- if(PrintMethodFlushing) {
+ if (PrintMethodFlushing) {
sweep_start = os::javaTimeMillis();
}
#endif
if (PrintMethodFlushing && Verbose) {
- tty->print_cr("### Sweep at %d out of %d. Invocations left: %d", _seen, CodeCache::nof_blobs(), _invocations);
- }
-
- // We want to visit all nmethods after NmethodSweepFraction invocations.
- // If invocation is 1 we do the rest
- int todo = CodeCache::nof_blobs();
- if (_invocations > 1) {
- todo = (CodeCache::nof_blobs() - _seen) / _invocations;
+ tty->print_cr("### Sweep at %d out of %d. Invocations left: %d", _seen, CodeCache::nof_nmethods(), _invocations);
}
- // Compilers may check to sweep more often than stack scans happen,
- // don't keep trying once it is all scanned
- _invocations--;
+ // We want to visit all nmethods after NmethodSweepFraction
+ // invocations so divide the remaining number of nmethods by the
+ // remaining number of invocations. This is only an estimate since
+ // the number of nmethods changes during the sweep so the final
+ // stage must iterate until it there are no more nmethods.
+ int todo = (CodeCache::nof_nmethods() - _seen) / _invocations;
assert(!SafepointSynchronize::is_at_safepoint(), "should not be in safepoint when we get here");
assert(!CodeCache_lock->owned_by_self(), "just checking");
@@ -166,11 +157,12 @@ void NMethodSweeper::sweep_code_cache() {
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- for(int i = 0; i < todo && _current != NULL; i++) {
+ // The last invocation iterates until there are no more nmethods
+ for (int i = 0; (i < todo || _invocations == 1) && _current != NULL; i++) {
- // Since we will give up the CodeCache_lock, always skip ahead to an nmethod.
- // Other blobs can be deleted by other threads
- // Read next before we potentially delete current
+ // Since we will give up the CodeCache_lock, always skip ahead
+ // to the next nmethod. Other blobs can be deleted by other
+ // threads but nmethods are only reclaimed by the sweeper.
nmethod* next = CodeCache::next_nmethod(_current);
// Now ready to process nmethod and give up CodeCache_lock
@@ -183,6 +175,8 @@ void NMethodSweeper::sweep_code_cache() {
}
}
+ assert(_invocations > 1 || _current == NULL, "must have scanned the whole cache");
+
if (_current == NULL && !_rescan && (_locked_seen || _not_entrant_seen_on_stack)) {
// we've completed a scan without making progress but there were
// nmethods we were unable to process either because they were
@@ -201,6 +195,10 @@ void NMethodSweeper::sweep_code_cache() {
tty->print_cr("### sweeper: sweep time(%d): " INT64_FORMAT, _invocations, sweep_end - sweep_start);
}
#endif
+
+ if (_invocations == 1) {
+ log_sweep("finished");
+ }
}
@@ -223,7 +221,7 @@ void NMethodSweeper::process_nmethod(nmethod *nm) {
if (nm->is_zombie()) {
// If it is first time, we see nmethod then we mark it. Otherwise,
// we reclame it. When we have seen a zombie method twice, we know that
- // there are no inline caches that referes to it.
+ // there are no inline caches that refer to it.
if (nm->is_marked_for_reclamation()) {
assert(!nm->is_locked_by_vm(), "must not flush locked nmethods");
if (PrintMethodFlushing && Verbose) {
@@ -320,16 +318,8 @@ void NMethodSweeper::handle_full_code_cache(bool is_full) {
jlong curr_interval = now - _last_was_full;
if (curr_interval < max_interval) {
_rescan = true;
- if (PrintMethodFlushing) {
- tty->print_cr("### handle full too often, turning off compiler");
- }
- if (LogCompilation && (xtty != NULL)) {
- ttyLocker ttyl;
- xtty->begin_elem("disable_compiler flushing_interval='" UINT64_FORMAT "' live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
- curr_interval/1000, CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- xtty->stamp();
- xtty->end_elem();
- }
+ log_sweep("disable_compiler", "flushing_interval='" UINT64_FORMAT "'",
+ curr_interval/1000);
return;
}
}
@@ -349,17 +339,7 @@ void NMethodSweeper::speculative_disconnect_nmethods(bool is_full) {
if ((!was_full()) && (is_full)) {
if (!CodeCache::needs_flushing()) {
- if (PrintMethodFlushing) {
- tty->print_cr("### sweeper: Live blobs:" UINT32_FORMAT "/Free code cache:" SIZE_FORMAT " bytes, restarting compiler",
- CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- }
- if (LogCompilation && (xtty != NULL)) {
- ttyLocker ttyl;
- xtty->begin_elem("restart_compiler live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
- CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- xtty->stamp();
- xtty->end_elem();
- }
+ log_sweep("restart_compiler");
CompileBroker::set_should_compile_new_jobs(CompileBroker::run_compilation);
return;
}
@@ -368,17 +348,7 @@ void NMethodSweeper::speculative_disconnect_nmethods(bool is_full) {
// Traverse the code cache trying to dump the oldest nmethods
uint curr_max_comp_id = CompileBroker::get_compilation_id();
uint flush_target = ((curr_max_comp_id - _highest_marked) >> 1) + _highest_marked;
- if (PrintMethodFlushing && Verbose) {
- tty->print_cr("### Cleaning code cache: Live blobs:" UINT32_FORMAT "/Free code cache:" SIZE_FORMAT " bytes",
- CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- }
- if (LogCompilation && (xtty != NULL)) {
- ttyLocker ttyl;
- xtty->begin_elem("start_cleaning_code_cache live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
- CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- xtty->stamp();
- xtty->end_elem();
- }
+ log_sweep("start_cleaning");
nmethod* nm = CodeCache::alive_nmethod(CodeCache::first());
jint disconnected = 0;
@@ -411,13 +381,9 @@ void NMethodSweeper::speculative_disconnect_nmethods(bool is_full) {
nm = CodeCache::alive_nmethod(CodeCache::next(nm));
}
- if (LogCompilation && (xtty != NULL)) {
- ttyLocker ttyl;
- xtty->begin_elem("stop_cleaning_code_cache disconnected='" UINT32_FORMAT "' made_not_entrant='" UINT32_FORMAT "' live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
- disconnected, made_not_entrant, CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
- xtty->stamp();
- xtty->end_elem();
- }
+ log_sweep("stop_cleaning",
+ "disconnected='" UINT32_FORMAT "' made_not_entrant='" UINT32_FORMAT "'",
+ disconnected, made_not_entrant);
// Shut off compiler. Sweeper will start over with a new stack scan and
// traversal cycle and turn it back on if it clears enough space.
@@ -435,3 +401,38 @@ void NMethodSweeper::speculative_disconnect_nmethods(bool is_full) {
}
#endif
}
+
+
+// Print out some state information about the current sweep and the
+// state of the code cache if it's requested.
+void NMethodSweeper::log_sweep(const char* msg, const char* format, ...) {
+ if (PrintMethodFlushing) {
+ ttyLocker ttyl;
+ tty->print("### sweeper: %s ", msg);
+ if (format != NULL) {
+ va_list ap;
+ va_start(ap, format);
+ tty->vprint(format, ap);
+ va_end(ap);
+ }
+ tty->print_cr(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'"
+ " adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
+ CodeCache::nof_blobs(), CodeCache::nof_nmethods(), CodeCache::nof_adapters(), CodeCache::unallocated_capacity());
+ }
+
+ if (LogCompilation && (xtty != NULL)) {
+ ttyLocker ttyl;
+ xtty->begin_elem("sweeper state='%s' traversals=`" INTX_FORMAT "' ", msg, (intx)traversal_count());
+ if (format != NULL) {
+ va_list ap;
+ va_start(ap, format);
+ xtty->vprint(format, ap);
+ va_end(ap);
+ }
+ xtty->print(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'"
+ " adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
+ CodeCache::nof_blobs(), CodeCache::nof_nmethods(), CodeCache::nof_adapters(), CodeCache::unallocated_capacity());
+ xtty->stamp();
+ xtty->end_elem();
+ }
+}
diff --git a/src/share/vm/runtime/sweeper.hpp b/src/share/vm/runtime/sweeper.hpp
index 19ae03a34..fd375fa2d 100644
--- a/src/share/vm/runtime/sweeper.hpp
+++ b/src/share/vm/runtime/sweeper.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,12 +31,13 @@ class NMethodSweeper : public AllStatic {
static long _traversals; // Stack traversal count
static nmethod* _current; // Current nmethod
static int _seen; // Nof. nmethod we have currently processed in current pass of CodeCache
- static int _invocations; // No. of invocations left until we are completed with this pass
+
+ static volatile int _invocations; // No. of invocations left until we are completed with this pass
+ static volatile int _sweep_started; // Flag to control conc sweeper
static bool _rescan; // Indicates that we should do a full rescan of the
// of the code cache looking for work to do.
static bool _do_sweep; // Flag to skip the conc sweep if no stack scan happened
- static jint _sweep_started; // Flag to control conc sweeper
static int _locked_seen; // Number of locked nmethods encountered during the scan
static int _not_entrant_seen_on_stack; // Number of not entrant nmethod were are still on stack
@@ -47,6 +48,9 @@ class NMethodSweeper : public AllStatic {
static long _was_full_traversal; // trav number at last emergency unloading
static void process_nmethod(nmethod *nm);
+
+ static void log_sweep(const char* msg, const char* format = NULL, ...);
+
public:
static long traversal_count() { return _traversals; }
diff --git a/src/share/vm/runtime/vmStructs.cpp b/src/share/vm/runtime/vmStructs.cpp
index 05ccdb991..78f676e9c 100644
--- a/src/share/vm/runtime/vmStructs.cpp
+++ b/src/share/vm/runtime/vmStructs.cpp
@@ -614,7 +614,6 @@ static inline uint64_t cast_uint64_t(size_t x)
/* NMethods (NOTE: incomplete, but only a little) */ \
/**************************************************/ \
\
- static_field(nmethod, _zombie_instruction_size, int) \
nonstatic_field(nmethod, _method, methodOop) \
nonstatic_field(nmethod, _entry_bci, int) \
nonstatic_field(nmethod, _osr_link, nmethod*) \
diff --git a/src/share/vm/runtime/vtune.hpp b/src/share/vm/runtime/vtune.hpp
deleted file mode 100644
index fcdef5355..000000000
--- a/src/share/vm/runtime/vtune.hpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-// Interface to Intel's VTune profiler.
-
-class VTune : AllStatic {
- public:
- static void create_nmethod(nmethod* nm); // register newly created nmethod
- static void delete_nmethod(nmethod* nm); // unregister nmethod before discarding it
-
- static void register_stub(const char* name, address start, address end);
- // register internal VM stub
- static void start_GC(); // start/end of GC or scavenge
- static void end_GC();
-
- static void start_class_load(); // start/end of class loading
- static void end_class_load();
-
- static void exit(); // VM exit
-};
-
-
-// helper objects
-class VTuneGCMarker : StackObj {
- public:
- VTuneGCMarker() { VTune::start_GC(); }
- ~VTuneGCMarker() { VTune::end_GC(); }
-};
-
-class VTuneClassLoadMarker : StackObj {
- public:
- VTuneClassLoadMarker() { VTune::start_class_load(); }
- ~VTuneClassLoadMarker() { VTune::end_class_load(); }
-};