changeset 14731:0cb5c4d276d4

use raw data support to fix incorrect use of String.intern() for embedding strings in code
author Doug Simon <doug.simon@oracle.com>
date Tue, 25 Mar 2014 13:57:48 +0100
parents 209cf6959421
children 56621a6eed29
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java src/share/vm/graal/graalRuntime.cpp src/share/vm/graal/graalRuntime.hpp
diffstat 4 files changed, 43 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Tue Mar 25 13:56:52 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Tue Mar 25 13:57:48 2014 +0100
@@ -22,18 +22,18 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import java.util.*;
 
-import com.oracle.graal.nodes.*;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
 
 /**
- * Converts a compile-time constant Java string into a malloc'ed C string. The malloc'ed string is
- * never reclaimed so this should only be used for strings in permanent code such as compiled stubs.
+ * Converts a compile-time constant Java string into a C string installed with the generated code.
  */
-public final class CStringNode extends FloatingNode implements Lowerable {
+public final class CStringNode extends FloatingNode implements LIRGenLowerable {
 
     private final String string;
 
@@ -42,16 +42,18 @@
         this.string = string;
     }
 
-    @Override
-    public void lower(LoweringTool tool) {
-        byte[] formatBytes = string.getBytes();
-        long cstring = unsafe.allocateMemory(formatBytes.length + 1);
-        for (int i = 0; i < formatBytes.length; i++) {
-            unsafe.putByte(cstring + i, formatBytes[i]);
-        }
-        unsafe.putByte(cstring + formatBytes.length, (byte) 0);
-        ConstantNode replacement = ConstantNode.forLong(cstring, graph());
-        graph().replaceFloating(this, replacement);
+    public void generate(LIRGenerator gen) {
+        gen.setResult(this, gen.emitMove(new RawDataValue(gen.target().wordKind, toCString(string))));
+    }
+
+    /**
+     * Converts a String to a null terminated byte array suitable for use as a C string value.
+     */
+    public static byte[] toCString(String value) {
+        byte[] bytes = value.getBytes();
+        byte[] nulTerminated = Arrays.copyOf(bytes, bytes.length + 1);
+        nulTerminated[bytes.length] = 0;
+        return nulTerminated;
     }
 
     @NodeIntrinsic(setStampFromReturnType = true)
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Tue Mar 25 13:56:52 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Tue Mar 25 13:57:48 2014 +0100
@@ -22,6 +22,9 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import static com.oracle.graal.api.meta.MetaUtil.*;
+import static com.oracle.graal.hotspot.nodes.CStringNode.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
@@ -38,7 +41,7 @@
 
     private final String format;
     @Input private ValueNode value;
-    public static final ForeignCallDescriptor VM_ERROR = new ForeignCallDescriptor("vm_error", void.class, Object.class, Object.class, long.class);
+    public static final ForeignCallDescriptor VM_ERROR = new ForeignCallDescriptor("vm_error", void.class, long.class, long.class, long.class);
 
     private VMErrorNode(String format, ValueNode value) {
         super(StampFactory.forVoid());
@@ -48,14 +51,22 @@
 
     @Override
     public void generate(LIRGenerator gen) {
-        String whereString = "in compiled code for " + graph();
-
-        // As these strings will end up embedded as oops in the code, they
-        // must be interned or else they will cause the nmethod to be unloaded
-        // (nmethods are a) weak GC roots and b) unloaded if any of their
-        // embedded oops become unreachable).
-        Constant whereArg = Constant.forObject(whereString.intern());
-        Constant formatArg = Constant.forObject(format.intern());
+        String whereString;
+        if (getState() != null) {
+            String nl = CodeUtil.NEW_LINE;
+            StringBuilder sb = new StringBuilder("in compiled code associated with frame state:");
+            FrameState fs = getState();
+            while (fs != null) {
+                MetaUtil.appendLocation(sb.append(nl).append("\t"), fs.method(), fs.bci);
+                fs = fs.outerFrameState();
+            }
+            whereString = sb.toString();
+        } else {
+            ResolvedJavaMethod method = graph().method();
+            whereString = "in compiled code for " + (method == null ? graph().toString() : format("%H.%n(%p)", method));
+        }
+        Value whereArg = new RawDataValue(gen.target().wordKind, toCString(whereString));
+        Value formatArg = new RawDataValue(gen.target().wordKind, toCString(format));
 
         ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(VMErrorNode.VM_ERROR);
         gen.emitForeignCall(linkage, null, whereArg, formatArg, gen.operand(value));
--- a/src/share/vm/graal/graalRuntime.cpp	Tue Mar 25 13:56:52 2014 +0100
+++ b/src/share/vm/graal/graalRuntime.cpp	Tue Mar 25 13:57:48 2014 +0100
@@ -438,13 +438,12 @@
   return (jint)ret;
 JRT_END
 
-JRT_ENTRY(void, GraalRuntime::vm_error(JavaThread* thread, oopDesc* where, oopDesc* format, jlong value))
+JRT_ENTRY(void, GraalRuntime::vm_error(JavaThread* thread, jlong where, jlong 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);
+  const char *error_msg = where == 0L ? "<internal Graal error>" : (char*) (address) where;
   char *detail_msg = NULL;
-  if (format != NULL) {
-    const char* buf = java_lang_String::as_utf8_string(format);
+  if (format != 0L) {
+    const char* buf = (char*) (address) format;
     size_t 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);
--- a/src/share/vm/graal/graalRuntime.hpp	Tue Mar 25 13:56:52 2014 +0100
+++ b/src/share/vm/graal/graalRuntime.hpp	Tue Mar 25 13:57:48 2014 +0100
@@ -43,7 +43,7 @@
   static void monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock);
   static void create_null_exception(JavaThread* thread);
   static void create_out_of_bounds_exception(JavaThread* thread, jint index);
-  static void vm_error(JavaThread* thread, oopDesc* where, oopDesc* format, jlong value);
+  static void vm_error(JavaThread* thread, jlong where, jlong format, jlong value);
   static oopDesc* load_and_clear_exception(JavaThread* thread);
   static void log_printf(JavaThread* thread, oopDesc* format, jlong v1, jlong v2, jlong v3);
   static void log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline);