changeset 19426:dd8989d5547f

provide more detail when Graal code installation fails due to a failed dependency check
author Doug Simon <doug.simon@oracle.com>
date Tue, 17 Feb 2015 14:49:05 +0100
parents b6d8deed3fd5
children 9f037830060a 19223d29cb32 e66b3cc0c27a
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledNmethod.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java src/share/vm/code/dependencies.cpp src/share/vm/code/dependencies.hpp src/share/vm/graal/graalCodeInstaller.cpp src/share/vm/graal/graalEnv.cpp src/share/vm/graal/graalEnv.hpp src/share/vm/graal/graalJavaAccess.hpp
diffstat 8 files changed, 47 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledNmethod.java	Tue Feb 17 14:07:13 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledNmethod.java	Tue Feb 17 14:49:05 2015 +0100
@@ -25,6 +25,8 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.hotspot.meta.*;
 
+import edu.umd.cs.findbugs.annotations.*;
+
 /**
  * {@link HotSpotCompiledCode} destined for installation as an nmethod.
  */
@@ -36,6 +38,12 @@
     public final int id;
     public final long graalEnv;
 
+    /**
+     * May be set by VM if code installation fails. It will describe in more detail why installation
+     * failed (e.g., exactly which dependency failed).
+     */
+    @SuppressFBWarnings("UWF_UNWRITTEN_FIELD") private String installationFailureMessage;
+
     public HotSpotCompiledNmethod(HotSpotResolvedJavaMethod method, CompilationResult compResult) {
         this(method, compResult, 0L);
     }
@@ -52,4 +60,8 @@
     public String toString() {
         return getClass().getSimpleName() + "[" + id + ":" + method.format("%H.%n(%p)%r@") + entryBCI + "]";
     }
+
+    public String getInstallationFailureMessage() {
+        return installationFailureMessage;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Tue Feb 17 14:07:13 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Tue Feb 17 14:49:05 2015 +0100
@@ -259,8 +259,13 @@
             HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false);
             installedCode = code;
         }
-        CodeInstallResult result = runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(hotspotMethod, compResult), installedCode, log);
+        HotSpotCompiledNmethod compiledCode = new HotSpotCompiledNmethod(hotspotMethod, compResult);
+        CodeInstallResult result = runtime.getCompilerToVM().installCode(compiledCode, installedCode, log);
         if (result != CodeInstallResult.OK) {
+            String msg = compiledCode.getInstallationFailureMessage();
+            if (msg != null) {
+                throw new BailoutException(result != CodeInstallResult.DEPENDENCIES_FAILED, "Code installation failed: %s%n%s", result, msg);
+            }
             throw new BailoutException(result != CodeInstallResult.DEPENDENCIES_FAILED, "Code installation failed: %s", result);
         }
         return logOrDump(installedCode, compResult);
--- a/src/share/vm/code/dependencies.cpp	Tue Feb 17 14:07:13 2015 +0100
+++ b/src/share/vm/code/dependencies.cpp	Tue Feb 17 14:49:05 2015 +0100
@@ -737,10 +737,10 @@
 }
 
 void Dependencies::print_dependency(DepType dept, int nargs, DepArgument args[],
-                                    Klass* witness) {
+                                    Klass* witness, outputStream* st) {
   ResourceMark rm;
   ttyLocker ttyl;   // keep the following output all in one block
-  tty->print_cr("%s of type %s",
+  st->print_cr("%s of type %s",
                 (witness == NULL)? "Dependency": "Failed dependency",
                 dep_name(dept));
   // print arguments
@@ -762,18 +762,18 @@
     } else {
       what = "object ";
     }
-    tty->print("  %s = %s", what, (put_star? "*": ""));
+    st->print("  %s = %s", what, (put_star? "*": ""));
     if (arg.is_klass())
-      tty->print("%s", ((Klass*)arg.metadata_value())->external_name());
+      st->print("%s", ((Klass*)arg.metadata_value())->external_name());
     else if (arg.is_method())
-      ((Method*)arg.metadata_value())->print_value();
+      ((Method*)arg.metadata_value())->print_value_on(st);
     else
       ShouldNotReachHere(); // Provide impl for this type.
-    tty->cr();
+    st->cr();
   }
   if (witness != NULL) {
     bool put_star = !Dependencies::is_concrete_klass(witness);
-    tty->print_cr("  witness = %s%s",
+    st->print_cr("  witness = %s%s",
                   (put_star? "*": ""),
                   witness->external_name());
   }
@@ -806,18 +806,18 @@
   }
 }
 
-void Dependencies::DepStream::print_dependency(Klass* witness, bool verbose) {
+void Dependencies::DepStream::print_dependency(Klass* witness, bool verbose, outputStream* st) {
   int nargs = argument_count();
   DepArgument args[max_arg_count];
   for (int j = 0; j < nargs; j++) {
     args[j] = argument(j);
   }
-  Dependencies::print_dependency(type(), nargs, args, witness);
+  Dependencies::print_dependency(type(), nargs, args, witness, st);
   if (verbose) {
     if (_code != NULL) {
-      tty->print("  code: ");
-      _code->print_value_on(tty);
-      tty->cr();
+      st->print("  code: ");
+      _code->print_value_on(st);
+      st->cr();
     }
   }
 }
--- a/src/share/vm/code/dependencies.hpp	Tue Feb 17 14:07:13 2015 +0100
+++ b/src/share/vm/code/dependencies.hpp	Tue Feb 17 14:49:05 2015 +0100
@@ -508,7 +508,7 @@
                                   Klass* witness = NULL);
   static void print_dependency(DepType dept,
                                int nargs, DepArgument args[],
-                               Klass* witness = NULL);
+                               Klass* witness = NULL, outputStream* st = tty);
 
  private:
   // helper for encoding common context types as zero:
@@ -605,7 +605,7 @@
     void log_dependency(Klass* witness = NULL);
 
     // Print the current dependency to tty.
-    void print_dependency(Klass* witness = NULL, bool verbose = false);
+    void print_dependency(Klass* witness = NULL, bool verbose = false, outputStream* st = tty);
   };
   friend class Dependencies::DepStream;
 
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Tue Feb 17 14:07:13 2015 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Tue Feb 17 14:49:05 2015 +0100
@@ -468,7 +468,7 @@
       id = CompileBroker::assign_compile_id_unlocked(Thread::current(), method, entry_bci);
     }
     result = GraalEnv::register_method(method, nm, entry_bci, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
-        GraalCompiler::instance(), _debug_recorder, _dependencies, env, id, false, installed_code, speculation_log);
+        GraalCompiler::instance(), _debug_recorder, _dependencies, env, id, false, installed_code, compiled_code, speculation_log);
     cb = nm;
   }
 
--- a/src/share/vm/graal/graalEnv.cpp	Tue Feb 17 14:07:13 2015 +0100
+++ b/src/share/vm/graal/graalEnv.cpp	Tue Feb 17 14:49:05 2015 +0100
@@ -421,11 +421,12 @@
 // ------------------------------------------------------------------
 // Check for changes to the system dictionary during compilation
 // class loads, evolution, breakpoints
-bool GraalEnv::check_for_system_dictionary_modification(Dependencies* dependencies, GraalEnv* env) {
+bool GraalEnv::check_for_system_dictionary_modification(Dependencies* dependencies, Handle compiled_code, GraalEnv* env, TRAPS) {
   // If JVMTI capabilities were enabled during compile, the compilation is invalidated.
   if (env != NULL) {
     if (!env->_jvmti_can_hotswap_or_post_breakpoint && JvmtiExport::can_hotswap_or_post_breakpoint()) {
-      // Hotswapping or breakpointing was enabled during compilation
+      Handle message = java_lang_String::create_from_str("Hotswapping or breakpointing was enabled during compilation", THREAD);
+      HotSpotCompiledNmethod::set_installationFailureMessage(compiled_code, message());
       return false;
     }
   }
@@ -440,8 +441,13 @@
   }
 
   for (Dependencies::DepStream deps(dependencies); deps.next(); ) {
-    Klass*  witness = deps.check_dependency();
+    Klass* witness = deps.check_dependency();
     if (witness != NULL) {
+      ResourceMark rm;
+      stringStream st;
+      deps.print_dependency(witness, true, &st);
+      Handle message = java_lang_String::create_from_str(st.as_string(), THREAD);
+      HotSpotCompiledNmethod::set_installationFailureMessage(compiled_code, message());
       return false;
     }
     if (LogCompilation) {
@@ -470,6 +476,7 @@
                                 int compile_id,
                                 bool has_unsafe_access,
                                 Handle installed_code,
+                                Handle compiled_code,
                                 Handle speculation_log) {
   GRAAL_EXCEPTION_CONTEXT;
   NMethodSweeper::possibly_sweep();
@@ -487,7 +494,7 @@
     dependencies->encode_content_bytes();
 
     // Check for {class loads, evolution, breakpoints} during compilation
-    if (!check_for_system_dictionary_modification(dependencies, env)) {
+    if (!check_for_system_dictionary_modification(dependencies, compiled_code, env, THREAD)) {
       // While not a true deoptimization, it is a preemptive decompile.
       MethodData* mdp = method()->method_data();
       if (mdp != NULL) {
--- a/src/share/vm/graal/graalEnv.hpp	Tue Feb 17 14:07:13 2015 +0100
+++ b/src/share/vm/graal/graalEnv.hpp	Tue Feb 17 14:49:05 2015 +0100
@@ -133,7 +133,7 @@
 
   // Helper routine for determining the validity of a compilation
   // with respect to concurrent class loading.
-  static bool check_for_system_dictionary_modification(Dependencies* target, GraalEnv* env);
+  static bool check_for_system_dictionary_modification(Dependencies* target, Handle compiled_code, GraalEnv* env, TRAPS);
 
 public:
   CompileTask* task() { return _task; }
@@ -156,6 +156,7 @@
                        int                       compile_id,
                        bool                      has_unsafe_access,
                        Handle                    installed_code,
+                       Handle                    compiled_code,
                        Handle                    speculation_log);
 
   // converts the Klass* representing the holder of a method into a
--- a/src/share/vm/graal/graalJavaAccess.hpp	Tue Feb 17 14:07:13 2015 +0100
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Tue Feb 17 14:49:05 2015 +0100
@@ -82,6 +82,7 @@
   end_class                                                                                                                                                    \
   start_class(HotSpotCompiledNmethod)                                                                                                                          \
     oop_field(HotSpotCompiledNmethod, method, "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;")                                                     \
+    oop_field(HotSpotCompiledNmethod, installationFailureMessage, "Ljava/lang/String;")                                                                        \
     int_field(HotSpotCompiledNmethod, entryBCI)                                                                                                                \
     int_field(HotSpotCompiledNmethod, id)                                                                                                                      \
     long_field(HotSpotCompiledNmethod, graalEnv)                                                                                                               \