8043070: nmethod::verify_interrupt_point() shouldn't enter safepoint
Summary: Introduce not_installed state for nmethods
Reviewed-by: dlong
--- a/src/hotspot/share/ci/ciEnv.cpp Mon Nov 20 17:10:02 2017 -0500
+++ b/src/hotspot/share/ci/ciEnv.cpp Mon Nov 20 19:00:22 2017 -0800
@@ -1101,6 +1101,7 @@
}
method->method_holder()->add_osr_nmethod(nm);
}
+ nm->make_in_use();
}
} // safepoints are allowed again
--- a/src/hotspot/share/code/compiledMethod.cpp Mon Nov 20 17:10:02 2017 -0500
+++ b/src/hotspot/share/code/compiledMethod.cpp Mon Nov 20 19:00:22 2017 -0800
@@ -64,6 +64,8 @@
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:
--- a/src/hotspot/share/code/compiledMethod.hpp Mon Nov 20 17:10:02 2017 -0500
+++ b/src/hotspot/share/code/compiledMethod.hpp Mon Nov 20 19:00:22 2017 -0800
@@ -183,12 +183,14 @@
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
};
--- a/src/hotspot/share/code/nmethod.cpp Mon Nov 20 17:10:02 2017 -0500
+++ b/src/hotspot/share/code/nmethod.cpp Mon Nov 20 19:00:22 2017 -0800
@@ -386,7 +386,7 @@
// 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 @@
nm->log_new_nmethod();
}
+ nm->make_in_use();
return nm;
}
@@ -1129,7 +1130,7 @@
/**
* 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_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()) &&
--- a/src/hotspot/share/code/nmethod.hpp Mon Nov 20 17:10:02 2017 -0500
+++ b/src/hotspot/share/code/nmethod.hpp Mon Nov 20 19:00:22 2017 -0800
@@ -124,7 +124,7 @@
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 @@
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 @@
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 @@
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
--- a/src/hotspot/share/jvmci/jvmciEnv.cpp Mon Nov 20 17:10:02 2017 -0500
+++ b/src/hotspot/share/jvmci/jvmciEnv.cpp Mon Nov 20 19:00:22 2017 -0800
@@ -582,6 +582,7 @@
InstanceKlass::cast(method->method_holder())->add_osr_nmethod(nm);
}
}
+ nm->make_in_use();
}
result = nm != NULL ? JVMCIEnv::ok :JVMCIEnv::cache_full;
}
--- a/src/hotspot/share/runtime/sweeper.cpp Mon Nov 20 17:10:02 2017 -0500
+++ b/src/hotspot/share/runtime/sweeper.cpp Mon Nov 20 19:00:22 2017 -0800
@@ -699,7 +699,7 @@
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
--- a/src/hotspot/share/runtime/vmStructs.cpp Mon Nov 20 17:10:02 2017 -0500
+++ b/src/hotspot/share/runtime/vmStructs.cpp Mon Nov 20 19:00:22 2017 -0800
@@ -830,7 +830,7 @@
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 @@
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) \