changeset 6453:3bba61323b38

added VMErrorNode intrinsic to support handling fatal errors in snippets
author Doug Simon <doug.simon@oracle.com>
date Thu, 27 Sep 2012 14:23:04 +0200
parents a89a18a57617
children 5a2c5d93f5c8
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java src/cpu/x86/vm/c1_Runtime1_x86.cpp src/share/vm/c1/c1_Runtime1.cpp src/share/vm/c1/c1_Runtime1.hpp
diffstat 7 files changed, 115 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Sep 26 21:48:07 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Sep 27 14:23:04 2012 +0200
@@ -180,6 +180,7 @@
     public long fastMonitorEnterStub;
     public long fastMonitorExitStub;
     public long verifyOopStub;
+    public long vmErrorStub;
 
     // special registers
     public final Register threadRegister = AMD64.r15;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Thu Sep 27 14:23:04 2012 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.snippets.*;
+
+/**
+ * Causes the VM to exit with a description of the current Java location
+ * and an optional {@linkplain Log#printf(String, long) formatted} error message specified.
+ */
+public final class VMErrorNode extends FixedWithNextNode implements LIRGenLowerable {
+
+    @Input private ValueNode format;
+    @Input private ValueNode value;
+
+    public VMErrorNode(ValueNode format, ValueNode value) {
+        super(StampFactory.forVoid());
+        this.format = format;
+        this.value = value;
+    }
+
+    @Override
+    public void generate(LIRGenerator gen) {
+        long vmErrorStub = HotSpotGraalRuntime.getInstance().getConfig().vmErrorStub;
+        LIRFrameState state = gen.state();
+        BytecodePosition pos = state.topFrame;
+        String where = CodeUtil.append(new StringBuilder(100), pos).toString();
+        Kind[] signature = new Kind[] {Kind.Object, Kind.Object, Kind.Long};
+        gen.emitCall(vmErrorStub, Kind.Void, signature, true, Constant.forObject(where), gen.operand(format), gen.operand(value));
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic
+    public static void vmError(String format, long value) {
+        throw new GraalInternalError("");
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java	Wed Sep 26 21:48:07 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java	Thu Sep 27 14:23:04 2012 +0200
@@ -25,6 +25,7 @@
 import static com.oracle.graal.hotspot.nodes.BeginLockScopeNode.*;
 import static com.oracle.graal.hotspot.nodes.DirectCompareAndSwapNode.*;
 import static com.oracle.graal.hotspot.nodes.EndLockScopeNode.*;
+import static com.oracle.graal.hotspot.nodes.VMErrorNode.*;
 import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*;
 import static com.oracle.graal.snippets.nodes.DirectObjectStoreNode.*;
 
@@ -69,7 +70,7 @@
      */
     private static final String TRACE_METHOD_FILTER = System.getProperty("graal.monitors.trace.methodFilter");
 
-    public static final boolean CHECK_BALANCED_MONITORS = Boolean.getBoolean("graal.monitors.checkBalance");
+    public static final boolean CHECK_BALANCED_MONITORS = Boolean.getBoolean("graal.monitors.checkBalanced");
 
     @Snippet
     public static void monitorenter(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) {
@@ -380,9 +381,7 @@
         final Word counter = MonitorCounterNode.counter(wordKind());
         final int count = UnsafeLoadNode.load(counter, 0, 0, Kind.Int);
         if (count != 0) {
-            Log.print(errMsg);
-            Log.println(count);
-            DirectObjectStoreNode.storeInt(Word.zero(), 0, 0, count + 1);
+            vmError(errMsg, count);
         }
     }
 
@@ -519,7 +518,7 @@
                     List<ReturnNode> rets = graph.getNodes().filter(ReturnNode.class).snapshot();
                     for (ReturnNode ret : rets) {
                         returnType = checkCounter.signature().returnType(checkCounter.holder());
-                        ConstantNode errMsg = ConstantNode.forObject("unbalanced monitors in " + MetaUtil.format("%H.%n(%p)", graph.method()), runtime, graph);
+                        ConstantNode errMsg = ConstantNode.forObject("unbalanced monitors in " + MetaUtil.format("%H.%n(%p)", graph.method()) + ", count = %d", runtime, graph);
                         callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter, new ValueNode[] {errMsg}, returnType));
                         invoke = graph.add(new InvokeNode(callTarget, 0, -1));
                         List<ValueNode> stack = Collections.emptyList();
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java	Wed Sep 26 21:48:07 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java	Thu Sep 27 14:23:04 2012 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.snippets;
 
+import java.io.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
@@ -31,7 +33,7 @@
 //JaCoCo Exclude
 
 /**
- * Provides printf-like debug facility. This should only be used in {@linkplain Snippet snippets}.
+ * Provides {@link PrintStream}-like logging facility. This should only be used in {@linkplain Snippet snippets}.
  */
 public final class Log {
 
@@ -83,7 +85,10 @@
     }
 
     /**
-     * @param format a C style printf format value - must be between 0 and 1024 characters
+     * Prints a formatted string to the log stream.
+     *
+     * @param format a C style printf format value that can contain at most one conversion specifier (i.e., a sequence
+     *            of characters starting with '%').
      */
     public static void printf(String format, long value) {
         printf(RuntimeCall.LogPrintf, format, value);
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Wed Sep 26 21:48:07 2012 +0200
+++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Thu Sep 27 14:23:04 2012 +0200
@@ -1917,6 +1917,18 @@
       break;
     }
 
+    case graal_vm_error_id: {
+      __ enter();
+      oop_maps = new OopMapSet();
+      OopMap* oop_map = save_live_registers(sasm, 0);
+      int call_offset = __ call_RT(noreg, noreg, (address)graal_vm_error, j_rarg0, j_rarg1, j_rarg2);
+      oop_maps->add_gc_map(call_offset, oop_map);
+      restore_live_registers(sasm);
+      __ leave();
+      __ ret(0);
+      break;
+    }
+
     case graal_log_printf_id: {
       __ enter();
       oop_maps = new OopMapSet();
--- a/src/share/vm/c1/c1_Runtime1.cpp	Wed Sep 26 21:48:07 2012 +0200
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Thu Sep 27 14:23:04 2012 +0200
@@ -761,68 +761,40 @@
   bool newline = flags & LOG_OBJECT_NEWLINE;
   if (!string) {
     if (!address && obj->is_oop_or_null(true)) {
-      char buf[400];
-      tty->print("%s@%p", obj->klass()->klass_part()->name()->as_C_string(buf, 400), obj);
+      char buf[O_BUFLEN];
+      tty->print("%s@%p", obj->klass()->klass_part()->name()->as_C_string(buf, O_BUFLEN), obj);
     } else {
       tty->print("%p", obj);
     }
   } else {
+    ResourceMark rm;
     assert(obj != NULL && java_lang_String::is_instance(obj), "must be");
-
-    typeArrayOop value  = java_lang_String::value(obj);
-    int          offset = java_lang_String::offset(obj);
-    int          length = java_lang_String::length(obj);
-
-    if (length != 0) {
-      int printLength = MIN2(length, 1024);
-      if (value == NULL) {
-        // This can happen if, e.g., printing a String
-        // object before its initializer has been called
-        tty->print("null");
-      } else if (printLength < 256 - 1) {
-        // Use an intermediate buffer to try and prevent interlacing of multi-threaded output
-        char buf[256];
-        for (int index = 0; index < printLength; index++) {
-          buf[index] = value->char_at(index + offset);
-        }
-        buf[printLength] = 0;
-        tty->print("%s", buf);
-        if (printLength < length) {
-          tty->print("... (%d more)", length - printLength);
-        }
-      } else {
-        for (int index = 0; index < printLength; index++) {
-          tty->print("%c", value->char_at(index + offset));
-        }
-        if (printLength < length) {
-          tty->print("... (%d more)", length - printLength);
-        }
-      }
-    }
+    char *buf = java_lang_String::as_utf8_string(obj);
+    tty->print(buf);
   }
   if (newline) {
     tty->cr();
   }
 JRT_END
 
-JRT_ENTRY(void, Runtime1::graal_log_printf(JavaThread* thread, oop format, jlong val))
-  char buf[1025];
-  assert(format != NULL && java_lang_String::is_instance(format), "must be");
-
-  typeArrayOop value  = java_lang_String::value(format);
-  int          offset = java_lang_String::offset(format);
-  int          length = java_lang_String::length(format);
+JRT_ENTRY(void, Runtime1::graal_vm_error(JavaThread* thread, oop where, oop format, jlong value))
+  ResourceMark rm;
+  assert(where == NULL || java_lang_String::is_instance(where), "must be");
+  const char *error_msg = where == NULL ? "<internal Graal error>" : java_lang_String::as_utf8_string(where);
+  char *detail_msg = NULL;
+  if (format != NULL) {
+    const char* buf = java_lang_String::as_utf8_string(format);
+    int detail_msg_length = strlen(buf) * 2;
+    detail_msg = (char *) NEW_RESOURCE_ARRAY(u_char, detail_msg_length);
+    jio_snprintf(detail_msg, detail_msg_length, buf, value);
+  }
+  report_vm_error(__FILE__, __LINE__, error_msg, detail_msg);
+JRT_END
 
-  assert(value != NULL, "fmtString must be a literal");
-  assert(length >= 0 && length <= 1024, "format must be between 0 and 1024 characters");
-  length = MIN2(length, 1024);
-
-  int index = 0;
-  while (index < length) {
-    buf[index] = value->char_at(index + offset);
-    index++;
-  }
-  buf[index++] = 0;
+JRT_ENTRY(void, Runtime1::graal_log_printf(JavaThread* thread, oop format, jlong val))
+  ResourceMark rm;
+  assert(format != NULL && java_lang_String::is_instance(format), "must be");
+  char *buf = java_lang_String::as_utf8_string(format);
   tty->print(buf, val);
 JRT_END
 
--- a/src/share/vm/c1/c1_Runtime1.hpp	Wed Sep 26 21:48:07 2012 +0200
+++ b/src/share/vm/c1/c1_Runtime1.hpp	Thu Sep 27 14:23:04 2012 +0200
@@ -76,7 +76,8 @@
   stub(graal_arithmetic_drem)        \
   stub(graal_monitorenter)           \
   stub(graal_monitorexit)            \
-  stub(graal_verify_oop)         \
+  stub(graal_verify_oop)             \
+  stub(graal_vm_error)               \
   stub(graal_set_deopt_info)         \
   stub(graal_create_null_pointer_exception) \
   stub(graal_create_out_of_bounds_exception) \
@@ -207,6 +208,7 @@
   static void graal_generic_callback(JavaThread* thread, oop _callback, oop _argument);
   static void graal_monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock);
   static void graal_monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock);
+  static void graal_vm_error(JavaThread* thread, oop where, oop format, jlong value);
   static void graal_log_printf(JavaThread* thread, oop format, jlong value);
   static void graal_log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline);