changeset 22643:456800cd1a17

Ensure that not_entrant InstalledCode can still be invalidated
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Wed, 30 Sep 2015 15:58:36 -0700
parents 6b444ec119b8
children cefe66df3455
files jvmci/jdk.internal.jvmci.code/src/jdk/internal/jvmci/code/InstalledCode.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/CompilerToVM.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotCodeCacheProvider.java jvmci/jdk.internal.jvmci.hotspot/src/jdk/internal/jvmci/hotspot/HotSpotInstalledCode.java src/share/vm/code/nmethod.cpp src/share/vm/code/nmethod.hpp src/share/vm/jvmci/jvmciCompilerToVM.cpp src/share/vm/jvmci/jvmciCompilerToVM.hpp src/share/vm/jvmci/jvmciJavaClasses.cpp src/share/vm/jvmci/jvmciJavaClasses.hpp
diffstat 10 files changed, 92 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- 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();
--- 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}.
--- 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;
     }
--- 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;
     }
--- 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;
--- 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
--- 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)},
--- 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 {
--- 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
--- 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                                                                                                                                                    \