提交 c8a1c782 编写于 作者: N never

5057818: codecache full and compiler disabled in bigapps fastdebug run

Reviewed-by: kvn
上级 aac75d6f
...@@ -414,9 +414,8 @@ int nmethod::total_size() const { ...@@ -414,9 +414,8 @@ int nmethod::total_size() const {
} }
const char* nmethod::compile_kind() const { const char* nmethod::compile_kind() const {
if (method() == NULL) return "unloaded";
if (is_native_method()) return "c2n";
if (is_osr_method()) return "osr"; if (is_osr_method()) return "osr";
if (method() != NULL && is_native_method()) return "c2n";
return NULL; return NULL;
} }
...@@ -1127,6 +1126,9 @@ void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) { ...@@ -1127,6 +1126,9 @@ void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) {
} }
flags.state = unloaded; flags.state = unloaded;
// Log the unloading.
log_state_change();
// The methodOop is gone at this point // The methodOop is gone at this point
assert(_method == NULL, "Tautology"); assert(_method == NULL, "Tautology");
...@@ -1137,8 +1139,6 @@ void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) { ...@@ -1137,8 +1139,6 @@ void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) {
void nmethod::invalidate_osr_method() { void nmethod::invalidate_osr_method() {
assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod"); assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod");
if (_entry_bci != InvalidOSREntryBci)
inc_decompile_count();
// Remove from list of active nmethods // Remove from list of active nmethods
if (method() != NULL) if (method() != NULL)
instanceKlass::cast(method()->method_holder())->remove_osr_nmethod(this); instanceKlass::cast(method()->method_holder())->remove_osr_nmethod(this);
...@@ -1146,59 +1146,63 @@ void nmethod::invalidate_osr_method() { ...@@ -1146,59 +1146,63 @@ void nmethod::invalidate_osr_method() {
_entry_bci = InvalidOSREntryBci; _entry_bci = InvalidOSREntryBci;
} }
void nmethod::log_state_change(int state) const { void nmethod::log_state_change() const {
if (LogCompilation) { if (LogCompilation) {
if (xtty != NULL) { if (xtty != NULL) {
ttyLocker ttyl; // keep the following output all in one block ttyLocker ttyl; // keep the following output all in one block
xtty->begin_elem("make_not_entrant %sthread='" UINTX_FORMAT "'", if (flags.state == unloaded) {
(state == zombie ? "zombie='1' " : ""), xtty->begin_elem("make_unloaded thread='" UINTX_FORMAT "'",
os::current_thread_id()); os::current_thread_id());
} else {
xtty->begin_elem("make_not_entrant thread='" UINTX_FORMAT "'%s",
os::current_thread_id(),
(flags.state == zombie ? " zombie='1'" : ""));
}
log_identity(xtty); log_identity(xtty);
xtty->stamp(); xtty->stamp();
xtty->end_elem(); xtty->end_elem();
} }
} }
if (PrintCompilation) { if (PrintCompilation && flags.state != unloaded) {
print_on(tty, state == zombie ? "made zombie " : "made not entrant "); print_on(tty, flags.state == zombie ? "made zombie " : "made not entrant ");
tty->cr(); tty->cr();
} }
} }
// Common functionality for both make_not_entrant and make_zombie // Common functionality for both make_not_entrant and make_zombie
void nmethod::make_not_entrant_or_zombie(int state) { bool nmethod::make_not_entrant_or_zombie(int state) {
assert(state == zombie || state == not_entrant, "must be zombie or not_entrant"); assert(state == zombie || state == not_entrant, "must be zombie or not_entrant");
// Code for an on-stack-replacement nmethod is removed when a class gets unloaded. // If the method is already zombie there is nothing to do
// They never become zombie/non-entrant, so the nmethod sweeper will never remove if (is_zombie()) {
// them. Instead the entry_bci is set to InvalidOSREntryBci, so the osr nmethod return false;
// will never be used anymore. That the nmethods only gets removed when class unloading
// happens, make life much simpler, since the nmethods are not just going to disappear
// out of the blue.
if (is_osr_method()) {
if (osr_entry_bci() != InvalidOSREntryBci) {
// only log this once
log_state_change(state);
}
invalidate_osr_method();
return;
}
// If the method is already zombie or set to the state we want, nothing to do
if (is_zombie() || (state == not_entrant && is_not_entrant())) {
return;
} }
log_state_change(state);
// Make sure the nmethod is not flushed in case of a safepoint in code below. // Make sure the nmethod is not flushed in case of a safepoint in code below.
nmethodLocker nml(this); nmethodLocker nml(this);
{ {
// invalidate osr nmethod before acquiring the patching lock since
// they both acquire leaf locks and we don't want a deadlock.
// This logic is equivalent to the logic below for patching the
// verified entry point of regular methods.
if (is_osr_method()) {
// this effectively makes the osr nmethod not entrant
invalidate_osr_method();
}
// Enter critical section. Does not block for safepoint. // Enter critical section. Does not block for safepoint.
MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag); MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
if (flags.state == state) {
// another thread already performed this transition so nothing
// to do, but return false to indicate this.
return false;
}
// The caller can be calling the method statically or through an inline // The caller can be calling the method statically or through an inline
// cache call. // cache call.
if (!is_not_entrant()) { if (!is_osr_method() && !is_not_entrant()) {
NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
SharedRuntime::get_handle_wrong_method_stub()); SharedRuntime::get_handle_wrong_method_stub());
assert (NativeJump::instruction_size == nmethod::_zombie_instruction_size, ""); assert (NativeJump::instruction_size == nmethod::_zombie_instruction_size, "");
...@@ -1217,6 +1221,10 @@ void nmethod::make_not_entrant_or_zombie(int state) { ...@@ -1217,6 +1221,10 @@ void nmethod::make_not_entrant_or_zombie(int state) {
// Change state // Change state
flags.state = state; flags.state = state;
// Log the transition once
log_state_change();
} // leave critical region under Patching_lock } // leave critical region under Patching_lock
if (state == not_entrant) { if (state == not_entrant) {
...@@ -1240,7 +1248,6 @@ void nmethod::make_not_entrant_or_zombie(int state) { ...@@ -1240,7 +1248,6 @@ void nmethod::make_not_entrant_or_zombie(int state) {
// It's a true state change, so mark the method as decompiled. // It's a true state change, so mark the method as decompiled.
inc_decompile_count(); inc_decompile_count();
// zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event // 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. // 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). // (the event may have been reported earilier if the GC marked it for unloading).
...@@ -1268,7 +1275,7 @@ void nmethod::make_not_entrant_or_zombie(int state) { ...@@ -1268,7 +1275,7 @@ void nmethod::make_not_entrant_or_zombie(int state) {
// Check whether method got unloaded at a safepoint before this, // Check whether method got unloaded at a safepoint before this,
// if so we can skip the flushing steps below // if so we can skip the flushing steps below
if (method() == NULL) return; if (method() == NULL) return true;
// Remove nmethod from method. // Remove nmethod from method.
// We need to check if both the _code and _from_compiled_code_entry_point // We need to check if both the _code and _from_compiled_code_entry_point
...@@ -1282,6 +1289,8 @@ void nmethod::make_not_entrant_or_zombie(int state) { ...@@ -1282,6 +1289,8 @@ void nmethod::make_not_entrant_or_zombie(int state) {
HandleMark hm; HandleMark hm;
method()->clear_code(); method()->clear_code();
} }
return true;
} }
......
...@@ -252,7 +252,9 @@ class nmethod : public CodeBlob { ...@@ -252,7 +252,9 @@ class nmethod : public CodeBlob {
void* operator new(size_t size, int nmethod_size); void* operator new(size_t size, int nmethod_size);
const char* reloc_string_for(u_char* begin, u_char* end); const char* reloc_string_for(u_char* begin, u_char* end);
void make_not_entrant_or_zombie(int state); // Returns true if this thread changed the state of the nmethod or
// false if another thread performed the transition.
bool make_not_entrant_or_zombie(int state);
void inc_decompile_count(); void inc_decompile_count();
// used to check that writes to nmFlags are done consistently. // used to check that writes to nmFlags are done consistently.
...@@ -375,10 +377,12 @@ class nmethod : public CodeBlob { ...@@ -375,10 +377,12 @@ class nmethod : public CodeBlob {
bool is_zombie() const { return flags.state == zombie; } bool is_zombie() const { return flags.state == zombie; }
bool is_unloaded() const { return flags.state == unloaded; } bool is_unloaded() const { return flags.state == unloaded; }
// Make the nmethod non entrant. The nmethod will continue to be alive. // Make the nmethod non entrant. The nmethod will continue to be
// It is used when an uncommon trap happens. // alive. It is used when an uncommon trap happens. Returns true
void make_not_entrant() { make_not_entrant_or_zombie(not_entrant); } // if this thread changed the state of the nmethod or false if
void make_zombie() { make_not_entrant_or_zombie(zombie); } // another thread performed the transition.
bool make_not_entrant() { return make_not_entrant_or_zombie(not_entrant); }
bool make_zombie() { return make_not_entrant_or_zombie(zombie); }
// used by jvmti to track if the unload event has been reported // used by jvmti to track if the unload event has been reported
bool unload_reported() { return _unload_reported; } bool unload_reported() { return _unload_reported; }
...@@ -563,7 +567,7 @@ class nmethod : public CodeBlob { ...@@ -563,7 +567,7 @@ class nmethod : public CodeBlob {
// Logging // Logging
void log_identity(xmlStream* log) const; void log_identity(xmlStream* log) const;
void log_new_nmethod() const; void log_new_nmethod() const;
void log_state_change(int state) const; void log_state_change() const;
// Prints a comment for one native instruction (reloc info, pc desc) // Prints a comment for one native instruction (reloc info, pc desc)
void print_code_comment_on(outputStream* st, int column, address begin, address end); void print_code_comment_on(outputStream* st, int column, address begin, address end);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册