changeset 7089:af30115c9d0e

added metering of code installation failure rate to detect excessive failure caused by overly optimistic assumptions
author Doug Simon <doug.simon@oracle.com>
date Wed, 28 Nov 2012 20:39:43 +0100
parents 97d0eae99568
children 05ce1defa4f9 dff79b1f82f1 770901ff8f80
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java src/share/vm/graal/graalCodeInstaller.cpp src/share/vm/graal/graalCodeInstaller.hpp src/share/vm/graal/graalCompilerToVM.cpp src/share/vm/graal/graalEnv.cpp src/share/vm/graal/graalEnv.hpp
diffstat 7 files changed, 81 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Wed Nov 28 19:18:39 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Wed Nov 28 20:39:43 2012 +0100
@@ -134,7 +134,8 @@
      * @param code if not null, then the code is installed as the non-default compiled code for the associated method
      *            and the details of the installation are written to this object
      * @param info additional information about the installation are written to this object if it is not null
-     * @return the value of {@code code} if installation was successful, null otherwise
+     * @return the value of {@code code} if installation was successful, null if dependency validation failed or the
+     *         code cache is full
      */
     HotSpotInstalledCode installCode(HotSpotCompilationResult compResult, HotSpotInstalledCode code, HotSpotCodeInfo info);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Wed Nov 28 19:18:39 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Wed Nov 28 20:39:43 2012 +0100
@@ -23,6 +23,8 @@
 
 package com.oracle.graal.hotspot.bridge;
 
+import static com.oracle.graal.hotspot.bridge.CompilerToVMImpl.CodeInstallResult.*;
+
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.meta.*;
@@ -34,6 +36,42 @@
  */
 public class CompilerToVMImpl implements CompilerToVM {
 
+    // Must be kept in sync with enum in graalEnv.hpp
+    enum CodeInstallResult {
+        OK,
+        DEPENDENCIES_FAILED,
+        CACHE_FULL
+    }
+
+    /**
+     * Number of successive successful installations.
+     */
+    private long successfulInstallations;
+
+    /**
+     * The minimum expected number of successful code installations between each code
+     * installation failure. Warning messages are printed when the failure rate goes
+     * above this threshold. This usually indicates use of some overly optimistic
+     * assumptions during compilation.
+     */
+    private static final int MINIMUM_SUCCESSFUL_INSTALLATIONS_PER_FAILURE = 2000;
+
+    private native int installCode0(HotSpotCompilationResult comp, HotSpotInstalledCode code, HotSpotCodeInfo info);
+
+    @Override
+    public HotSpotInstalledCode installCode(HotSpotCompilationResult comp, HotSpotInstalledCode code, HotSpotCodeInfo info) {
+        int result = installCode0(comp, code, info);
+        if (result != OK.ordinal()) {
+            if (successfulInstallations < MINIMUM_SUCCESSFUL_INSTALLATIONS_PER_FAILURE) {
+                System.err.println("Failed to install compiled code for " + comp.method + " [reason: " + CodeInstallResult.values()[result] + "]");
+            }
+            successfulInstallations = 0L;
+        } else {
+            successfulInstallations++;
+        }
+        return code;
+    }
+
     @Override
     public native long getMetaspaceMethod(Method reflectionMethod, HotSpotResolvedObjectType[] resultHolder);
 
@@ -83,9 +121,6 @@
     public native JavaField lookupFieldInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode);
 
     @Override
-    public native HotSpotInstalledCode installCode(HotSpotCompilationResult comp, HotSpotInstalledCode code, HotSpotCodeInfo info);
-
-    @Override
     public native void initializeConfiguration(HotSpotVMConfig config);
 
     @Override
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Wed Nov 28 19:18:39 2012 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Wed Nov 28 20:39:43 2012 +0100
@@ -23,12 +23,12 @@
 
 #include "precompiled.hpp"
 #include "runtime/javaCalls.hpp"
+#include "graal/graalEnv.hpp"
 #include "graal/graalCompiler.hpp"
 #include "graal/graalCodeInstaller.hpp"
 #include "graal/graalJavaAccess.hpp"
 #include "graal/graalCompilerToVM.hpp"
 #include "graal/graalVmIds.hpp"
-#include "graal/graalEnv.hpp"
 #include "c1/c1_Runtime1.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "vmreg_x86.inline.hpp"
@@ -291,7 +291,7 @@
 }
 
 // constructor used to create a method
-CodeInstaller::CodeInstaller(Handle& comp_result, methodHandle method, nmethod*& nm, Handle installed_code) {
+CodeInstaller::CodeInstaller(Handle& comp_result, methodHandle method, GraalEnv::CodeInstallResult& result, nmethod*& nm, Handle installed_code) {
   _env = CURRENT_ENV;
   GraalCompiler::initialize_buffer_blob();
   CodeBuffer buffer(JavaThread::current()->get_buffer_blob());
@@ -308,7 +308,7 @@
 
   int stack_slots = _total_frame_size / HeapWordSize; // conversion to words
 
-  nm = GraalEnv::register_method(method, entry_bci, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
+  result = GraalEnv::register_method(method, nm, entry_bci, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
     &_implicit_exception_table, GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, -1, true, false, installed_code);
 
   method->clear_queued_for_compilation();
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Wed Nov 28 19:18:39 2012 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Wed Nov 28 20:39:43 2012 +0100
@@ -85,7 +85,7 @@
 public:
 
   // constructor used to create a method
-  CodeInstaller(Handle& comp_result, methodHandle method, nmethod*& nm, Handle installed_code);
+  CodeInstaller(Handle& comp_result, methodHandle method, GraalEnv::CodeInstallResult& result, nmethod*& nm, Handle installed_code);
 
   // constructor used to create a stub
   CodeInstaller(Handle& target_method, BufferBlob*& blob, jlong& id);
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Wed Nov 28 19:18:39 2012 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Wed Nov 28 20:39:43 2012 +0100
@@ -735,7 +735,7 @@
   set_int(env, config, "arrayClassElementOffset", in_bytes(ObjArrayKlass::element_klass_offset()));
 C2V_END
 
-C2V_VMENTRY(jobject, installCode, (JNIEnv *jniEnv, jobject, jobject compResult, jobject installed_code, jobject info))
+C2V_VMENTRY(jint, installCode0, (JNIEnv *jniEnv, jobject, jobject compResult, jobject installed_code, jobject info))
   ResourceMark rm;
   HandleMark hm;
   Handle compResultHandle = JNIHandles::resolve(compResult);
@@ -744,29 +744,27 @@
   Arena arena;
   ciEnv env(&arena);
   Handle installed_code_handle = JNIHandles::resolve(installed_code);
-  CodeInstaller installer(compResultHandle, method, nm, installed_code_handle);
-
-  if (nm == NULL) {
-    // dependency (re)checking failed
-    return NULL;
-  }
+  GraalEnv::CodeInstallResult result;
+  CodeInstaller installer(compResultHandle, method, result, nm, installed_code_handle);
 
-  if (info != NULL) {
-    arrayOop codeCopy = oopFactory::new_byteArray(nm->code_size(), CHECK_0);
-    memcpy(codeCopy->base(T_BYTE), nm->code_begin(), nm->code_size());
-    HotSpotCodeInfo::set_code(info, codeCopy);
-    HotSpotCodeInfo::set_start(info, (jlong) nm->code_begin());
-  }
+  if (result != GraalEnv::ok) {
+    assert(nm == NULL, "should be");
+  } else {
+    if (info != NULL) {
+      arrayOop codeCopy = oopFactory::new_byteArray(nm->code_size(), CHECK_0);
+      memcpy(codeCopy->base(T_BYTE), nm->code_begin(), nm->code_size());
+      HotSpotCodeInfo::set_code(info, codeCopy);
+      HotSpotCodeInfo::set_start(info, (jlong) nm->code_begin());
+    }
 
-  if (!installed_code_handle.is_null()) {
-    assert(installed_code_handle->is_a(HotSpotInstalledCode::klass()), "wrong type");
-    HotSpotInstalledCode::set_nmethod(installed_code_handle, (jlong) nm);
-    HotSpotInstalledCode::set_method(installed_code_handle, HotSpotCompilationResult::method(compResult));
-    assert(nm == NULL || !installed_code_handle->is_scavengable() || nm->on_scavenge_root_list(), "nm should be scavengable if installed_code is scavengable");
-    return installed_code;
-  } else {
-    return NULL;
+    if (!installed_code_handle.is_null()) {
+      assert(installed_code_handle->is_a(HotSpotInstalledCode::klass()), "wrong type");
+      HotSpotInstalledCode::set_nmethod(installed_code_handle, (jlong) nm);
+      HotSpotInstalledCode::set_method(installed_code_handle, HotSpotCompilationResult::method(compResult));
+      assert(nm == NULL || !installed_code_handle->is_scavengable() || nm->on_scavenge_root_list(), "nm should be scavengable if installed_code is scavengable");
+    }
   }
+  return result;
 C2V_END
 
 C2V_VMENTRY(jobject, disassembleNative, (JNIEnv *jniEnv, jobject, jbyteArray code, jlong start_address))
@@ -952,7 +950,7 @@
   {CC"getMetaspaceConstructor",       CC"("REFLECT_CONSTRUCTOR"["HS_RESOLVED_TYPE")"METASPACE_METHOD,   FN_PTR(getMetaspaceConstructor)},
   {CC"getJavaField",                  CC"("REFLECT_FIELD")"HS_RESOLVED_FIELD,                           FN_PTR(getJavaField)},
   {CC"initializeConfiguration",       CC"("HS_CONFIG")V",                                               FN_PTR(initializeConfiguration)},
-  {CC"installCode",                   CC"("HS_COMP_RESULT HS_INSTALLED_CODE HS_CODE_INFO")"HS_INSTALLED_CODE, FN_PTR(installCode)},
+  {CC"installCode0",                  CC"("HS_COMP_RESULT HS_INSTALLED_CODE HS_CODE_INFO")I",           FN_PTR(installCode0)},
   {CC"disassembleNative",             CC"([BJ)"STRING,                                                  FN_PTR(disassembleNative)},
   {CC"executeCompiledMethod",         CC"("METASPACE_METHOD NMETHOD OBJECT OBJECT OBJECT")"OBJECT,      FN_PTR(executeCompiledMethod)},
   {CC"executeCompiledMethodVarargs",  CC"("METASPACE_METHOD NMETHOD "["OBJECT")"OBJECT,                 FN_PTR(executeCompiledMethodVarargs)},
--- a/src/share/vm/graal/graalEnv.cpp	Wed Nov 28 19:18:39 2012 +0100
+++ b/src/share/vm/graal/graalEnv.cpp	Wed Nov 28 20:39:43 2012 +0100
@@ -428,7 +428,9 @@
 
 // ------------------------------------------------------------------
 // ciEnv::register_method
-nmethod* GraalEnv::register_method(methodHandle& method,
+GraalEnv::CodeInstallResult GraalEnv::register_method(
+                                methodHandle& method,
+                                nmethod*& nm,
                                 int entry_bci,
                                 CodeOffsets* offsets,
                                 int orig_pc_offset,
@@ -447,7 +449,7 @@
                                 Handle installed_code) {
   EXCEPTION_CONTEXT;
   NMethodSweeper::possibly_sweep();
-  nmethod* nm = NULL;
+  nm = NULL;
   int comp_level = CompLevel_simple;
   {
     // To prevent compile queue updates.
@@ -472,7 +474,7 @@
       // If the code buffer is created on each compile attempt
       // as in C2, then it must be freed.
       //code_buffer->free_blob();
-      return NULL;
+      return GraalEnv::dependencies_failed;
     }
 
     nm =  nmethod::new_nmethod(method,
@@ -555,8 +557,9 @@
   // JVMTI -- compiled method notification (must be done outside lock)
   if (nm != NULL) {
     nm->post_compiled_method_load_event();
+    return GraalEnv::ok;
   }
 
-  return nm;
+  return GraalEnv::cache_full;
 }
 
--- a/src/share/vm/graal/graalEnv.hpp	Wed Nov 28 19:18:39 2012 +0100
+++ b/src/share/vm/graal/graalEnv.hpp	Wed Nov 28 20:39:43 2012 +0100
@@ -46,6 +46,13 @@
 
 public:
 
+  // Must be kept in sync with the enum in the HotSpot implementation of CompilerToVM
+  enum CodeInstallResult {
+     ok,
+     dependencies_failed,
+     cache_full
+  };
+
   // Look up a klass by name from a particular class loader (the accessor's).
   // If require_local, result must be defined in that class loader, or NULL.
   // If !require_local, a result from remote class loader may be reported,
@@ -109,7 +116,9 @@
 
 public:
   // Register the result of a compilation.
-  static nmethod* register_method(methodHandle&             target,
+  static GraalEnv::CodeInstallResult register_method(
+                       methodHandle&             target,
+                       nmethod*&                 nm,
                        int                       entry_bci,
                        CodeOffsets*              offsets,
                        int                       orig_pc_offset,