< prev index next >

src/hotspot/share/code/nmethod.cpp

Print this page

        

*** 407,416 **** --- 407,417 ---- _rtm_state = NoRTM; #endif #if INCLUDE_JVMCI _jvmci_installed_code = NULL; _speculation_log = NULL; + _jvmci_installed_code_triggers_unloading = false; #endif } nmethod* nmethod::new_native_nmethod(const methodHandle& method, int compile_id,
*** 459,470 **** ExceptionHandlerTable* handler_table, ImplicitExceptionTable* nul_chk_table, AbstractCompiler* compiler, int comp_level #if INCLUDE_JVMCI ! , Handle installed_code, ! Handle speculationLog #endif ) { assert(debug_info->oop_recorder() == code_buffer->oop_recorder(), "shared OR"); code_buffer->finalize_oop_references(method); --- 460,471 ---- ExceptionHandlerTable* handler_table, ImplicitExceptionTable* nul_chk_table, AbstractCompiler* compiler, int comp_level #if INCLUDE_JVMCI ! , jweak installed_code, ! jweak speculationLog #endif ) { assert(debug_info->oop_recorder() == code_buffer->oop_recorder(), "shared OR"); code_buffer->finalize_oop_references(method);
*** 640,651 **** ExceptionHandlerTable* handler_table, ImplicitExceptionTable* nul_chk_table, AbstractCompiler* compiler, int comp_level #if INCLUDE_JVMCI ! , Handle installed_code, ! Handle speculation_log #endif ) : CompiledMethod(method, "nmethod", type, nmethod_size, sizeof(nmethod), code_buffer, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps, false), _native_receiver_sp_offset(in_ByteSize(-1)), _native_basic_lock_sp_offset(in_ByteSize(-1)) --- 641,652 ---- ExceptionHandlerTable* handler_table, ImplicitExceptionTable* nul_chk_table, AbstractCompiler* compiler, int comp_level #if INCLUDE_JVMCI ! , jweak installed_code, ! jweak speculation_log #endif ) : CompiledMethod(method, "nmethod", type, nmethod_size, sizeof(nmethod), code_buffer, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps, false), _native_receiver_sp_offset(in_ByteSize(-1)), _native_basic_lock_sp_offset(in_ByteSize(-1))
*** 669,680 **** _consts_offset = content_offset() + code_buffer->total_offset_of(code_buffer->consts()); _stub_offset = content_offset() + code_buffer->total_offset_of(code_buffer->stubs()); set_ctable_begin(header_begin() + _consts_offset); #if INCLUDE_JVMCI ! _jvmci_installed_code = installed_code(); ! _speculation_log = (instanceOop)speculation_log(); if (compiler->is_jvmci()) { // JVMCI might not produce any stub sections if (offsets->value(CodeOffsets::Exceptions) != -1) { _exception_offset = code_offset() + offsets->value(CodeOffsets::Exceptions); --- 670,687 ---- _consts_offset = content_offset() + code_buffer->total_offset_of(code_buffer->consts()); _stub_offset = content_offset() + code_buffer->total_offset_of(code_buffer->stubs()); set_ctable_begin(header_begin() + _consts_offset); #if INCLUDE_JVMCI ! _jvmci_installed_code = installed_code; ! _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()) { // JVMCI might not produce any stub sections if (offsets->value(CodeOffsets::Exceptions) != -1) { _exception_offset = code_offset() + offsets->value(CodeOffsets::Exceptions);
*** 1024,1035 **** LogStream ls(lt); ls.print_cr("making nmethod " INTPTR_FORMAT " unloadable, Method*(" INTPTR_FORMAT "), cause(" INTPTR_FORMAT ")", 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 if (is_osr_method()) { // Invalidate the osr nmethod only once if (is_in_use()) { --- 1031,1040 ----
*** 1075,1092 **** log_state_change(); #if INCLUDE_JVMCI // 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 ! // reference to the dead object. Nulling out the reference has to happen ! // after the method is unregistered since the original value may be still ! // tracked by the rset. 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 // The Method* is gone at this point assert(_method == NULL, "Tautology"); --- 1080,1091 ---- log_state_change(); #if INCLUDE_JVMCI // 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 ! // reference to the dead object. maybe_invalidate_installed_code(); #endif // The Method* is gone at this point assert(_method == NULL, "Tautology");
*** 1244,1257 **** // safepoint can sneak in, otherwise the oops used by the // dependency logic could have become stale. MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); if (nmethod_needs_unregister) { Universe::heap()->unregister_nmethod(this); - #ifdef JVMCI - _jvmci_installed_code = NULL; - _speculation_log = NULL; - #endif } flush_dependencies(NULL); } // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload --- 1243,1252 ----
*** 1312,1321 **** --- 1307,1321 ---- if (on_scavenge_root_list()) { 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(); CodeCache::free(this); } //
*** 1498,1530 **** return do_unloading_scopes(is_alive, unloading_occurred); } #if INCLUDE_JVMCI 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->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(_jvmci_installed_code)) { ! if (!is_alive->do_object_b(_jvmci_installed_code)) { ! clear_jvmci_installed_code(); ! } ! } else { ! if (can_unload(is_alive, (oop*)&_jvmci_installed_code, unloading_occurred)) { return true; } } } ! ! 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 // Iterate over metadata calling this function. Used by RedefineClasses void nmethod::metadata_do(void f(Metadata*)) { --- 1498,1519 ---- return do_unloading_scopes(is_alive, unloading_occurred); } #if INCLUDE_JVMCI bool nmethod::do_unloading_jvmci(BoolObjectClosure* is_alive, bool unloading_occurred) { if (_jvmci_installed_code != NULL) { ! if (JNIHandles::is_global_weak_cleared(_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(); } } } ! return false; } #endif // Iterate over metadata calling this function. Used by RedefineClasses void nmethod::metadata_do(void f(Metadata*)) {
*** 1592,1610 **** low_boundary += NativeJump::instruction_size; // %%% Note: On SPARC we patch only a 4-byte trap, not a full NativeJump. // (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); while (iter.next()) { if (iter.type() == relocInfo::oop_type ) { oop_Relocation* r = iter.oop_reloc(); --- 1581,1590 ----
*** 2858,2891 **** #endif // !PRODUCT #if INCLUDE_JVMCI void nmethod::clear_jvmci_installed_code() { ! // write_ref_method_pre/post can only be safely called at a ! // 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) { ! // This must be done carefully to maintain nmethod remembered sets properly ! BarrierSet* bs = Universe::heap()->barrier_set(); ! bs->write_ref_nmethod_pre(&_jvmci_installed_code, this); _jvmci_installed_code = NULL; ! bs->write_ref_nmethod_post(&_jvmci_installed_code, this); } } void nmethod::maybe_invalidate_installed_code() { assert(Patching_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "should be performed under a lock for consistency"); ! oop installed_code = jvmci_installed_code(); if (installed_code != NULL) { nmethod* nm = (nmethod*)InstalledCode::address(installed_code); ! if (nm == NULL || nm != this) { ! // The link has been broken or the InstalledCode instance is ! // associated with another nmethod so do nothing. ! return; ! } if (!is_alive()) { // Break the link between nmethod and InstalledCode such that the nmethod // can subsequently be flushed safely. The link must be maintained while // the method could have live activations since invalidateInstalledCode // might want to invalidate all existing activations. --- 2838,2870 ---- #endif // !PRODUCT #if INCLUDE_JVMCI void nmethod::clear_jvmci_installed_code() { ! assert_locked_or_safepoint(Patching_lock); if (_jvmci_installed_code != NULL) { ! JNIHandles::destroy_weak_global(_jvmci_installed_code); _jvmci_installed_code = NULL; ! } ! } ! ! 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() { assert(Patching_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "should be performed under a lock for consistency"); ! oop installed_code = JNIHandles::resolve(_jvmci_installed_code); 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); ! if (nm == this) { if (!is_alive()) { // Break the link between nmethod and InstalledCode such that the nmethod // can subsequently be flushed safely. The link must be maintained while // the method could have live activations since invalidateInstalledCode // might want to invalidate all existing activations.
*** 2896,2905 **** --- 2875,2891 ---- // the address link around that so that existing activations can // be invalidated. 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) { if (installedCode() == NULL) { THROW(vmSymbols::java_lang_NullPointerException());
*** 2914,2960 **** nmethodLocker nml(nm); #ifdef ASSERT { MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag); // This relationship can only be checked safely under a lock ! assert(nm == NULL || !nm->is_alive() || nm->jvmci_installed_code() == installedCode(), "sanity check"); } #endif if (nm->is_alive()) { ! // The nmethod state machinery maintains the link between the ! // HotSpotInstalledCode and nmethod* so as long as the nmethod appears to be ! // alive assume there is work to do and deoptimize the nmethod. nm->mark_for_deoptimization(); VM_Deoptimize op; VMThread::execute(&op); } 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) { InstalledCode::set_address(installedCode, 0); } } char* nmethod::jvmci_installed_code_name(char* buf, size_t buflen) { if (!this->is_compiled_by_jvmci()) { return NULL; } ! oop installedCode = this->jvmci_installed_code(); ! if (installedCode != NULL) { ! oop installedCodeName = NULL; ! if (installedCode->is_a(InstalledCode::klass())) { ! installedCodeName = InstalledCode::name(installedCode); } ! if (installedCodeName != NULL) { ! return java_lang_String::as_utf8_string(installedCodeName, buf, (int)buflen); ! } else { ! jio_snprintf(buf, buflen, "null"); ! return buf; } } ! jio_snprintf(buf, buflen, "noInstalledCode"); ! return buf; } #endif --- 2900,2950 ---- nmethodLocker nml(nm); #ifdef ASSERT { MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag); // This relationship can only be checked safely under a lock ! assert(!nm->is_alive() || nm->jvmci_installed_code() == installedCode(), "sanity check"); } #endif if (nm->is_alive()) { ! // Invalidating the InstalledCode means we want the nmethod ! // to be deoptimized. nm->mark_for_deoptimization(); VM_Deoptimize 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); if (InstalledCode::address(installedCode) == nativeMethod) { 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) { if (!this->is_compiled_by_jvmci()) { return NULL; } ! oop installed_code = JNIHandles::resolve(_jvmci_installed_code); ! if (installed_code != NULL) { ! oop installed_code_name = NULL; ! if (installed_code->is_a(InstalledCode::klass())) { ! installed_code_name = InstalledCode::name(installed_code); } ! if (installed_code_name != NULL) { ! return java_lang_String::as_utf8_string(installed_code_name, buf, (int)buflen); } } ! return NULL; } #endif
< prev index next >