# HG changeset patch # User Tom Rodriguez # Date 1443653916 25200 # Node ID 456800cd1a17f26dcb63a4c74d45b5cc82f636ff # Parent 6b444ec119b8bd60ea9b8d741408ab7a2355b771 Ensure that not_entrant InstalledCode can still be invalidated diff -r 6b444ec119b8 -r 456800cd1a17 jvmci/jdk.internal.jvmci.code/src/jdk/internal/jvmci/code/InstalledCode.java --- a/jvmci/jdk.internal.jvmci.code/src/jdk/internal/jvmci/code/InstalledCode.java Wed Sep 30 15:58:33 2015 -0700 +++ b/jvmci/jdk.internal.jvmci.code/src/jdk/internal/jvmci/code/InstalledCode.java Wed Sep 30 15:58:36 2015 -0700 @@ -29,11 +29,16 @@ public class InstalledCode { /** - * Raw address of this code blob. + * Raw address address of entity representing this installed code. */ private long address; /** + * Raw address of entryPoint of this installed code. + */ + protected long entryPoint; + + /** * Counts how often the address field was reassigned. */ private long version; @@ -44,27 +49,35 @@ this.name = name; } - public final void setAddress(long address) { + public final void setAddressAndEntryPoint(long address, long entryPoint) { this.address = address; + this.entryPoint = entryPoint; version++; } /** - * @return the address of this code blob + * @return the address of entity representing this installed code. */ public final long getAddress() { return address; } /** - * @return the address of this code blob + * @return the address of the normal entry point of the installed code. + */ + public final long getEntryPoint() { + return entryPoint; + } + + /** + * @return the version number of this installed code */ public final long getVersion() { return version; } /** - * Returns the name of this code blob. + * Returns the name of this installed code. */ public String getName() { return name; @@ -79,10 +92,19 @@ } /** - * Returns the number of instruction bytes for this code. + * @return true if the code represented by this object is still valid for invocation, false + * otherwise (may happen due to deopt, etc.) */ - public long getCodeSize() { - return 0; + public boolean isValid() { + return entryPoint != 0; + } + + /** + * @return true if the code represented by this object still exists and might have live + * activations, false otherwise (may happen due to deopt, etc.) + */ + public boolean isAlive() { + return address != 0; } /** @@ -93,17 +115,9 @@ } /** - * @return true if the code represented by this object is still valid, false otherwise (may - * happen due to deopt, etc.) - */ - public boolean isValid() { - return address != 0; - } - - /** * Invalidates this installed code such that any subsequent * {@linkplain #executeVarargs(Object...) invocation} will throw an - * {@link InvalidInstalledCodeException}. + * {@link InvalidInstalledCodeException} and all existing invocations will be deoptimized. */ public void invalidate() { throw new UnsupportedOperationException(); diff -r 6b444ec119b8 -r 456800cd1a17 jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/CompilerToVM.java --- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/CompilerToVM.java Wed Sep 30 15:58:33 2015 -0700 +++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/CompilerToVM.java Wed Sep 30 15:58:36 2015 -0700 @@ -388,7 +388,7 @@ * {@code codeBlob} could not be disassembled for some reason */ // The HotSpot disassembler seems not to be thread safe so it's better to synchronize its usage - synchronized native String disassembleCodeBlob(long codeBlob); + synchronized native String disassembleCodeBlob(InstalledCode installedCode); /** * Gets a stack trace element for {@code method} at bytecode index {@code bci}. diff -r 6b444ec119b8 -r 456800cd1a17 jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotCodeCacheProvider.java --- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotCodeCacheProvider.java Wed Sep 30 15:58:33 2015 -0700 +++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotCodeCacheProvider.java Wed Sep 30 15:58:36 2015 -0700 @@ -251,8 +251,7 @@ public String disassemble(InstalledCode code) { if (code.isValid()) { - long codeBlob = code.getAddress(); - return runtime.getCompilerToVM().disassembleCodeBlob(codeBlob); + return runtime.getCompilerToVM().disassembleCodeBlob(code); } return null; } diff -r 6b444ec119b8 -r 456800cd1a17 jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotInstalledCode.java --- a/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotInstalledCode.java Wed Sep 30 15:58:33 2015 -0700 +++ b/jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotInstalledCode.java Wed Sep 30 15:58:36 2015 -0700 @@ -58,18 +58,6 @@ return size; } - /** - * @return a copy of this code blob if it is {@linkplain #isValid() valid}, null otherwise. - */ - public byte[] getBlob() { - if (!isValid()) { - return null; - } - byte[] blob = new byte[size]; - UNSAFE.copyMemory(null, getAddress(), blob, Unsafe.ARRAY_BYTE_BASE_OFFSET, size); - return blob; - } - @Override public abstract String toString(); @@ -78,7 +66,6 @@ return codeStart; } - @Override public long getCodeSize() { return codeSize; } diff -r 6b444ec119b8 -r 456800cd1a17 src/share/vm/code/nmethod.cpp --- a/src/share/vm/code/nmethod.cpp Wed Sep 30 15:58:33 2015 -0700 +++ b/src/share/vm/code/nmethod.cpp Wed Sep 30 15:58:36 2015 -0700 @@ -1490,20 +1490,17 @@ // Unregister must be done before the state change Universe::heap()->unregister_nmethod(this); + _state = unloaded; + #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. - if (_jvmci_installed_code != NULL) { - InstalledCode::set_address(_jvmci_installed_code, 0); - _jvmci_installed_code = NULL; - } + maybe_invalidate_installed_code(); #endif - _state = unloaded; - // Log the unloading. log_state_change(); @@ -1667,12 +1664,8 @@ } else { assert(state == not_entrant, "other cases may need to be handled differently"); } -#if INCLUDE_JVMCI - if (_jvmci_installed_code != NULL) { - // Break the link between nmethod and InstalledCode such that the nmethod can subsequently be flushed safely. - InstalledCode::set_address(_jvmci_installed_code, 0); - } -#endif + + JVMCI_ONLY(maybe_invalidate_installed_code()); if (TraceCreateZombies) { ResourceMark m; @@ -3549,6 +3542,22 @@ } #if INCLUDE_JVMCI +void nmethod::maybe_invalidate_installed_code() { + if (_jvmci_installed_code != NULL) { + 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. + InstalledCode::set_address(_jvmci_installed_code, 0); + InstalledCode::set_entryPoint(_jvmci_installed_code, 0); + _jvmci_installed_code = NULL; + } else if (is_not_entrant()) { + InstalledCode::set_entryPoint(_jvmci_installed_code, 0); + } + } +} + char* nmethod::jvmci_installed_code_name(char* buf, size_t buflen) { if (!this->is_compiled_by_jvmci()) { return NULL; diff -r 6b444ec119b8 -r 456800cd1a17 src/share/vm/code/nmethod.hpp --- a/src/share/vm/code/nmethod.hpp Wed Sep 30 15:58:33 2015 -0700 +++ b/src/share/vm/code/nmethod.hpp Wed Sep 30 15:58:36 2015 -0700 @@ -630,6 +630,7 @@ oop jvmci_installed_code() { return _jvmci_installed_code ; } char* jvmci_installed_code_name(char* buf, size_t buflen); void set_jvmci_installed_code(oop installed_code) { _jvmci_installed_code = installed_code; } + void maybe_invalidate_installed_code(); oop speculation_log() { return _speculation_log ; } void set_speculation_log(oop speculation_log) { _speculation_log = speculation_log; } #endif diff -r 6b444ec119b8 -r 456800cd1a17 src/share/vm/jvmci/jvmciCompilerToVM.cpp --- a/src/share/vm/jvmci/jvmciCompilerToVM.cpp Wed Sep 30 15:58:33 2015 -0700 +++ b/src/share/vm/jvmci/jvmciCompilerToVM.cpp Wed Sep 30 15:58:36 2015 -0700 @@ -78,6 +78,20 @@ return NULL; } +void CompilerToVM::invalidate_installed_code(Handle installedCode) { + jlong nativeMethod = InstalledCode::address(installedCode); + nmethod* nm = (nmethod*)nativeMethod; + if (nm != NULL && 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); + } + InstalledCode::set_address(installedCode, 0); +} + C2V_VMENTRY(void, initializeConfiguration, (JNIEnv *, jobject, jobject config)) VMStructs::initHotSpotVMConfig(JNIHandles::resolve(config)); C2V_END @@ -608,8 +622,13 @@ } else { if (!installed_code_handle.is_null()) { assert(installed_code_handle->is_a(InstalledCode::klass()), "wrong type"); + CompilerToVM::invalidate_installed_code(installed_code_handle); InstalledCode::set_address(installed_code_handle, (jlong) cb); - InstalledCode::set_version(installed_code_handle, InstalledCode::version(installed_code_handle) + 1); + if (cb->is_nmethod()) { + InstalledCode::set_entryPoint(installed_code_handle, (jlong) cb->as_nmethod_or_null()->verified_entry_point()); + } else { + InstalledCode::set_entryPoint(installed_code_handle, (jlong) cb->code_begin()); + } if (installed_code_handle->is_a(HotSpotInstalledCode::klass())) { HotSpotInstalledCode::set_size(installed_code_handle, cb->size()); HotSpotInstalledCode::set_codeStart(installed_code_handle, (jlong) cb->code_begin()); @@ -656,10 +675,19 @@ stats->_osr.reset(); C2V_END -C2V_VMENTRY(jobject, disassembleCodeBlob, (JNIEnv *jniEnv, jobject, jlong codeBlob)) +C2V_VMENTRY(jobject, disassembleCodeBlob, (JNIEnv *jniEnv, jobject, jobject installedCode)) ResourceMark rm; HandleMark hm; + if (installedCode == NULL) { + THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(), "installedCode is null"); + } + + jlong codeBlob = InstalledCode::address(installedCode); + if (codeBlob == 0L) { + return NULL; + } + CodeBlob* cb = (CodeBlob*) (address) codeBlob; if (cb == NULL) { return NULL; @@ -810,15 +838,9 @@ C2V_END -C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv*, jobject, jobject hotspotInstalledCode)) - jlong nativeMethod = InstalledCode::address(hotspotInstalledCode); - nmethod* m = (nmethod*)nativeMethod; - if (m != NULL && !m->is_not_entrant()) { - m->mark_for_deoptimization(); - VM_Deoptimize op; - VMThread::execute(&op); - } - InstalledCode::set_address(hotspotInstalledCode, 0); +C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv*, jobject, jobject installed_code)) + Handle installed_code_handle = JNIHandles::resolve(installed_code); + CompilerToVM::invalidate_installed_code(installed_code_handle); C2V_END C2V_VMENTRY(jobject, readUncompressedOop, (JNIEnv*, jobject, jlong addr)) @@ -1225,7 +1247,7 @@ {CC"installCode", CC"("TARGET_DESCRIPTION HS_COMPILED_CODE INSTALLED_CODE SPECULATION_LOG")I", FN_PTR(installCode)}, {CC"notifyCompilationStatistics", CC"(I"HS_RESOLVED_METHOD"ZIJJ"INSTALLED_CODE")V", FN_PTR(notifyCompilationStatistics)}, {CC"resetCompilationStatistics", CC"()V", FN_PTR(resetCompilationStatistics)}, - {CC"disassembleCodeBlob", CC"(J)"STRING, FN_PTR(disassembleCodeBlob)}, + {CC"disassembleCodeBlob", CC"("INSTALLED_CODE")"STRING, FN_PTR(disassembleCodeBlob)}, {CC"executeInstalledCode", CC"(["OBJECT INSTALLED_CODE")"OBJECT, FN_PTR(executeInstalledCode)}, {CC"getLineNumberTable", CC"("HS_RESOLVED_METHOD")[J", FN_PTR(getLineNumberTable)}, {CC"getLocalVariableTableStart", CC"("HS_RESOLVED_METHOD")J", FN_PTR(getLocalVariableTableStart)}, diff -r 6b444ec119b8 -r 456800cd1a17 src/share/vm/jvmci/jvmciCompilerToVM.hpp --- a/src/share/vm/jvmci/jvmciCompilerToVM.hpp Wed Sep 30 15:58:33 2015 -0700 +++ b/src/share/vm/jvmci/jvmciCompilerToVM.hpp Wed Sep 30 15:58:36 2015 -0700 @@ -92,6 +92,8 @@ static oop get_jvmci_method(methodHandle method, TRAPS); static oop get_jvmci_type(KlassHandle klass, TRAPS); + + static void invalidate_installed_code(Handle installedCode); }; class JavaArgumentUnboxer : public SignatureIterator { diff -r 6b444ec119b8 -r 456800cd1a17 src/share/vm/jvmci/jvmciJavaClasses.cpp --- a/src/share/vm/jvmci/jvmciJavaClasses.cpp Wed Sep 30 15:58:33 2015 -0700 +++ b/src/share/vm/jvmci/jvmciJavaClasses.cpp Wed Sep 30 15:58:36 2015 -0700 @@ -69,7 +69,6 @@ void jvmci_compute_offsets() { COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, OOP_FIELD, OOP_FIELD, STATIC_OOP_FIELD, STATIC_OOP_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD) - guarantee(InstalledCode::_address_offset == sizeof(oopDesc), "codeBlob must be first field!"); } #define EMPTY0 diff -r 6b444ec119b8 -r 456800cd1a17 src/share/vm/jvmci/jvmciJavaClasses.hpp --- a/src/share/vm/jvmci/jvmciJavaClasses.hpp Wed Sep 30 15:58:33 2015 -0700 +++ b/src/share/vm/jvmci/jvmciJavaClasses.hpp Wed Sep 30 15:58:36 2015 -0700 @@ -62,6 +62,7 @@ end_class \ start_class(InstalledCode) \ long_field(InstalledCode, address) \ + long_field(InstalledCode, entryPoint) \ long_field(InstalledCode, version) \ oop_field(InstalledCode, name, "Ljava/lang/String;") \ end_class \