mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8188102: [JVMCI] Convert special JVMCI oops in nmethod to jweak values
Reviewed-by: never, kvn, kbarrett
This commit is contained in:
parent
67b21ffa1d
commit
f37bbe430d
13 changed files with 146 additions and 216 deletions
|
@ -1,18 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<projectDescription>
|
|
||||||
<name>mx.jvmci</name>
|
|
||||||
<comment></comment>
|
|
||||||
<projects>
|
|
||||||
<project>mx</project>
|
|
||||||
</projects>
|
|
||||||
<buildSpec>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.python.pydev.PyDevBuilder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
</buildSpec>
|
|
||||||
<natures>
|
|
||||||
<nature>org.python.pydev.pythonNature</nature>
|
|
||||||
</natures>
|
|
||||||
</projectDescription>
|
|
|
@ -1,12 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<?eclipse-pydev version="1.0"?><pydev_project>
|
|
||||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
|
|
||||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
|
|
||||||
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
|
|
||||||
<path>/mx.jvmci</path>
|
|
||||||
</pydev_pathproperty>
|
|
||||||
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
|
|
||||||
<path>/mx</path>
|
|
||||||
</pydev_pathproperty>
|
|
||||||
|
|
||||||
</pydev_project>
|
|
|
@ -409,6 +409,7 @@ void nmethod::init_defaults() {
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
_jvmci_installed_code = NULL;
|
_jvmci_installed_code = NULL;
|
||||||
_speculation_log = NULL;
|
_speculation_log = NULL;
|
||||||
|
_jvmci_installed_code_triggers_unloading = false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,8 +462,8 @@ nmethod* nmethod::new_nmethod(const methodHandle& method,
|
||||||
AbstractCompiler* compiler,
|
AbstractCompiler* compiler,
|
||||||
int comp_level
|
int comp_level
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
, Handle installed_code,
|
, jweak installed_code,
|
||||||
Handle speculationLog
|
jweak speculationLog
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -642,8 +643,8 @@ nmethod::nmethod(
|
||||||
AbstractCompiler* compiler,
|
AbstractCompiler* compiler,
|
||||||
int comp_level
|
int comp_level
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
, Handle installed_code,
|
, jweak installed_code,
|
||||||
Handle speculation_log
|
jweak speculation_log
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
: CompiledMethod(method, "nmethod", type, nmethod_size, sizeof(nmethod), code_buffer, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps, false),
|
: CompiledMethod(method, "nmethod", type, nmethod_size, sizeof(nmethod), code_buffer, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps, false),
|
||||||
|
@ -671,8 +672,14 @@ nmethod::nmethod(
|
||||||
set_ctable_begin(header_begin() + _consts_offset);
|
set_ctable_begin(header_begin() + _consts_offset);
|
||||||
|
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
_jvmci_installed_code = installed_code();
|
_jvmci_installed_code = installed_code;
|
||||||
_speculation_log = (instanceOop)speculation_log();
|
_speculation_log = speculation_log;
|
||||||
|
oop obj = JNIHandles::resolve(installed_code);
|
||||||
|
if (obj == NULL || (obj->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(obj))) {
|
||||||
|
_jvmci_installed_code_triggers_unloading = false;
|
||||||
|
} else {
|
||||||
|
_jvmci_installed_code_triggers_unloading = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (compiler->is_jvmci()) {
|
if (compiler->is_jvmci()) {
|
||||||
// JVMCI might not produce any stub sections
|
// JVMCI might not produce any stub sections
|
||||||
|
@ -1026,8 +1033,6 @@ void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) {
|
||||||
" unloadable, Method*(" INTPTR_FORMAT
|
" unloadable, Method*(" INTPTR_FORMAT
|
||||||
"), cause(" INTPTR_FORMAT ")",
|
"), cause(" INTPTR_FORMAT ")",
|
||||||
p2i(this), p2i(_method), p2i(cause));
|
p2i(this), p2i(_method), p2i(cause));
|
||||||
if (!Universe::heap()->is_gc_active())
|
|
||||||
cause->klass()->print_on(&ls);
|
|
||||||
}
|
}
|
||||||
// Unlink the osr method, so we do not look this up again
|
// Unlink the osr method, so we do not look this up again
|
||||||
if (is_osr_method()) {
|
if (is_osr_method()) {
|
||||||
|
@ -1077,14 +1082,8 @@ void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) {
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
// The method can only be unloaded after the pointer to the installed code
|
// The method can only be unloaded after the pointer to the installed code
|
||||||
// Java wrapper is no longer alive. Here we need to clear out this weak
|
// Java wrapper is no longer alive. Here we need to clear out this weak
|
||||||
// reference to the dead object. Nulling out the reference has to happen
|
// reference to the dead object.
|
||||||
// after the method is unregistered since the original value may be still
|
|
||||||
// tracked by the rset.
|
|
||||||
maybe_invalidate_installed_code();
|
maybe_invalidate_installed_code();
|
||||||
// Clear these out after the nmethod has been unregistered and any
|
|
||||||
// updates to the InstalledCode instance have been performed.
|
|
||||||
_jvmci_installed_code = NULL;
|
|
||||||
_speculation_log = NULL;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The Method* is gone at this point
|
// The Method* is gone at this point
|
||||||
|
@ -1246,10 +1245,6 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
|
||||||
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||||
if (nmethod_needs_unregister) {
|
if (nmethod_needs_unregister) {
|
||||||
Universe::heap()->unregister_nmethod(this);
|
Universe::heap()->unregister_nmethod(this);
|
||||||
#ifdef JVMCI
|
|
||||||
_jvmci_installed_code = NULL;
|
|
||||||
_speculation_log = NULL;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
flush_dependencies(NULL);
|
flush_dependencies(NULL);
|
||||||
}
|
}
|
||||||
|
@ -1314,6 +1309,11 @@ void nmethod::flush() {
|
||||||
CodeCache::drop_scavenge_root_nmethod(this);
|
CodeCache::drop_scavenge_root_nmethod(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if INCLUDE_JVMCI
|
||||||
|
assert(_jvmci_installed_code == NULL, "should have been nulled out when transitioned to zombie");
|
||||||
|
assert(_speculation_log == NULL, "should have been nulled out when transitioned to zombie");
|
||||||
|
#endif
|
||||||
|
|
||||||
CodeBlob::flush();
|
CodeBlob::flush();
|
||||||
CodeCache::free(this);
|
CodeCache::free(this);
|
||||||
}
|
}
|
||||||
|
@ -1500,29 +1500,18 @@ bool nmethod::do_unloading_oops(address low_boundary, BoolObjectClosure* is_aliv
|
||||||
|
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
bool nmethod::do_unloading_jvmci(BoolObjectClosure* is_alive, bool unloading_occurred) {
|
bool nmethod::do_unloading_jvmci(BoolObjectClosure* is_alive, bool unloading_occurred) {
|
||||||
bool is_unloaded = false;
|
|
||||||
// Follow JVMCI method
|
|
||||||
BarrierSet* bs = Universe::heap()->barrier_set();
|
|
||||||
if (_jvmci_installed_code != NULL) {
|
if (_jvmci_installed_code != NULL) {
|
||||||
if (_jvmci_installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(_jvmci_installed_code)) {
|
if (JNIHandles::is_global_weak_cleared(_jvmci_installed_code)) {
|
||||||
if (!is_alive->do_object_b(_jvmci_installed_code)) {
|
if (_jvmci_installed_code_triggers_unloading) {
|
||||||
|
// jweak reference processing has already cleared the referent
|
||||||
|
make_unloaded(is_alive, NULL);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
clear_jvmci_installed_code();
|
clear_jvmci_installed_code();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (can_unload(is_alive, (oop*)&_jvmci_installed_code, unloading_occurred)) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return false;
|
||||||
|
|
||||||
if (_speculation_log != NULL) {
|
|
||||||
if (!is_alive->do_object_b(_speculation_log)) {
|
|
||||||
bs->write_ref_nmethod_pre(&_speculation_log, this);
|
|
||||||
_speculation_log = NULL;
|
|
||||||
bs->write_ref_nmethod_post(&_speculation_log, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return is_unloaded;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1594,15 +1583,6 @@ void nmethod::oops_do(OopClosure* f, bool allow_zombie) {
|
||||||
// (See comment above.)
|
// (See comment above.)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if INCLUDE_JVMCI
|
|
||||||
if (_jvmci_installed_code != NULL) {
|
|
||||||
f->do_oop((oop*) &_jvmci_installed_code);
|
|
||||||
}
|
|
||||||
if (_speculation_log != NULL) {
|
|
||||||
f->do_oop((oop*) &_speculation_log);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
RelocIterator iter(this, low_boundary);
|
RelocIterator iter(this, low_boundary);
|
||||||
|
|
||||||
while (iter.next()) {
|
while (iter.next()) {
|
||||||
|
@ -2860,30 +2840,29 @@ void nmethod::print_statistics() {
|
||||||
|
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
void nmethod::clear_jvmci_installed_code() {
|
void nmethod::clear_jvmci_installed_code() {
|
||||||
// write_ref_method_pre/post can only be safely called at a
|
assert_locked_or_safepoint(Patching_lock);
|
||||||
// safepoint or while holding the CodeCache_lock
|
|
||||||
assert(CodeCache_lock->is_locked() ||
|
|
||||||
SafepointSynchronize::is_at_safepoint(), "should be performed under a lock for consistency");
|
|
||||||
if (_jvmci_installed_code != NULL) {
|
if (_jvmci_installed_code != NULL) {
|
||||||
// This must be done carefully to maintain nmethod remembered sets properly
|
JNIHandles::destroy_weak_global(_jvmci_installed_code);
|
||||||
BarrierSet* bs = Universe::heap()->barrier_set();
|
|
||||||
bs->write_ref_nmethod_pre(&_jvmci_installed_code, this);
|
|
||||||
_jvmci_installed_code = NULL;
|
_jvmci_installed_code = NULL;
|
||||||
bs->write_ref_nmethod_post(&_jvmci_installed_code, this);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nmethod::clear_speculation_log() {
|
||||||
|
assert_locked_or_safepoint(Patching_lock);
|
||||||
|
if (_speculation_log != NULL) {
|
||||||
|
JNIHandles::destroy_weak_global(_speculation_log);
|
||||||
|
_speculation_log = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nmethod::maybe_invalidate_installed_code() {
|
void nmethod::maybe_invalidate_installed_code() {
|
||||||
assert(Patching_lock->is_locked() ||
|
assert(Patching_lock->is_locked() ||
|
||||||
SafepointSynchronize::is_at_safepoint(), "should be performed under a lock for consistency");
|
SafepointSynchronize::is_at_safepoint(), "should be performed under a lock for consistency");
|
||||||
oop installed_code = jvmci_installed_code();
|
oop installed_code = JNIHandles::resolve(_jvmci_installed_code);
|
||||||
if (installed_code != NULL) {
|
if (installed_code != NULL) {
|
||||||
|
// Update the values in the InstalledCode instance if it still refers to this nmethod
|
||||||
nmethod* nm = (nmethod*)InstalledCode::address(installed_code);
|
nmethod* nm = (nmethod*)InstalledCode::address(installed_code);
|
||||||
if (nm == NULL || nm != this) {
|
if (nm == this) {
|
||||||
// The link has been broken or the InstalledCode instance is
|
|
||||||
// associated with another nmethod so do nothing.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!is_alive()) {
|
if (!is_alive()) {
|
||||||
// Break the link between nmethod and InstalledCode such that the nmethod
|
// Break the link between nmethod and InstalledCode such that the nmethod
|
||||||
// can subsequently be flushed safely. The link must be maintained while
|
// can subsequently be flushed safely. The link must be maintained while
|
||||||
|
@ -2898,6 +2877,13 @@ void nmethod::maybe_invalidate_installed_code() {
|
||||||
InstalledCode::set_entryPoint(installed_code, 0);
|
InstalledCode::set_entryPoint(installed_code, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (!is_alive()) {
|
||||||
|
// Clear these out after the nmethod has been unregistered and any
|
||||||
|
// updates to the InstalledCode instance have been performed.
|
||||||
|
clear_jvmci_installed_code();
|
||||||
|
clear_speculation_log();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nmethod::invalidate_installed_code(Handle installedCode, TRAPS) {
|
void nmethod::invalidate_installed_code(Handle installedCode, TRAPS) {
|
||||||
|
@ -2916,45 +2902,49 @@ void nmethod::invalidate_installed_code(Handle installedCode, TRAPS) {
|
||||||
{
|
{
|
||||||
MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
|
MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
|
||||||
// This relationship can only be checked safely under a lock
|
// This relationship can only be checked safely under a lock
|
||||||
assert(nm == NULL || !nm->is_alive() || nm->jvmci_installed_code() == installedCode(), "sanity check");
|
assert(!nm->is_alive() || nm->jvmci_installed_code() == installedCode(), "sanity check");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (nm->is_alive()) {
|
if (nm->is_alive()) {
|
||||||
// The nmethod state machinery maintains the link between the
|
// Invalidating the InstalledCode means we want the nmethod
|
||||||
// HotSpotInstalledCode and nmethod* so as long as the nmethod appears to be
|
// to be deoptimized.
|
||||||
// alive assume there is work to do and deoptimize the nmethod.
|
|
||||||
nm->mark_for_deoptimization();
|
nm->mark_for_deoptimization();
|
||||||
VM_Deoptimize op;
|
VM_Deoptimize op;
|
||||||
VMThread::execute(&op);
|
VMThread::execute(&op);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Multiple threads could reach this point so we now need to
|
||||||
|
// lock and re-check the link to the nmethod so that only one
|
||||||
|
// thread clears it.
|
||||||
MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
|
MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
|
||||||
// Check that it's still associated with the same nmethod and break
|
|
||||||
// the link if it is.
|
|
||||||
if (InstalledCode::address(installedCode) == nativeMethod) {
|
if (InstalledCode::address(installedCode) == nativeMethod) {
|
||||||
InstalledCode::set_address(installedCode, 0);
|
InstalledCode::set_address(installedCode, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oop nmethod::jvmci_installed_code() {
|
||||||
|
return JNIHandles::resolve(_jvmci_installed_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop nmethod::speculation_log() {
|
||||||
|
return JNIHandles::resolve(_speculation_log);
|
||||||
|
}
|
||||||
|
|
||||||
char* nmethod::jvmci_installed_code_name(char* buf, size_t buflen) {
|
char* nmethod::jvmci_installed_code_name(char* buf, size_t buflen) {
|
||||||
if (!this->is_compiled_by_jvmci()) {
|
if (!this->is_compiled_by_jvmci()) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
oop installedCode = this->jvmci_installed_code();
|
oop installed_code = JNIHandles::resolve(_jvmci_installed_code);
|
||||||
if (installedCode != NULL) {
|
if (installed_code != NULL) {
|
||||||
oop installedCodeName = NULL;
|
oop installed_code_name = NULL;
|
||||||
if (installedCode->is_a(InstalledCode::klass())) {
|
if (installed_code->is_a(InstalledCode::klass())) {
|
||||||
installedCodeName = InstalledCode::name(installedCode);
|
installed_code_name = InstalledCode::name(installed_code);
|
||||||
}
|
}
|
||||||
if (installedCodeName != NULL) {
|
if (installed_code_name != NULL) {
|
||||||
return java_lang_String::as_utf8_string(installedCodeName, buf, (int)buflen);
|
return java_lang_String::as_utf8_string(installed_code_name, buf, (int)buflen);
|
||||||
} else {
|
|
||||||
jio_snprintf(buf, buflen, "null");
|
|
||||||
return buf;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jio_snprintf(buf, buflen, "noInstalledCode");
|
return NULL;
|
||||||
return buf;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -63,9 +63,22 @@ class nmethod : public CompiledMethod {
|
||||||
jmethodID _jmethod_id; // Cache of method()->jmethod_id()
|
jmethodID _jmethod_id; // Cache of method()->jmethod_id()
|
||||||
|
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
// Needed to keep nmethods alive that are not the default nmethod for the associated Method.
|
// A weak reference to an InstalledCode object associated with
|
||||||
oop _jvmci_installed_code;
|
// this nmethod.
|
||||||
oop _speculation_log;
|
jweak _jvmci_installed_code;
|
||||||
|
|
||||||
|
// A weak reference to a SpeculationLog object associated with
|
||||||
|
// this nmethod.
|
||||||
|
jweak _speculation_log;
|
||||||
|
|
||||||
|
// Determines whether this nmethod is unloaded when the
|
||||||
|
// referent in _jvmci_installed_code is cleared. This
|
||||||
|
// will be false if the referent is initialized to a
|
||||||
|
// HotSpotNMethod object whose isDefault field is true.
|
||||||
|
// That is, installed code other than a "default"
|
||||||
|
// HotSpotNMethod causes nmethod unloading.
|
||||||
|
// This field is ignored once _jvmci_installed_code is NULL.
|
||||||
|
bool _jvmci_installed_code_triggers_unloading;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// To support simple linked-list chaining of nmethods:
|
// To support simple linked-list chaining of nmethods:
|
||||||
|
@ -192,8 +205,8 @@ class nmethod : public CompiledMethod {
|
||||||
AbstractCompiler* compiler,
|
AbstractCompiler* compiler,
|
||||||
int comp_level
|
int comp_level
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
, Handle installed_code,
|
, jweak installed_code,
|
||||||
Handle speculation_log
|
jweak speculation_log
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -236,8 +249,8 @@ class nmethod : public CompiledMethod {
|
||||||
AbstractCompiler* compiler,
|
AbstractCompiler* compiler,
|
||||||
int comp_level
|
int comp_level
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
, Handle installed_code = Handle(),
|
, jweak installed_code = NULL,
|
||||||
Handle speculation_log = Handle()
|
jweak speculation_log = NULL
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -433,27 +446,46 @@ public:
|
||||||
void set_method(Method* method) { _method = method; }
|
void set_method(Method* method) { _method = method; }
|
||||||
|
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
oop jvmci_installed_code() { return _jvmci_installed_code ; }
|
// Gets the InstalledCode object associated with this nmethod
|
||||||
|
// which may be NULL if this nmethod was not compiled by JVMCI
|
||||||
|
// or the weak reference has been cleared.
|
||||||
|
oop jvmci_installed_code();
|
||||||
|
|
||||||
|
// Copies the value of the name field in the InstalledCode
|
||||||
|
// object (if any) associated with this nmethod into buf.
|
||||||
|
// Returns the value of buf if it was updated otherwise NULL.
|
||||||
char* jvmci_installed_code_name(char* buf, size_t buflen);
|
char* jvmci_installed_code_name(char* buf, size_t buflen);
|
||||||
|
|
||||||
// Update the state of any InstalledCode instance associated with
|
// Updates the state of the InstalledCode (if any) associated with
|
||||||
// this nmethod based on the current value of _state.
|
// this nmethod based on the current value of _state.
|
||||||
void maybe_invalidate_installed_code();
|
void maybe_invalidate_installed_code();
|
||||||
|
|
||||||
// Helper function to invalidate InstalledCode instances
|
// Deoptimizes the nmethod (if any) in the address field of a given
|
||||||
|
// InstalledCode object. The address field is zeroed upon return.
|
||||||
static void invalidate_installed_code(Handle installed_code, TRAPS);
|
static void invalidate_installed_code(Handle installed_code, TRAPS);
|
||||||
|
|
||||||
oop speculation_log() { return _speculation_log ; }
|
// Gets the SpeculationLog object associated with this nmethod
|
||||||
|
// which may be NULL if this nmethod was not compiled by JVMCI
|
||||||
|
// or the weak reference has been cleared.
|
||||||
|
oop speculation_log();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Deletes the weak reference (if any) to the InstalledCode object
|
||||||
|
// associated with this nmethod.
|
||||||
void clear_jvmci_installed_code();
|
void clear_jvmci_installed_code();
|
||||||
|
|
||||||
|
// Deletes the weak reference (if any) to the SpeculationLog object
|
||||||
|
// associated with this nmethod.
|
||||||
|
void clear_speculation_log();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool do_unloading_oops(address low_boundary, BoolObjectClosure* is_alive, bool unloading_occurred);
|
virtual bool do_unloading_oops(address low_boundary, BoolObjectClosure* is_alive, bool unloading_occurred);
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
|
// See comment for _jvmci_installed_code_triggers_unloading field.
|
||||||
|
// Returns whether this nmethod was unloaded.
|
||||||
virtual bool do_unloading_jvmci(BoolObjectClosure* is_alive, bool unloading_occurred);
|
virtual bool do_unloading_jvmci(BoolObjectClosure* is_alive, bool unloading_occurred);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -214,52 +214,3 @@ G1SATBCardTableLoggingModRefBS::invalidate(MemRegion mr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1SATBCardTableModRefBS::write_ref_nmethod_post(oop* dst, nmethod* nm) {
|
|
||||||
oop obj = oopDesc::load_heap_oop(dst);
|
|
||||||
if (obj != NULL) {
|
|
||||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
|
||||||
HeapRegion* hr = g1h->heap_region_containing(obj);
|
|
||||||
hr->add_strong_code_root(nm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class G1EnsureLastRefToRegion : public OopClosure {
|
|
||||||
G1CollectedHeap* _g1h;
|
|
||||||
HeapRegion* _hr;
|
|
||||||
oop* _dst;
|
|
||||||
|
|
||||||
bool _value;
|
|
||||||
public:
|
|
||||||
G1EnsureLastRefToRegion(G1CollectedHeap* g1h, HeapRegion* hr, oop* dst) :
|
|
||||||
_g1h(g1h), _hr(hr), _dst(dst), _value(true) {}
|
|
||||||
|
|
||||||
void do_oop(oop* p) {
|
|
||||||
if (_value && p != _dst) {
|
|
||||||
oop obj = oopDesc::load_heap_oop(p);
|
|
||||||
if (obj != NULL) {
|
|
||||||
HeapRegion* hr = _g1h->heap_region_containing(obj);
|
|
||||||
if (hr == _hr) {
|
|
||||||
// Another reference to the same region.
|
|
||||||
_value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void do_oop(narrowOop* p) { ShouldNotReachHere(); }
|
|
||||||
bool value() const { return _value; }
|
|
||||||
};
|
|
||||||
|
|
||||||
void G1SATBCardTableModRefBS::write_ref_nmethod_pre(oop* dst, nmethod* nm) {
|
|
||||||
oop obj = oopDesc::load_heap_oop(dst);
|
|
||||||
if (obj != NULL) {
|
|
||||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
|
||||||
HeapRegion* hr = g1h->heap_region_containing(obj);
|
|
||||||
G1EnsureLastRefToRegion ensure_last_ref(g1h, hr, dst);
|
|
||||||
nm->oops_do(&ensure_last_ref);
|
|
||||||
if (ensure_last_ref.value()) {
|
|
||||||
// Last reference to this region, remove the nmethod from the rset.
|
|
||||||
hr->remove_strong_code_root(nm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -95,9 +95,6 @@ public:
|
||||||
jbyte val = _byte_map[card_index];
|
jbyte val = _byte_map[card_index];
|
||||||
return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val();
|
return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val();
|
||||||
}
|
}
|
||||||
virtual void write_ref_nmethod_pre(oop* dst, nmethod* nm);
|
|
||||||
virtual void write_ref_nmethod_post(oop* dst, nmethod* nm);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
|
@ -120,9 +120,6 @@ public:
|
||||||
static void static_write_ref_array_pre(HeapWord* start, size_t count);
|
static void static_write_ref_array_pre(HeapWord* start, size_t count);
|
||||||
static void static_write_ref_array_post(HeapWord* start, size_t count);
|
static void static_write_ref_array_post(HeapWord* start, size_t count);
|
||||||
|
|
||||||
virtual void write_ref_nmethod_pre(oop* dst, nmethod* nm) {}
|
|
||||||
virtual void write_ref_nmethod_post(oop* dst, nmethod* nm) {}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void write_ref_array_work(MemRegion mr) = 0;
|
virtual void write_ref_array_work(MemRegion mr) = 0;
|
||||||
|
|
||||||
|
|
|
@ -1039,7 +1039,7 @@ C2V_VMENTRY(jint, installCode, (JNIEnv *jniEnv, jobject, jobject target, jobject
|
||||||
if (result != JVMCIEnv::ok) {
|
if (result != JVMCIEnv::ok) {
|
||||||
assert(cb == NULL, "should be");
|
assert(cb == NULL, "should be");
|
||||||
} else {
|
} else {
|
||||||
if (!installed_code_handle.is_null()) {
|
if (installed_code_handle.not_null()) {
|
||||||
assert(installed_code_handle->is_a(InstalledCode::klass()), "wrong type");
|
assert(installed_code_handle->is_a(InstalledCode::klass()), "wrong type");
|
||||||
nmethod::invalidate_installed_code(installed_code_handle, CHECK_0);
|
nmethod::invalidate_installed_code(installed_code_handle, CHECK_0);
|
||||||
{
|
{
|
||||||
|
@ -1058,13 +1058,6 @@ C2V_VMENTRY(jint, installCode, (JNIEnv *jniEnv, jobject, jobject target, jobject
|
||||||
HotSpotInstalledCode::set_codeSize(installed_code_handle, cb->code_size());
|
HotSpotInstalledCode::set_codeSize(installed_code_handle, cb->code_size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nmethod* nm = cb->as_nmethod_or_null();
|
|
||||||
if (nm != NULL && installed_code_handle->is_scavengable()) {
|
|
||||||
assert(nm->detect_scavenge_root_oops(), "nm should be scavengable if installed_code is scavengable");
|
|
||||||
if (!UseG1GC) {
|
|
||||||
assert(nm->on_scavenge_root_list(), "nm should be on scavengable list");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -521,7 +521,9 @@ JVMCIEnv::CodeInstallResult JVMCIEnv::register_method(
|
||||||
debug_info, dependencies, code_buffer,
|
debug_info, dependencies, code_buffer,
|
||||||
frame_words, oop_map_set,
|
frame_words, oop_map_set,
|
||||||
handler_table, &implicit_tbl,
|
handler_table, &implicit_tbl,
|
||||||
compiler, comp_level, installed_code, speculation_log);
|
compiler, comp_level,
|
||||||
|
JNIHandles::make_weak_global(installed_code),
|
||||||
|
JNIHandles::make_weak_global(speculation_log));
|
||||||
|
|
||||||
// Free codeBlobs
|
// Free codeBlobs
|
||||||
//code_buffer->free_blob();
|
//code_buffer->free_blob();
|
||||||
|
|
|
@ -1674,19 +1674,9 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* thread, jint tra
|
||||||
tty->print(" compiler=%s compile_id=%d", nm->compiler_name(), nm->compile_id());
|
tty->print(" compiler=%s compile_id=%d", nm->compiler_name(), nm->compile_id());
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
if (nm->is_nmethod()) {
|
if (nm->is_nmethod()) {
|
||||||
oop installedCode = nm->as_nmethod()->jvmci_installed_code();
|
char* installed_code_name = nm->as_nmethod()->jvmci_installed_code_name(buf, sizeof(buf));
|
||||||
if (installedCode != NULL) {
|
if (installed_code_name != NULL) {
|
||||||
oop installedCodeName = NULL;
|
tty->print(" (JVMCI: installed code name=%s) ", installed_code_name);
|
||||||
if (installedCode->is_a(InstalledCode::klass())) {
|
|
||||||
installedCodeName = InstalledCode::name(installedCode);
|
|
||||||
}
|
|
||||||
if (installedCodeName != NULL) {
|
|
||||||
tty->print(" (JVMCI: installedCodeName=%s) ", java_lang_String::as_utf8_string(installedCodeName));
|
|
||||||
} else {
|
|
||||||
tty->print(" (JVMCI: installed code has no name) ");
|
|
||||||
}
|
|
||||||
} else if (nm->is_compiled_by_jvmci()) {
|
|
||||||
tty->print(" (JVMCI: no installed code) ");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -127,6 +127,11 @@ oop JNIHandles::resolve_jweak(jweak handle) {
|
||||||
template oop JNIHandles::resolve_jweak<true>(jweak);
|
template oop JNIHandles::resolve_jweak<true>(jweak);
|
||||||
template oop JNIHandles::resolve_jweak<false>(jweak);
|
template oop JNIHandles::resolve_jweak<false>(jweak);
|
||||||
|
|
||||||
|
bool JNIHandles::is_global_weak_cleared(jweak handle) {
|
||||||
|
assert(is_jweak(handle), "not a weak handle");
|
||||||
|
return guard_value<false>(jweak_ref(handle)) == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void JNIHandles::destroy_global(jobject handle) {
|
void JNIHandles::destroy_global(jobject handle) {
|
||||||
if (handle != NULL) {
|
if (handle != NULL) {
|
||||||
assert(is_global_handle(handle), "Invalid delete of global JNI handle");
|
assert(is_global_handle(handle), "Invalid delete of global JNI handle");
|
||||||
|
|
|
@ -82,6 +82,7 @@ class JNIHandles : AllStatic {
|
||||||
// Weak global handles
|
// Weak global handles
|
||||||
static jobject make_weak_global(Handle obj);
|
static jobject make_weak_global(Handle obj);
|
||||||
static void destroy_weak_global(jobject handle);
|
static void destroy_weak_global(jobject handle);
|
||||||
|
static bool is_global_weak_cleared(jweak handle); // Test jweak without resolution
|
||||||
|
|
||||||
// Sentinel marking deleted handles in block. Note that we cannot store NULL as
|
// Sentinel marking deleted handles in block. Note that we cannot store NULL as
|
||||||
// the sentinel, since clearing weak global JNI refs are done by storing NULL in
|
// the sentinel, since clearing weak global JNI refs are done by storing NULL in
|
||||||
|
|
|
@ -30,13 +30,10 @@ import jdk.vm.ci.meta.JavaType;
|
||||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link InstalledCode} for code installed as an nmethod. The nmethod stores a
|
* Implementation of {@link InstalledCode} for code installed as an nmethod.
|
||||||
* weak reference to an instance of this class. This is necessary to keep the nmethod from being
|
*
|
||||||
* unloaded while the associated {@link HotSpotNmethod} instance is alive.
|
* When a {@link HotSpotNmethod} dies, it triggers unloading of the nmethod unless
|
||||||
* <p>
|
* {@link #isDefault() == true}.
|
||||||
* Note that there is no (current) way for the reference from an nmethod to a {@link HotSpotNmethod}
|
|
||||||
* instance to be anything but weak. This is due to the fact that HotSpot does not treat nmethods as
|
|
||||||
* strong GC roots.
|
|
||||||
*/
|
*/
|
||||||
public class HotSpotNmethod extends HotSpotInstalledCode {
|
public class HotSpotNmethod extends HotSpotInstalledCode {
|
||||||
|
|
||||||
|
@ -54,6 +51,11 @@ public class HotSpotNmethod extends HotSpotInstalledCode {
|
||||||
this.isDefault = isDefault;
|
this.isDefault = isDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the nmethod associated with this object is the compiled entry point for
|
||||||
|
* {@link #getMethod()}. If {@code false}, then the nmethod is unloaded when the VM determines
|
||||||
|
* this object has died.
|
||||||
|
*/
|
||||||
public boolean isDefault() {
|
public boolean isDefault() {
|
||||||
return isDefault;
|
return isDefault;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue