8043070: nmethod::verify_interrupt_point() shouldn't enter safepoint
Introduce not_installed state for nmethods Reviewed-by: dlong
This commit is contained in:
parent
61a6cba43c
commit
2811fa2e82
src/hotspot/share
@ -1101,6 +1101,7 @@ void ciEnv::register_method(ciMethod* target,
|
||||
}
|
||||
method->method_holder()->add_osr_nmethod(nm);
|
||||
}
|
||||
nm->make_in_use();
|
||||
}
|
||||
} // safepoints are allowed again
|
||||
|
||||
|
@ -64,6 +64,8 @@ bool CompiledMethod::is_method_handle_return(address return_pc) {
|
||||
const char* CompiledMethod::state() const {
|
||||
int state = get_state();
|
||||
switch (state) {
|
||||
case not_installed:
|
||||
return "not installed";
|
||||
case in_use:
|
||||
return "in use";
|
||||
case not_used:
|
||||
|
@ -183,12 +183,14 @@ public:
|
||||
bool has_wide_vectors() const { return _has_wide_vectors; }
|
||||
void set_has_wide_vectors(bool z) { _has_wide_vectors = z; }
|
||||
|
||||
enum { in_use = 0, // executable nmethod
|
||||
not_used = 1, // not entrant, but revivable
|
||||
not_entrant = 2, // marked for deoptimization but activations may still exist,
|
||||
enum { not_installed = -1, // in construction, only the owner doing the construction is
|
||||
// allowed to advance state
|
||||
in_use = 0, // executable nmethod
|
||||
not_used = 1, // not entrant, but revivable
|
||||
not_entrant = 2, // marked for deoptimization but activations may still exist,
|
||||
// will be transformed to zombie when all activations are gone
|
||||
zombie = 3, // no activations exist, nmethod is ready for purge
|
||||
unloaded = 4 // there should be no activations, should not be called,
|
||||
zombie = 3, // no activations exist, nmethod is ready for purge
|
||||
unloaded = 4 // there should be no activations, should not be called,
|
||||
// will be transformed to zombie immediately
|
||||
};
|
||||
|
||||
|
@ -386,7 +386,7 @@ const char* nmethod::compile_kind() const {
|
||||
|
||||
// Fill in default values for various flag fields
|
||||
void nmethod::init_defaults() {
|
||||
_state = in_use;
|
||||
_state = not_installed;
|
||||
_has_flushed_dependencies = 0;
|
||||
_lock_count = 0;
|
||||
_stack_traversal_mark = 0;
|
||||
@ -445,6 +445,7 @@ nmethod* nmethod::new_native_nmethod(const methodHandle& method,
|
||||
nm->log_new_nmethod();
|
||||
}
|
||||
|
||||
nm->make_in_use();
|
||||
return nm;
|
||||
}
|
||||
|
||||
@ -1129,7 +1130,7 @@ void nmethod::log_state_change() const {
|
||||
/**
|
||||
* Common functionality for both make_not_entrant and make_zombie
|
||||
*/
|
||||
bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
|
||||
bool nmethod::make_not_entrant_or_zombie(int state) {
|
||||
assert(state == zombie || state == not_entrant, "must be zombie or not_entrant");
|
||||
assert(!is_zombie(), "should not already be a zombie");
|
||||
|
||||
@ -2097,9 +2098,7 @@ void nmethod::verify() {
|
||||
|
||||
void nmethod::verify_interrupt_point(address call_site) {
|
||||
// Verify IC only when nmethod installation is finished.
|
||||
bool is_installed = (method()->code() == this) // nmethod is in state 'in_use' and installed
|
||||
|| !this->is_in_use(); // nmethod is installed, but not in 'in_use' state
|
||||
if (is_installed) {
|
||||
if (!is_not_installed()) {
|
||||
Thread *cur = Thread::current();
|
||||
if (CompiledIC_lock->owner() == cur ||
|
||||
((cur->is_VM_thread() || cur->is_ConcurrentGC_thread()) &&
|
||||
|
@ -124,7 +124,7 @@ class nmethod : public CompiledMethod {
|
||||
bool _unload_reported;
|
||||
|
||||
// Protected by Patching_lock
|
||||
volatile unsigned char _state; // {in_use, not_entrant, zombie, unloaded}
|
||||
volatile char _state; // {not_installed, in_use, not_entrant, zombie, unloaded}
|
||||
|
||||
#ifdef ASSERT
|
||||
bool _oops_are_stale; // indicates that it's no longer safe to access oops section
|
||||
@ -216,7 +216,7 @@ class nmethod : public CompiledMethod {
|
||||
const char* reloc_string_for(u_char* begin, u_char* end);
|
||||
// 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(unsigned int state);
|
||||
bool make_not_entrant_or_zombie(int state);
|
||||
bool make_entrant() { Unimplemented(); return false; }
|
||||
void inc_decompile_count();
|
||||
|
||||
@ -316,8 +316,9 @@ class nmethod : public CompiledMethod {
|
||||
address verified_entry_point() const { return _verified_entry_point; } // if klass is correct
|
||||
|
||||
// flag accessing and manipulation
|
||||
bool is_in_use() const { return _state == in_use; }
|
||||
bool is_alive() const { unsigned char s = _state; return s < zombie; }
|
||||
bool is_not_installed() const { return _state == not_installed; }
|
||||
bool is_in_use() const { return _state <= in_use; }
|
||||
bool is_alive() const { return _state < zombie; }
|
||||
bool is_not_entrant() const { return _state == not_entrant; }
|
||||
bool is_zombie() const { return _state == zombie; }
|
||||
bool is_unloaded() const { return _state == unloaded; }
|
||||
@ -328,6 +329,7 @@ class nmethod : public CompiledMethod {
|
||||
void set_rtm_state(RTMState state) { _rtm_state = state; }
|
||||
#endif
|
||||
|
||||
void make_in_use() { _state = in_use; }
|
||||
// Make the nmethod non entrant. The nmethod will continue to be
|
||||
// alive. It is used when an uncommon trap happens. Returns true
|
||||
// if this thread changed the state of the nmethod or false if
|
||||
|
@ -582,6 +582,7 @@ JVMCIEnv::CodeInstallResult JVMCIEnv::register_method(
|
||||
InstanceKlass::cast(method->method_holder())->add_osr_nmethod(nm);
|
||||
}
|
||||
}
|
||||
nm->make_in_use();
|
||||
}
|
||||
result = nm != NULL ? JVMCIEnv::ok :JVMCIEnv::cache_full;
|
||||
}
|
||||
|
@ -699,7 +699,7 @@ NMethodSweeper::MethodStateChange NMethodSweeper::process_compiled_method(Compil
|
||||
|
||||
void NMethodSweeper::possibly_flush(nmethod* nm) {
|
||||
if (UseCodeCacheFlushing) {
|
||||
if (!nm->is_locked_by_vm() && !nm->is_native_method()) {
|
||||
if (!nm->is_locked_by_vm() && !nm->is_native_method() && !nm->is_not_installed()) {
|
||||
bool make_not_entrant = false;
|
||||
|
||||
// Do not make native methods not-entrant
|
||||
|
@ -830,7 +830,7 @@ typedef PaddedEnd<ObjectMonitor> PaddedObjectMonitor;
|
||||
nonstatic_field(nmethod, _osr_link, nmethod*) \
|
||||
nonstatic_field(nmethod, _scavenge_root_link, nmethod*) \
|
||||
nonstatic_field(nmethod, _scavenge_root_state, jbyte) \
|
||||
nonstatic_field(nmethod, _state, volatile unsigned char) \
|
||||
nonstatic_field(nmethod, _state, volatile char) \
|
||||
nonstatic_field(nmethod, _exception_offset, int) \
|
||||
nonstatic_field(nmethod, _orig_pc_offset, int) \
|
||||
nonstatic_field(nmethod, _stub_offset, int) \
|
||||
@ -1351,7 +1351,7 @@ typedef PaddedEnd<ObjectMonitor> PaddedObjectMonitor;
|
||||
declare_integer_type(long) \
|
||||
declare_integer_type(char) \
|
||||
declare_unsigned_integer_type(unsigned char) \
|
||||
declare_unsigned_integer_type(volatile unsigned char) \
|
||||
declare_unsigned_integer_type(volatile char) \
|
||||
declare_unsigned_integer_type(u_char) \
|
||||
declare_unsigned_integer_type(unsigned int) \
|
||||
declare_unsigned_integer_type(uint) \
|
||||
|
Loading…
x
Reference in New Issue
Block a user