changeset 5580:69358a2182a3

added printf-like facility (Log.java) for logging debug output in snippets
author Doug Simon <doug.simon@oracle.com>
date Wed, 13 Jun 2012 00:15:15 +0200
parents 8e6622e1fb7e
children 9911227e6dd3
files graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCall.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java src/share/vm/c1/c1_Runtime1.cpp src/share/vm/c1/c1_Runtime1.hpp src/share/vm/graal/graalCodeInstaller.cpp src/share/vm/graal/graalJavaAccess.hpp
diffstat 10 files changed, 257 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCall.java	Tue Jun 12 23:42:31 2012 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCall.java	Wed Jun 13 00:15:15 2012 +0200
@@ -46,7 +46,9 @@
     ArithmeticCos(Double, Double),
     ArithmeticTan(Double, Double),
     ArithmeticSin(Double, Double),
-    GenericCallback(Object, Object, Object);
+    GenericCallback(Object, Object, Object),
+    LogPrimitive(Void, Int, Long, Boolean),
+    LogObject(Void, Object, Boolean, Boolean);
 
     public final Kind resultKind;
     public final Kind[] arguments;
@@ -55,4 +57,13 @@
         this.resultKind = resultKind;
         this.arguments = args;
     }
+
+    public boolean hasSideEffect() {
+        switch (this) {
+            case LogObject:
+            case LogPrimitive:
+                return false;
+        }
+        return true;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Tue Jun 12 23:42:31 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Wed Jun 13 00:15:15 2012 +0200
@@ -229,6 +229,7 @@
         }
         int slot = localsSize + stackSize - popSlots;
         for (int i = 0; i < pushSlots; i++) {
+            assert pushedValues[i] == null || !pushedValues[i].kind().isVoid();
             other.setValueAt(slot++, pushedValues[i]);
         }
         other.virtualObjectMappings.setAll(virtualObjectMappings);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Tue Jun 12 23:42:31 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Wed Jun 13 00:15:15 2012 +0200
@@ -135,6 +135,7 @@
 
     @Override
     public void intrinsify(Node node) {
+        assert !(node instanceof ValueNode) || ((ValueNode) node).kind().isVoid() == kind().isVoid();
         MethodCallTargetNode call = callTarget;
         FrameState stateAfter = stateAfter();
         if (node instanceof StateSplit) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Tue Jun 12 23:42:31 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Jun 13 00:15:15 2012 +0200
@@ -175,6 +175,7 @@
 
     @Override
     public void intrinsify(Node node) {
+        assert !(node instanceof ValueNode) || ((ValueNode) node).kind().isVoid() == kind().isVoid();
         MethodCallTargetNode call = callTarget;
         FrameState state = stateAfter();
         killExceptionEdge();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Tue Jun 12 23:42:31 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Wed Jun 13 00:15:15 2012 +0200
@@ -45,6 +45,11 @@
     }
 
     @Override
+    public boolean hasSideEffect() {
+        return call.hasSideEffect();
+    }
+
+    @Override
     public void generate(LIRGeneratorTool gen) {
         gen.emitRuntimeCall(this);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java	Wed Jun 13 00:15:15 2012 +0200
@@ -0,0 +1,163 @@
+/*
+ * 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.snippets;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.nodes.extended.*;
+
+/**
+ * Provides printf-like debug facility. This should only be used in {@linkplain Snippet snippets}.
+ */
+public final class Log {
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic(RuntimeCallNode.class)
+    private static void log(@ConstantNodeParameter RuntimeCall logObject, Object object, boolean newline, boolean string) {
+        throw new UnsupportedOperationException("This method may only be compiled with the Graal compiler");
+    }
+
+    @SuppressWarnings("unused")
+    @NodeIntrinsic(RuntimeCallNode.class)
+    private static void log(@ConstantNodeParameter RuntimeCall logPrimitive, int typeChar, long value, boolean newline) {
+        throw new UnsupportedOperationException("This method may only be compiled with the Graal compiler");
+    }
+
+    public static void print(boolean value) {
+        log(RuntimeCall.LogPrimitive, Kind.Boolean.typeChar, value ? 1L : 0L, false);
+    }
+
+    public static void print(byte value) {
+        log(RuntimeCall.LogPrimitive, Kind.Byte.typeChar, value, false);
+    }
+
+    public static void print(char value) {
+        log(RuntimeCall.LogPrimitive, Kind.Char.typeChar, value, false);
+    }
+
+    public static void print(short value) {
+        log(RuntimeCall.LogPrimitive, Kind.Short.typeChar, value, false);
+    }
+
+    public static void print(int value) {
+        log(RuntimeCall.LogPrimitive, Kind.Int.typeChar, value, false);
+    }
+
+    public static void print(long value) {
+        log(RuntimeCall.LogPrimitive, Kind.Long.typeChar, value, false);
+    }
+
+    public static void print(float value) {
+        if (Float.isNaN(value)) {
+            print("NaN");
+        } else if (value == Float.POSITIVE_INFINITY) {
+            print("Infinity");
+        } else if (value == Float.NEGATIVE_INFINITY) {
+            print("-Infinity");
+        } else {
+            log(RuntimeCall.LogPrimitive, Kind.Float.typeChar, Float.floatToRawIntBits(value), false);
+        }
+    }
+
+    public static void print(double value) {
+        if (Double.isNaN(value)) {
+            print("NaN");
+        } else if (value == Double.POSITIVE_INFINITY) {
+            print("Infinity");
+        } else if (value == Double.NEGATIVE_INFINITY) {
+            print("-Infinity");
+        } else {
+            log(RuntimeCall.LogPrimitive, Kind.Double.typeChar, Double.doubleToRawLongBits(value), false);
+        }
+    }
+
+    public static void print(String value) {
+        log(RuntimeCall.LogObject, value, false, true);
+    }
+
+    public static void printAddress(Object o) {
+        log(RuntimeCall.LogObject, o, false, false);
+    }
+
+    public static void println(boolean value) {
+        log(RuntimeCall.LogPrimitive, Kind.Boolean.typeChar, value ? 1L : 0L, true);
+    }
+
+    public static void println(byte value) {
+        log(RuntimeCall.LogPrimitive, Kind.Byte.typeChar, value, true);
+    }
+
+    public static void println(char value) {
+        log(RuntimeCall.LogPrimitive, Kind.Char.typeChar, value, true);
+    }
+
+    public static void println(short value) {
+        log(RuntimeCall.LogPrimitive, Kind.Short.typeChar, value, true);
+    }
+
+    public static void println(int value) {
+        log(RuntimeCall.LogPrimitive, Kind.Int.typeChar, value, true);
+    }
+
+    public static void println(long value) {
+        log(RuntimeCall.LogPrimitive, Kind.Long.typeChar, value, true);
+    }
+
+    public static void println(float value) {
+        if (Float.isNaN(value)) {
+            println("NaN");
+        } else if (value == Float.POSITIVE_INFINITY) {
+            println("Infinity");
+        } else if (value == Float.NEGATIVE_INFINITY) {
+            println("-Infinity");
+        } else {
+            log(RuntimeCall.LogPrimitive, Kind.Float.typeChar, Float.floatToRawIntBits(value), true);
+        }
+    }
+
+    public static void println(double value) {
+        if (Double.isNaN(value)) {
+            println("NaN");
+        } else if (value == Double.POSITIVE_INFINITY) {
+            println("Infinity");
+        } else if (value == Double.NEGATIVE_INFINITY) {
+            println("-Infinity");
+        } else {
+            log(RuntimeCall.LogPrimitive, Kind.Double.typeChar, Double.doubleToRawLongBits(value), true);
+        }
+    }
+
+    public static void println(String value) {
+        log(RuntimeCall.LogObject, value, true, true);
+    }
+
+    public static void printlnAddress(Object o) {
+        log(RuntimeCall.LogObject, o, true, false);
+    }
+
+    public static void println() {
+        println("");
+    }
+}
--- a/src/share/vm/c1/c1_Runtime1.cpp	Tue Jun 12 23:42:31 2012 +0200
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Wed Jun 13 00:15:15 2012 +0200
@@ -212,6 +212,8 @@
     case graal_arithmetic_frem_id:
     case graal_arithmetic_drem_id:
     case graal_set_deopt_info_id:
+    case graal_log_primitive_id:
+    case graal_log_object_id:
 #endif
       break;
 
@@ -738,7 +740,65 @@
   }
 JRT_END
 
-#endif
+JRT_ENTRY(void, Runtime1::graal_log_object(JavaThread* thread, oop obj, jboolean newline, jboolean string))
+  if (!string) {
+    tty->print("%p", obj);
+  } else {
+    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) {
+      if (value == NULL) {
+        // This can happen if, e.g., printing a String
+        // object before its initializer has been called
+        tty->print("null");
+      } else if (length < 256 - 1) {
+        // Use an intermediate buffer to try and prevent interlacing of multi-threaded output
+        char buf[256];
+        for (int index = 0; index < length; index++) {
+          buf[index] = value->char_at(index + offset);
+        }
+        buf[length] = 0;
+        tty->print("%s", buf);
+      } else {
+        for (int index = 0; index < length; index++) {
+          tty->print("%c", value->char_at(index + offset));
+        }
+      }
+    }
+  }
+  if (newline) {
+    tty->cr();
+  }
+JRT_END
+
+JRT_ENTRY(void, Runtime1::graal_log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline))
+  union {
+      jlong l;
+      jdouble d;
+      jfloat f;
+  } uu;
+  uu.l = value;
+  switch (typeChar) {
+    case 'z': tty->print(value == 0 ? "false" : "true"); break;
+    case 'b': tty->print("%d", (jbyte) value); break;
+    case 'c': tty->print("%c", (jchar) value); break;
+    case 's': tty->print("%d", (jshort) value); break;
+    case 'i': tty->print("%d", (jint) value); break;
+    case 'f': tty->print("%f", uu.f); break;
+    case 'j': tty->print(INT64_FORMAT, value); break;
+    case 'd': tty->print("%lf", uu.d); break;
+    default: assert(false, "unknown typeChar"); break;
+  }
+  if (newline) {
+    tty->cr();
+  }
+JRT_END
+
+#endif /* GRAAL */
 
 
 JRT_ENTRY_NO_ASYNC(void, Runtime1::monitorenter(JavaThread* thread, oopDesc* obj, BasicObjectLock* lock))
--- a/src/share/vm/c1/c1_Runtime1.hpp	Tue Jun 12 23:42:31 2012 +0200
+++ b/src/share/vm/c1/c1_Runtime1.hpp	Wed Jun 13 00:15:15 2012 +0200
@@ -81,6 +81,8 @@
   stub(graal_create_null_pointer_exception) \
   stub(graal_create_out_of_bounds_exception) \
   stub(graal_generic_callback)       \
+  stub(graal_log_object)             \
+  stub(graal_log_primitive)          \
   last_entry(number_of_ids)
 #else
 #define RUNTIME1_STUBS(stub, last_entry) \
@@ -204,6 +206,8 @@
   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_log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline);
+  static void graal_log_object(JavaThread* thread, oop msg, jboolean newline, jboolean string);
 #endif
 
   static void deoptimize(JavaThread* thread);
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Tue Jun 12 23:42:31 2012 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Wed Jun 13 00:15:15 2012 +0200
@@ -581,6 +581,12 @@
   } else if (runtime_call == RuntimeCall::GenericCallback()) {
     target_addr = Runtime1::entry_for(Runtime1::graal_generic_callback_id);
     TRACE_graal_3("RuntimeCall::GenericCallback()");
+  } else if (runtime_call == RuntimeCall::LogPrimitive()) {
+    target_addr = Runtime1::entry_for(Runtime1::graal_log_primitive_id);
+    TRACE_graal_3("RuntimeCall::LogPrimitive()");
+  } else if (runtime_call == RuntimeCall::LogObject()) {
+    target_addr = Runtime1::entry_for(Runtime1::graal_log_object_id);
+    TRACE_graal_3("RuntimeCall::LogObject()");
   } else {
     runtime_call->print();
     fatal("runtime_call not implemented");
@@ -598,7 +604,7 @@
 
   if (target_klass->is_subclass_of(SystemDictionary::Long_klass())) {
     global_stub = target;
-  } else if (target_klass->name() == vmSymbols::com_oracle_graal_api_code_RuntimeCall()) {
+  } else if (target->is_a(RuntimeCall::klass())) {
     runtime_call = target;
   } else {
     hotspot_method = target;
--- a/src/share/vm/graal/graalJavaAccess.hpp	Tue Jun 12 23:42:31 2012 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Wed Jun 13 00:15:15 2012 +0200
@@ -203,6 +203,8 @@
     static_oop_field(RuntimeCall, ArithmeticSin, "Lcom/oracle/graal/api/code/RuntimeCall;");   \
     static_oop_field(RuntimeCall, Deoptimize, "Lcom/oracle/graal/api/code/RuntimeCall;");      \
     static_oop_field(RuntimeCall, GenericCallback, "Lcom/oracle/graal/api/code/RuntimeCall;"); \
+    static_oop_field(RuntimeCall, LogPrimitive, "Lcom/oracle/graal/api/code/RuntimeCall;");    \
+    static_oop_field(RuntimeCall, LogObject, "Lcom/oracle/graal/api/code/RuntimeCall;");       \
   end_class                                                                             \
   start_class(JavaMethod)                                                                 \
   end_class                                                                             \