# HG changeset patch # User Doug Simon # Date 1366646354 -7200 # Node ID bb2447c64055b48a784d746c16c0122f4ba4052f # Parent ee3a9188c65e9b97c215a3faeaaffae801f850b3 strings used in compiled stubs are lowered to malloc'ed C strings so that there are no embedded oops (for the strings) in the resulting installed code diff -r ee3a9188c65e -r bb2447c64055 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Apr 22 17:09:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Apr 22 17:59:14 2013 +0200 @@ -363,6 +363,7 @@ public long logPrimitiveStub; public long logObjectStub; public long logPrintfStub; + public long stubPrintfStub; public int deoptReasonNone; public long threadIsInterruptedStub; public long identityHashCodeStub; diff -r ee3a9188c65e -r bb2447c64055 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Apr 22 17:09:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Apr 22 17:59:14 2013 +0200 @@ -262,6 +262,14 @@ /* arg2: value */ Kind.Long, /* arg3: value */ Kind.Long)); + addRuntimeCall(Stub.STUB_PRINTF, config.stubPrintfStub, + /* temps */ null, + /* ret */ ret(Kind.Void), + /* arg0: format */ javaCallingConvention(Kind.Long, + /* arg1: value */ Kind.Long, + /* arg2: value */ Kind.Long, + /* arg3: value */ Kind.Long)); + addRuntimeCall(LOG_OBJECT, config.logObjectStub, /* temps */ null, /* ret */ ret(Kind.Void), diff -r ee3a9188c65e -r bb2447c64055 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java Mon Apr 22 17:59:14 2013 +0200 @@ -0,0 +1,61 @@ +/* + * 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 static com.oracle.graal.graph.UnsafeAccess.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +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. + */ +public final class CStringNode extends FloatingNode implements Lowerable { + + private final String string; + + public CStringNode(String string) { + super(StampFactory.forWord()); + 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); + StructuredGraph graph = (StructuredGraph) graph(); + ConstantNode replacement = ConstantNode.forLong(cstring, graph); + graph.replaceFloating(this, replacement); + } + + @NodeIntrinsic + public static native Word cstring(@ConstantNodeParameter String string); +} diff -r ee3a9188c65e -r bb2447c64055 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Mon Apr 22 17:09:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Mon Apr 22 17:59:14 2013 +0200 @@ -208,40 +208,4 @@ private static boolean forceSlowPath() { return Boolean.getBoolean("graal.newInstanceStub.forceSlowPath"); } - - static void log(boolean enabled, String format, long value) { - if (enabled) { - Log.printf(format, value); - } - } - - static void log(boolean enabled, String format, WordBase value) { - if (enabled) { - Log.printf(format, value.rawValue()); - } - } - - static void log(boolean enabled, String format, long v1, long v2) { - if (enabled) { - Log.printf(format, v1, v2); - } - } - - static void log(boolean enabled, String format, Word v1, long v2) { - if (enabled) { - Log.printf(format, v1.rawValue(), v2); - } - } - - static void log(boolean enabled, String format, Word v1, Word v2) { - if (enabled) { - Log.printf(format, v1.rawValue(), v2.rawValue()); - } - } - - static void log(boolean enabled, String format, long v1, long v2, long v3) { - if (enabled) { - Log.printf(format, v1, v2, v3); - } - } } diff -r ee3a9188c65e -r bb2447c64055 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Mon Apr 22 17:09:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Mon Apr 22 17:59:14 2013 +0200 @@ -22,19 +22,25 @@ */ package com.oracle.graal.hotspot.stubs; +import static com.oracle.graal.hotspot.nodes.CStringNode.*; + import java.util.*; import java.util.concurrent.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; +import com.oracle.graal.graph.Node.ConstantNodeParameter; +import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.PhasePlan.PhasePosition; @@ -43,6 +49,7 @@ import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; import com.oracle.graal.replacements.SnippetTemplate.Arguments; import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; +import com.oracle.graal.word.*; /** * Base class for implementing some low level code providing the out-of-line slow path for a @@ -156,4 +163,52 @@ } return code; } + + static void log(boolean enabled, String format, long value) { + if (enabled) { + printf(format, value); + } + } + + static void log(boolean enabled, String format, WordBase value) { + if (enabled) { + printf(format, value.rawValue()); + } + } + + static void log(boolean enabled, String format, Word v1, long v2) { + if (enabled) { + printf(format, v1.rawValue(), v2); + } + } + + static void log(boolean enabled, String format, Word v1, Word v2) { + if (enabled) { + printf(format, v1.rawValue(), v2.rawValue()); + } + } + + public static final Descriptor STUB_PRINTF = new Descriptor("stubPrintf", false, void.class, Word.class, long.class, long.class, long.class); + + @NodeIntrinsic(RuntimeCallNode.class) + private static native void printf(@ConstantNodeParameter Descriptor stubPrintf, Word format, long v1, long v2, long v3); + + /** + * 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 '%'). + * @param value the value associated with the conversion specifier + */ + public static void printf(String format, long value) { + printf(STUB_PRINTF, cstring(format), value, 0L, 0L); + } + + public static void printf(String format, long v1, long v2) { + printf(STUB_PRINTF, cstring(format), v1, v2, 0L); + } + + public static void printf(String format, long v1, long v2, long v3) { + printf(STUB_PRINTF, cstring(format), v1, v2, v3); + } } diff -r ee3a9188c65e -r bb2447c64055 src/cpu/x86/vm/graalRuntime_x86.cpp --- a/src/cpu/x86/vm/graalRuntime_x86.cpp Mon Apr 22 17:09:02 2013 +0200 +++ b/src/cpu/x86/vm/graalRuntime_x86.cpp Mon Apr 22 17:59:14 2013 +0200 @@ -972,6 +972,18 @@ break; } + case stub_printf_id: { + __ enter(); + oop_maps = new OopMapSet(); + OopMap* oop_map = save_live_registers(sasm, 4); + int call_offset = __ call_RT(noreg, noreg, (address)stub_printf, j_rarg0, j_rarg1, j_rarg2, j_rarg3); + oop_maps->add_gc_map(call_offset, oop_map); + restore_live_registers(sasm); + __ leave(); + __ ret(0); + break; + } + case log_primitive_id: { __ enter(); oop_maps = new OopMapSet(); diff -r ee3a9188c65e -r bb2447c64055 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Mon Apr 22 17:09:02 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Mon Apr 22 17:59:14 2013 +0200 @@ -773,6 +773,7 @@ set_stub("logPrimitiveStub", GraalRuntime::entry_for(GraalRuntime::log_primitive_id)); set_stub("logObjectStub", GraalRuntime::entry_for(GraalRuntime::log_object_id)); set_stub("logPrintfStub", GraalRuntime::entry_for(GraalRuntime::log_printf_id)); + set_stub("stubPrintfStub", GraalRuntime::entry_for(GraalRuntime::stub_printf_id)); set_stub("aescryptEncryptBlockStub", StubRoutines::aescrypt_encryptBlock()); set_stub("aescryptDecryptBlockStub", StubRoutines::aescrypt_decryptBlock()); set_stub("cipherBlockChainingEncryptAESCryptStub", StubRoutines::cipherBlockChaining_encryptAESCrypt()); diff -r ee3a9188c65e -r bb2447c64055 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Mon Apr 22 17:09:02 2013 +0200 +++ b/src/share/vm/graal/graalRuntime.cpp Mon Apr 22 17:59:14 2013 +0200 @@ -565,6 +565,12 @@ tty->print(buf, v1, v2, v3); JRT_END +JRT_LEAF(void, GraalRuntime::stub_printf(JavaThread* thread, jlong format, jlong v1, jlong v2, jlong v3)) + ResourceMark rm; + char *buf = (char*) (address) format; + tty->print(buf, v1, v2, v3); +JRT_END + JRT_ENTRY(void, GraalRuntime::log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline)) union { jlong l; diff -r ee3a9188c65e -r bb2447c64055 src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Mon Apr 22 17:09:02 2013 +0200 +++ b/src/share/vm/graal/graalRuntime.hpp Mon Apr 22 17:59:14 2013 +0200 @@ -98,6 +98,7 @@ stub(create_out_of_bounds_exception) \ stub(log_object) \ stub(log_printf) \ + stub(stub_printf) \ stub(log_primitive) \ stub(identity_hash_code) \ stub(thread_is_interrupted) \ @@ -146,6 +147,7 @@ static void monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock); static void vm_error(JavaThread* thread, oop where, oop format, jlong value); static void log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3); + static void stub_printf(JavaThread* thread, jlong format, jlong v1, jlong v2, jlong v3); static void log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline); static void wb_pre_call(JavaThread* thread, oopDesc* obj); static void wb_post_call(JavaThread* thread, oopDesc* obj, void* card);