# HG changeset patch # User Doug Simon # Date 1339539315 -7200 # Node ID 69358a2182a3e77de8145f9eeae3f013539bca35 # Parent 8e6622e1fb7e5f1750afe1f11e907ec269bdaddd added printf-like facility (Log.java) for logging debug output in snippets diff -r 8e6622e1fb7e -r 69358a2182a3 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCall.java --- 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; + } } diff -r 8e6622e1fb7e -r 69358a2182a3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java --- 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); diff -r 8e6622e1fb7e -r 69358a2182a3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java --- 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) { diff -r 8e6622e1fb7e -r 69358a2182a3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java --- 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(); diff -r 8e6622e1fb7e -r 69358a2182a3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java --- 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); } diff -r 8e6622e1fb7e -r 69358a2182a3 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java --- /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(""); + } +} diff -r 8e6622e1fb7e -r 69358a2182a3 src/share/vm/c1/c1_Runtime1.cpp --- 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)) diff -r 8e6622e1fb7e -r 69358a2182a3 src/share/vm/c1/c1_Runtime1.hpp --- 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); diff -r 8e6622e1fb7e -r 69358a2182a3 src/share/vm/graal/graalCodeInstaller.cpp --- 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; diff -r 8e6622e1fb7e -r 69358a2182a3 src/share/vm/graal/graalJavaAccess.hpp --- 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 \