Mercurial > hg > graal-compiler
changeset 7221:2ae3e26b7e9a
Merge.
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java Mon Dec 10 22:19:07 2012 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java Tue Dec 11 08:48:12 2012 +0100 @@ -64,7 +64,7 @@ public ConcreteSubtype(ResolvedJavaType context, ResolvedJavaType subtype) { this.context = context; this.subtype = subtype; - assert !subtype.isInterface(); + assert !subtype.isInterface() : subtype.toString() + " : " + context.toString(); } @Override
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64AsmOptions.java Mon Dec 10 22:19:07 2012 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64AsmOptions.java Tue Dec 11 08:48:12 2012 +0100 @@ -24,7 +24,7 @@ public class AMD64AsmOptions { public static int Atomics = 0; - public static boolean UseNormalNop = true; + public static boolean UseNormalNop = false; public static boolean UseAddressNop = true; public static boolean UseIncDec = false; public static boolean UseXmmLoadAndClearUpper = true;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Mon Dec 10 22:19:07 2012 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Tue Dec 11 08:48:12 2012 +0100 @@ -34,6 +34,8 @@ import static com.oracle.graal.hotspot.nodes.NewMultiArrayStubCall.*; import static com.oracle.graal.hotspot.nodes.VMErrorNode.*; import static com.oracle.graal.hotspot.nodes.VerifyOopStubCall.*; +import static com.oracle.graal.hotspot.nodes.IdentityHashCodeStubCall.*; +import static com.oracle.graal.hotspot.nodes.ThreadIsInterruptedStubCall.*; import static com.oracle.graal.lir.amd64.AMD64Call.*; import com.oracle.graal.api.code.*; @@ -46,7 +48,6 @@ public AMD64HotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime graalRuntime) { super(config, graalRuntime); - HotSpotVMConfig c = config; Kind word = graalRuntime.getTarget().wordKind; addRuntimeCall(DEOPTIMIZE, config.deoptimizeStub, @@ -80,7 +81,7 @@ /* arg0: object */ arg(0, Kind.Object), /* arg1: lock */ arg(1, word)); - addRuntimeCall(MONITOREXIT, c.monitorExitStub, + addRuntimeCall(MONITOREXIT, config.monitorExitStub, /* temps */ null, /* ret */ ret(Kind.Void), /* arg0: object */ arg(0, Kind.Object), @@ -92,7 +93,7 @@ /* arg0: hub */ rdx.asValue(word), /* arg1: length */ rbx.asValue(Kind.Int)); - addRuntimeCall(NEW_ARRAY_SLOW, c.newArrayStub, + addRuntimeCall(NEW_ARRAY_SLOW, config.newArrayStub, /* temps */ null, /* ret */ rax.asValue(Kind.Object), /* arg0: hub */ rdx.asValue(word), @@ -108,25 +109,35 @@ /* ret */ rax.asValue(Kind.Object), /* arg0: hub */ rdx.asValue(word)); - addRuntimeCall(NEW_MULTI_ARRAY, c.newMultiArrayStub, + addRuntimeCall(NEW_MULTI_ARRAY, config.newMultiArrayStub, /* temps */ null, /* ret */ rax.asValue(Kind.Object), /* arg0: hub */ rax.asValue(word), /* arg1: rank */ rbx.asValue(Kind.Int), /* arg2: dims */ rcx.asValue(word)); - addRuntimeCall(VERIFY_OOP, c.verifyOopStub, + addRuntimeCall(VERIFY_OOP, config.verifyOopStub, /* temps */ null, /* ret */ ret(Kind.Void), /* arg0: object */ r13.asValue(Kind.Object)); - addRuntimeCall(VM_ERROR, c.vmErrorStub, + addRuntimeCall(VM_ERROR, config.vmErrorStub, /* temps */ null, /* ret */ ret(Kind.Void), /* arg0: where */ arg(0, Kind.Object), /* arg1: format */ arg(1, Kind.Object), /* arg2: value */ arg(2, Kind.Long)); + addRuntimeCall(IDENTITY_HASHCODE, config.identityHashCodeStub, + /* temps */ null, + /* ret */ rax.asValue(Kind.Int), + /* arg0: obj */ rdx.asValue(Kind.Object)); + + addRuntimeCall(THREAD_IS_INTERRUPTED, config.threadIsInterruptedStub, + /* temps */ null, + /* ret */ rax.asValue(Kind.Boolean), + /* arg0: thread */ rdx.asValue(Kind.Object), + /* arg1: clearInterrupted */ rdx.asValue(Kind.Boolean)); } @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Mon Dec 10 22:19:07 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Tue Dec 11 08:48:12 2012 +0100 @@ -36,6 +36,7 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; +import com.oracle.graal.snippets.*; /** * Singleton class holding the instance of the {@link GraalRuntime}. @@ -240,15 +241,12 @@ @SuppressWarnings("unchecked") @Override public <T> T getCapability(Class<T> clazz) { - if (clazz == GraalCodeCacheProvider.class || clazz == MetaAccessProvider.class) { + if (clazz == GraalCodeCacheProvider.class || clazz == MetaAccessProvider.class || clazz == SnippetProvider.class) { return (T) getRuntime(); } if (clazz == GraalCompiler.class) { return (T) getCompiler(); } - if (clazz == MetaAccessProvider.class) { - return (T) getRuntime(); - } if (clazz == RuntimeInterpreterInterface.class) { return (T) getRuntimeInterpreterInterface(); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Dec 10 22:19:07 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Dec 11 08:48:12 2012 +0100 @@ -130,6 +130,16 @@ public int threadObjectOffset; /** + * The value of JavaThread::osthread_offset(). + */ + public int osThreadOffset; + + /** + * The value of OSThread::interrupted_offset(). + */ + public int osThreadInterruptedOffset; + + /** * The value of markOopDesc::unlocked_value. */ public int unlockedMask; @@ -155,6 +165,16 @@ public int biasedLockPattern; /** + * Identity hash code value when uninitialized. + */ + public int uninitializedIdentityHashCodeValue; + + /** + * Mark word right shift to get identity hash code. + */ + public int identityHashCodeShift; + + /** * Offset of _access_flags in metaspace Method object. */ public int methodAccessFlagsOffset; @@ -204,6 +224,26 @@ public int klassAccessFlagsOffset; /** + * The offset of the _layout_helper field in a Klass. + */ + public int klassLayoutHelperOffset; + + /** + * Bit pattern in the klass layout helper that can be used to identify arrays. + */ + public int arrayKlassLayoutHelperIdentifier; + + /** + * The offset of the _componentMirror field in an ArrayKlass. + */ + public int arrayKlassComponentMirrorOffset; + + /** + * The offset of the _super field in a Klass. + */ + public int klassSuperKlassOffset; + + /** * The offset of the injected klass field in a {@link Class}. */ public int klassOffset; @@ -288,6 +328,8 @@ public long logPrimitiveStub; public long logObjectStub; public long logPrintfStub; + public long threadIsInterruptedStub; + public long identityHashCodeStub; public void check() { assert vmPageSize >= 16;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Mon Dec 10 22:19:07 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Tue Dec 11 08:48:12 2012 +0100 @@ -574,7 +574,7 @@ if (onStackReplacement) { phasePlan.addPhase(PhasePosition.AFTER_PARSING, new OnStackReplacementPhase()); } - if (GraalOptions.Intrinsify) { + if (GraalOptions.Intrinsify && GraalOptions.IntrinsifyArrayCopy) { phasePlan.addPhase(PhasePosition.HIGH_LEVEL, intrinsifyArrayCopy); } return phasePlan;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Mon Dec 10 22:19:07 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Tue Dec 11 08:48:12 2012 +0100 @@ -175,7 +175,7 @@ } type = (HotSpotResolvedObjectType) fromMetaspaceKlass(subklass); } - if (unsafeReadWord(type.metaspaceKlass + config.subklassOffset) != 0) { + if (type.isInterface() || unsafeReadWord(type.metaspaceKlass + config.subklassOffset) != 0) { return null; } return type;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Dec 10 22:19:07 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Dec 11 08:48:12 2012 +0100 @@ -29,7 +29,6 @@ import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.snippets.SystemSnippets.*; import static com.oracle.graal.java.GraphBuilderPhase.*; -import static com.oracle.graal.nodes.StructuredGraph.*; import static com.oracle.graal.nodes.UnwindNode.*; import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*; import static com.oracle.graal.snippets.Log.*; @@ -71,7 +70,7 @@ /** * HotSpot implementation of {@link GraalCodeCacheProvider}. */ -public abstract class HotSpotRuntime implements GraalCodeCacheProvider { +public abstract class HotSpotRuntime implements GraalCodeCacheProvider, SnippetProvider { public final HotSpotVMConfig config; protected final RegisterConfig regConfig; @@ -293,9 +292,24 @@ protected abstract RegisterConfig createRegisterConfig(boolean globalStubConfig); public void installSnippets(SnippetInstaller installer, Assumptions assumptions) { - installer.install(SystemSnippets.class); - installer.install(UnsafeSnippets.class); - installer.install(ArrayCopySnippets.class); + if (GraalOptions.IntrinsifyObjectMethods) { + installer.install(ObjectSnippets.class); + } + if (GraalOptions.IntrinsifySystemMethods) { + installer.install(SystemSnippets.class); + } + if (GraalOptions.IntrinsifyThreadMethods) { + installer.install(ThreadSnippets.class); + } + if (GraalOptions.IntrinsifyUnsafeMethods) { + installer.install(UnsafeSnippets.class); + } + if (GraalOptions.IntrinsifyClassMethods) { + installer.install(ClassSnippets.class); + } + if (GraalOptions.IntrinsifyArrayCopy) { + installer.install(ArrayCopySnippets.class); + } installer.install(CheckCastSnippets.class); installer.install(InstanceOfSnippets.class); @@ -701,54 +715,6 @@ @Override public StructuredGraph intrinsicGraph(ResolvedJavaMethod caller, int bci, ResolvedJavaMethod method, List<? extends Node> parameters) { - ResolvedJavaType holder = method.getDeclaringClass(); - String fullName = method.getName() + ((HotSpotSignature) method.getSignature()).asString(); - Kind wordKind = graalRuntime.getTarget().wordKind; - if (MetaUtil.isJavaLangObject(holder)) { - if (fullName.equals("getClass()Ljava/lang/Class;")) { - ValueNode obj = (ValueNode) parameters.get(0); - ObjectStamp stamp = (ObjectStamp) obj.stamp(); - if (stamp.nonNull() && stamp.isExactType()) { - HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) stamp.type(); - StructuredGraph graph = new StructuredGraph(); - ValueNode result = ConstantNode.forObject(type.mirror(), this, graph); - ReturnNode ret = graph.add(new ReturnNode(result)); - graph.start().setNext(ret); - return graph; - } - StructuredGraph graph = new StructuredGraph(); - LocalNode receiver = graph.unique(new LocalNode(0, StampFactory.objectNonNull())); - LoadHubNode hub = graph.add(new LoadHubNode(receiver, wordKind)); - Stamp resultStamp = StampFactory.declaredNonNull(lookupJavaType(Class.class)); - FloatingReadNode result = graph.unique(new FloatingReadNode(hub, LocationNode.create(LocationNode.FINAL_LOCATION, Kind.Object, config.classMirrorOffset, graph), null, resultStamp)); - ReturnNode ret = graph.add(new ReturnNode(result)); - graph.start().setNext(hub); - hub.setNext(ret); - return graph; - } - } else if (holder.equals(lookupJavaType(Class.class))) { - if (fullName.equals("getModifiers()I")) { - StructuredGraph graph = new StructuredGraph(); - LocalNode receiver = graph.unique(new LocalNode(0, StampFactory.objectNonNull())); - SafeReadNode klass = safeRead(graph, wordKind, receiver, config.klassOffset, StampFactory.forKind(wordKind), INVALID_GRAPH_ID); - graph.start().setNext(klass); - LocationNode location = LocationNode.create(LocationNode.FINAL_LOCATION, Kind.Int, config.klassModifierFlagsOffset, graph); - FloatingReadNode readModifiers = graph.unique(new FloatingReadNode(klass, location, null, StampFactory.intValue())); - CompareNode isZero = CompareNode.createCompareNode(Condition.EQ, klass, ConstantNode.defaultForKind(wordKind, graph)); - GuardNode guard = graph.unique(new GuardNode(isZero, graph.start(), NullCheckException, InvalidateReprofile, true, INVALID_GRAPH_ID)); - readModifiers.dependencies().add(guard); - ReturnNode ret = graph.add(new ReturnNode(readModifiers)); - klass.setNext(ret); - return graph; - } - } else if (holder.equals(lookupJavaType(Thread.class))) { - if (fullName.equals("currentThread()Ljava/lang/Thread;")) { - StructuredGraph graph = new StructuredGraph(); - ReturnNode ret = graph.add(new ReturnNode(graph.unique(new CurrentThread(config.threadObjectOffset, this)))); - graph.start().setNext(ret); - return graph; - } - } return null; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentThread.java Mon Dec 10 22:19:07 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentThread.java Tue Dec 11 08:48:12 2012 +0100 @@ -33,8 +33,8 @@ private int threadObjectOffset; - public CurrentThread(int threadObjectOffset, CodeCacheProvider runtime) { - super(StampFactory.declaredNonNull(runtime.lookupJavaType(Thread.class))); + public CurrentThread(int threadObjectOffset) { + super(StampFactory.declaredNonNull(HotSpotGraalRuntime.getInstance().getRuntime().lookupJavaType(Thread.class))); this.threadObjectOffset = threadObjectOffset; } @@ -45,5 +45,5 @@ } @NodeIntrinsic - public static native Object get(@ConstantNodeParameter int threadObjectOffset); + public static native Thread get(@ConstantNodeParameter int threadObjectOffset); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/IdentityHashCodeStubCall.java Tue Dec 11 08:48:12 2012 +0100 @@ -0,0 +1,55 @@ +/* + * 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.code.RuntimeCall.Descriptor; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; + +/** + * Node implementing a call to HotSpot's {@code graal_identityhashcode} stub. + */ +public class IdentityHashCodeStubCall extends FixedWithNextNode implements LIRGenLowerable { + @Input private final ValueNode object; + public static final Descriptor IDENTITY_HASHCODE = new Descriptor("identity_hashcode", false, Kind.Int, Kind.Object); + + public IdentityHashCodeStubCall(ValueNode object) { + super(StampFactory.forKind(Kind.Int)); + this.object = object; + } + + @Override + public void generate(LIRGenerator gen) { + RuntimeCall stub = gen.getRuntime().lookupRuntimeCall(IdentityHashCodeStubCall.IDENTITY_HASHCODE); + Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object)); + gen.setResult(this, result); + } + + @NodeIntrinsic + public static native int call(Object object); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java Tue Dec 11 08:48:12 2012 +0100 @@ -0,0 +1,55 @@ +/* + * 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.code.RuntimeCall.Descriptor; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; + +/** + * Node implementing a call to HotSpot's ThreadIsInterrupted stub. + */ +public class ThreadIsInterruptedStubCall extends FixedWithNextNode implements LIRGenLowerable { + @Input private final ValueNode thread; + public static final Descriptor THREAD_IS_INTERRUPTED = new Descriptor("thread_is_interrupted", false, Kind.Boolean, Kind.Object, Kind.Boolean); + + public ThreadIsInterruptedStubCall(ValueNode thread) { + super(StampFactory.forKind(Kind.Boolean)); + this.thread = thread; + } + + @Override + public void generate(LIRGenerator gen) { + RuntimeCall stub = gen.getRuntime().lookupRuntimeCall(ThreadIsInterruptedStubCall.THREAD_IS_INTERRUPTED); + Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(thread)); + gen.setResult(this, result); + } + + @NodeIntrinsic + public static native boolean call(Thread thread); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSnippets.java Tue Dec 11 08:48:12 2012 +0100 @@ -0,0 +1,104 @@ +/* + * 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.snippets; + +import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*; + +import java.lang.reflect.*; + +import com.oracle.graal.snippets.*; + +@ClassSubstitution(java.lang.Class.class) +public class ClassSnippets implements SnippetsInterface { + @InstanceMethodSubstitution + public static int getModifiers(final Class<?> thisObj) { + Word klass = loadWordFromObject(thisObj, klassOffset()); + if (klass == Word.zero()) { + return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC; + } else { + return loadIntFromWord(klass, klassModifierFlagsOffset()); + } + } + + @InstanceMethodSubstitution + public static boolean isInterface(final Class<?> thisObj) { + Word klass = loadWordFromObject(thisObj, klassOffset()); + if (klass == Word.zero()) { + return false; + } else { + int accessFlags = loadIntFromWord(klass, klassAccessFlagsOffset()); + return (accessFlags & Modifier.INTERFACE) != 0; + } + } + + @InstanceMethodSubstitution + public static boolean isArray(final Class<?> thisObj) { + Word klass = loadWordFromObject(thisObj, klassOffset()); + if (klass == Word.zero()) { + return false; + } else { + int layoutHelper = loadIntFromWord(klass, klassLayoutHelperOffset()); + return (layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0; + } + } + + @InstanceMethodSubstitution + public static boolean isPrimitive(final Class<?> thisObj) { + Word klass = loadWordFromObject(thisObj, klassOffset()); + return klass == Word.zero(); + } + + @InstanceMethodSubstitution + public static Class<?> getSuperclass(final Class<?> thisObj) { + Word klass = loadWordFromObject(thisObj, klassOffset()); + if (klass != Word.zero()) { + int accessFlags = loadIntFromWord(klass, klassAccessFlagsOffset()); + if ((accessFlags & Modifier.INTERFACE) == 0) { + int layoutHelper = loadIntFromWord(klass, klassLayoutHelperOffset()); + if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) { + return Object.class; + } else { + Word superKlass = loadWordFromWord(klass, klassSuperKlassOffset()); + if (superKlass == Word.zero()) { + return null; + } else { + return (Class<?>) loadObjectFromWord(superKlass, classMirrorOffset()); + } + } + } + } + return null; + } + + @InstanceMethodSubstitution + public static Class<?> getComponentType(final Class<?> thisObj) { + Word klass = loadWordFromObject(thisObj, klassOffset()); + if (klass != Word.zero()) { + int layoutHelper = loadIntFromWord(klass, klassLayoutHelperOffset()); + if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) { + return (Class<?>) loadObjectFromWord(klass, arrayKlassComponentMirrorOffset()); + } + } + return null; + } +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Mon Dec 10 22:19:07 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Tue Dec 11 08:48:12 2012 +0100 @@ -1,416 +1,485 @@ -/* - * 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.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.hotspot.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.snippets.Snippet.Fold; -import com.oracle.graal.snippets.*; - -//JaCoCo Exclude - -/** - * A collection of methods used in HotSpot snippets. - */ -public class HotSpotSnippetUtils { - - public static HotSpotVMConfig config() { - return HotSpotGraalRuntime.getInstance().getConfig(); - } - - @Fold - public static boolean verifyOops() { - return config().verifyOops; - } - - @Fold - public static int threadTlabTopOffset() { - return config().threadTlabTopOffset; - } - - @Fold - public static int threadTlabEndOffset() { - return config().threadTlabEndOffset; - } - - @Fold - public static Kind wordKind() { - return HotSpotGraalRuntime.getInstance().getTarget().wordKind; - } - - @Fold - public static Register threadRegister() { - return HotSpotGraalRuntime.getInstance().getRuntime().threadRegister(); - } - - @Fold - public static Register stackPointerRegister() { - return HotSpotGraalRuntime.getInstance().getRuntime().stackPointerRegister(); - } - - @Fold - public static int wordSize() { - return HotSpotGraalRuntime.getInstance().getTarget().wordSize; - } - - @Fold - public static int pageSize() { - return HotSpotGraalRuntime.getInstance().getTarget().pageSize; - } - - @Fold - public static int prototypeMarkWordOffset() { - return config().prototypeMarkWordOffset; - } - - @Fold - public static long arrayPrototypeMarkWord() { - return config().arrayPrototypeMarkWord; - } - - @Fold - public static int markOffset() { - return config().markOffset; - } - - @Fold - public static int unlockedMask() { - return config().unlockedMask; - } - - /** - * Mask for a biasable, locked or unlocked mark word. - * <pre> - * +----------------------------------+-+-+ - * | 1|1|1| - * +----------------------------------+-+-+ - * </pre> - * - */ - @Fold - public static int biasedLockMaskInPlace() { - return config().biasedLockMaskInPlace; - } - - @Fold - public static int epochMaskInPlace() { - return config().epochMaskInPlace; - } - - /** - * Pattern for a biasable, unlocked mark word. - * <pre> - * +----------------------------------+-+-+ - * | 1|0|1| - * +----------------------------------+-+-+ - * </pre> - * - */ - @Fold - public static int biasedLockPattern() { - return config().biasedLockPattern; - } - - @Fold - public static int ageMaskInPlace() { - return config().ageMaskInPlace; - } - - @Fold - public static int hubOffset() { - return config().hubOffset; - } - - @Fold - public static int metaspaceArrayLengthOffset() { - return config().metaspaceArrayLengthOffset; - } - - @Fold - public static int metaspaceArrayBaseOffset() { - return config().metaspaceArrayBaseOffset; - } - - @Fold - public static int arrayLengthOffset() { - return config().arrayLengthOffset; - } - - @Fold - public static int arrayBaseOffset(Kind elementKind) { - return HotSpotRuntime.getArrayBaseOffset(elementKind); - } - - @Fold - public static int arrayIndexScale(Kind elementKind) { - return HotSpotRuntime.getArrayIndexScale(elementKind); - } - - @Fold - public static int cardTableShift() { - return config().cardtableShift; - } - - @Fold - public static long cardTableStart() { - return config().cardtableStartAddress; - } - - @Fold - public static int superCheckOffsetOffset() { - return config().superCheckOffsetOffset; - } - - @Fold - public static int secondarySuperCacheOffset() { - return config().secondarySuperCacheOffset; - } - - @Fold - public static int secondarySupersOffset() { - return config().secondarySupersOffset; - } - - @Fold - public static int lockDisplacedMarkOffset() { - return config().basicLockDisplacedHeaderOffset; - } - - @Fold - public static boolean useBiasedLocking() { - return config().useBiasedLocking; - } - - /** - * Loads the hub from a object, null checking it first. - */ - public static Word loadHub(Object object) { - return loadHubIntrinsic(object, wordKind()); - } - - public static Object verifyOop(Object object) { - if (verifyOops()) { - VerifyOopStubCall.call(object); - } - return object; - } - - /** - * Gets the value of the stack pointer register as a Word. - */ - public static Word stackPointer() { - return HotSpotSnippetUtils.registerAsWord(stackPointerRegister()); - } - - /** - * Gets the value of the thread register as a Word. - */ - public static Word thread() { - return HotSpotSnippetUtils.registerAsWord(threadRegister()); - } - - public static int loadIntFromWord(Word address, int offset) { - Integer value = UnsafeLoadNode.load(address, 0, offset, Kind.Int); - return value; - } - - public static Word loadWordFromWord(Word address, int offset) { - return loadWordFromWordIntrinsic(address, 0, offset, wordKind()); - } - - public static Word loadWordFromObject(Object object, int offset) { - return loadWordFromObjectIntrinsic(object, 0, offset, wordKind()); - } - - @NodeIntrinsic(value = RegisterNode.class, setStampFromReturnType = true) - public static native Word registerAsWord(@ConstantNodeParameter Register register); - - @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true) - private static native Word loadWordFromObjectIntrinsic(Object object, @ConstantNodeParameter int displacement, long offset, @ConstantNodeParameter Kind wordKind); - - @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true) - private static native Word loadWordFromWordIntrinsic(Word address, @ConstantNodeParameter int displacement, long offset, @ConstantNodeParameter Kind wordKind); - - @NodeIntrinsic(value = LoadHubNode.class, setStampFromReturnType = true) - static native Word loadHubIntrinsic(Object object, @ConstantNodeParameter Kind word); - - @Fold - public - static int log2WordSize() { - return CodeUtil.log2(wordSize()); - } - - @Fold - public - static int klassStateOffset() { - return config().klassStateOffset; - } - - @Fold - public - static int klassInstanceSizeOffset() { - return config().klassInstanceSizeOffset; - } - - @Fold - public - static long heapTopAddress() { - return config().heapTopAddress; - } - - @Fold - public - static long heapEndAddress() { - return config().heapEndAddress; - } - - @Fold - public - static int threadTlabStartOffset() { - return config().threadTlabStartOffset; - } - - @Fold - public - static long tlabIntArrayMarkWord() { - return config().tlabIntArrayMarkWord; - } - - @Fold - public - static boolean inlineContiguousAllocationSupported() { - return config().inlineContiguousAllocationSupported; - } - - @Fold - public - static int tlabAlignmentReserveInHeapWords() { - return config().tlabAlignmentReserve; - } - - @Fold - public - static int threadTlabSizeOffset() { - return config().threadTlabSizeOffset; - } - - @Fold - public - static int threadAllocatedBytesOffset() { - return config().threadAllocatedBytesOffset; - } - - @Fold - public - static int klassStateFullyInitialized() { - return config().klassStateFullyInitialized; - } - - @Fold - public - static int tlabRefillWasteLimitOffset() { - return config().tlabRefillWasteLimitOffset; - } - - @Fold - public - static int tlabNumberOfRefillsOffset() { - return config().tlabNumberOfRefillsOffset; - } - - @Fold - public - static int tlabFastRefillWasteOffset() { - return config().tlabFastRefillWasteOffset; - } - - @Fold - public - static int tlabSlowAllocationsOffset() { - return config().tlabSlowAllocationsOffset; - } - - @Fold - public - static int tlabRefillWasteIncrement() { - return config().tlabRefillWasteIncrement; - } - - @Fold - public - static boolean tlabStats() { - return config().tlabStats; - } - - @Fold - public static int layoutHelperOffset() { - return config().layoutHelperOffset; - } - - @Fold - public static int layoutHelperHeaderSizeShift() { - return config().layoutHelperHeaderSizeShift; - } - - @Fold - public static int layoutHelperHeaderSizeMask() { - return config().layoutHelperHeaderSizeMask; - } - - @Fold - public static int layoutHelperLog2ElementSizeShift() { - return config().layoutHelperLog2ElementSizeShift; - } - - @Fold - public static int layoutHelperLog2ElementSizeMask() { - return config().layoutHelperLog2ElementSizeMask; - } - - @Fold - public static int layoutHelperElementTypeShift() { - return config().layoutHelperElementTypeShift; - } - - @Fold - public static int layoutHelperElementTypeMask() { - return config().layoutHelperElementTypeMask; - } - - static { - assert arrayIndexScale(Kind.Byte) == 1; - assert arrayIndexScale(Kind.Boolean) == 1; - assert arrayIndexScale(Kind.Char) == 2; - assert arrayIndexScale(Kind.Short) == 2; - assert arrayIndexScale(Kind.Int) == 4; - assert arrayIndexScale(Kind.Long) == 8; - assert arrayIndexScale(Kind.Float) == 4; - assert arrayIndexScale(Kind.Double) == 8; - } -} +/* + * 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.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.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.snippets.Snippet.Fold; +import com.oracle.graal.snippets.*; + +//JaCoCo Exclude + +/** + * A collection of methods used in HotSpot snippets. + */ +public class HotSpotSnippetUtils { + + public static HotSpotVMConfig config() { + return HotSpotGraalRuntime.getInstance().getConfig(); + } + + @Fold + public static boolean verifyOops() { + return config().verifyOops; + } + + @Fold + public static int threadTlabTopOffset() { + return config().threadTlabTopOffset; + } + + @Fold + public static int threadTlabEndOffset() { + return config().threadTlabEndOffset; + } + + @Fold + public static int threadObjectOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().threadObjectOffset; + } + + @Fold + public static int osThreadOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().osThreadOffset; + } + + @Fold + public static int osThreadInterruptedOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().osThreadInterruptedOffset; + } + + @Fold + public static Kind wordKind() { + return HotSpotGraalRuntime.getInstance().getTarget().wordKind; + } + + @Fold + public static Register threadRegister() { + return HotSpotGraalRuntime.getInstance().getRuntime().threadRegister(); + } + + @Fold + public static Register stackPointerRegister() { + return HotSpotGraalRuntime.getInstance().getRuntime().stackPointerRegister(); + } + + @Fold + public static int wordSize() { + return HotSpotGraalRuntime.getInstance().getTarget().wordSize; + } + + @Fold + public static int pageSize() { + return HotSpotGraalRuntime.getInstance().getTarget().pageSize; + } + + @Fold + public static int prototypeMarkWordOffset() { + return config().prototypeMarkWordOffset; + } + + @Fold + public static long arrayPrototypeMarkWord() { + return config().arrayPrototypeMarkWord; + } + + @Fold + public static int klassOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().klassOffset; + } + + @Fold + public static int klassModifierFlagsOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().klassModifierFlagsOffset; + } + + @Fold + public static int klassAccessFlagsOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().klassAccessFlagsOffset; + } + + @Fold + public static int klassLayoutHelperOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().klassLayoutHelperOffset; + } + + @Fold + public static int arrayKlassLayoutHelperIdentifier() { + return HotSpotGraalRuntime.getInstance().getConfig().arrayKlassLayoutHelperIdentifier; + } + + @Fold + public static int arrayKlassComponentMirrorOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().arrayKlassComponentMirrorOffset; + } + + @Fold + public static int klassSuperKlassOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().klassSuperKlassOffset; + } + + @Fold + public static int classMirrorOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().classMirrorOffset; + } + + @Fold + public static int markOffset() { + return config().markOffset; + } + + @Fold + public static int unlockedMask() { + return config().unlockedMask; + } + + /** + * Mask for a biasable, locked or unlocked mark word. + * <pre> + * +----------------------------------+-+-+ + * | 1|1|1| + * +----------------------------------+-+-+ + * </pre> + * + */ + @Fold + public static int biasedLockMaskInPlace() { + return config().biasedLockMaskInPlace; + } + + @Fold + public static int epochMaskInPlace() { + return config().epochMaskInPlace; + } + + /** + * Pattern for a biasable, unlocked mark word. + * <pre> + * +----------------------------------+-+-+ + * | 1|0|1| + * +----------------------------------+-+-+ + * </pre> + * + */ + @Fold + public static int biasedLockPattern() { + return config().biasedLockPattern; + } + + @Fold + public static int ageMaskInPlace() { + return config().ageMaskInPlace; + } + + @Fold + public static int hubOffset() { + return config().hubOffset; + } + + @Fold + public static int metaspaceArrayLengthOffset() { + return config().metaspaceArrayLengthOffset; + } + + @Fold + public static int metaspaceArrayBaseOffset() { + return config().metaspaceArrayBaseOffset; + } + + @Fold + public static int arrayLengthOffset() { + return config().arrayLengthOffset; + } + + @Fold + public static int arrayBaseOffset(Kind elementKind) { + return HotSpotRuntime.getArrayBaseOffset(elementKind); + } + + @Fold + public static int arrayIndexScale(Kind elementKind) { + return HotSpotRuntime.getArrayIndexScale(elementKind); + } + + @Fold + public static int cardTableShift() { + return config().cardtableShift; + } + + @Fold + public static long cardTableStart() { + return config().cardtableStartAddress; + } + + @Fold + public static int superCheckOffsetOffset() { + return config().superCheckOffsetOffset; + } + + @Fold + public static int secondarySuperCacheOffset() { + return config().secondarySuperCacheOffset; + } + + @Fold + public static int secondarySupersOffset() { + return config().secondarySupersOffset; + } + + @Fold + public static int lockDisplacedMarkOffset() { + return config().basicLockDisplacedHeaderOffset; + } + + @Fold + public static boolean useBiasedLocking() { + return config().useBiasedLocking; + } + + @Fold + static int uninitializedIdentityHashCodeValue() { + return HotSpotGraalRuntime.getInstance().getConfig().uninitializedIdentityHashCodeValue; + } + + @Fold + static int identityHashCodeShift() { + return HotSpotGraalRuntime.getInstance().getConfig().identityHashCodeShift; + } + + /** + * Loads the hub from a object, null checking it first. + */ + public static Word loadHub(Object object) { + return loadHubIntrinsic(object, wordKind()); + } + + public static Object verifyOop(Object object) { + if (verifyOops()) { + VerifyOopStubCall.call(object); + } + return object; + } + + /** + * Gets the value of the stack pointer register as a Word. + */ + public static Word stackPointer() { + return HotSpotSnippetUtils.registerAsWord(stackPointerRegister()); + } + + /** + * Gets the value of the thread register as a Word. + */ + public static Word thread() { + return HotSpotSnippetUtils.registerAsWord(threadRegister()); + } + + public static int loadIntFromWord(Word address, int offset) { + Integer value = UnsafeLoadNode.load(address, 0, offset, Kind.Int); + return value; + } + + public static Word loadWordFromWord(Word address, int offset) { + return loadWordFromWordIntrinsic(address, 0, offset, wordKind()); + } + + static Object loadObjectFromWord(Word address, int offset) { + return UnsafeLoadNode.load(address, 0, offset, Kind.Object); + } + + public static Word loadWordFromObject(Object object, int offset) { + return loadWordFromObjectIntrinsic(object, 0, offset, wordKind()); + } + + @NodeIntrinsic(value = RegisterNode.class, setStampFromReturnType = true) + public static native Word registerAsWord(@ConstantNodeParameter Register register); + + @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true) + private static native Word loadWordFromObjectIntrinsic(Object object, @ConstantNodeParameter int displacement, long offset, @ConstantNodeParameter Kind wordKind); + + @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true) + private static native Word loadWordFromWordIntrinsic(Word address, @ConstantNodeParameter int displacement, long offset, @ConstantNodeParameter Kind wordKind); + + @NodeIntrinsic(value = LoadHubNode.class, setStampFromReturnType = true) + static native Word loadHubIntrinsic(Object object, @ConstantNodeParameter Kind word); + + @Fold + public + static int log2WordSize() { + return CodeUtil.log2(wordSize()); + } + + @Fold + public + static int klassStateOffset() { + return config().klassStateOffset; + } + + @Fold + public + static int klassInstanceSizeOffset() { + return config().klassInstanceSizeOffset; + } + + @Fold + public + static long heapTopAddress() { + return config().heapTopAddress; + } + + @Fold + public + static long heapEndAddress() { + return config().heapEndAddress; + } + + @Fold + public + static int threadTlabStartOffset() { + return config().threadTlabStartOffset; + } + + @Fold + public + static long tlabIntArrayMarkWord() { + return config().tlabIntArrayMarkWord; + } + + @Fold + public + static boolean inlineContiguousAllocationSupported() { + return config().inlineContiguousAllocationSupported; + } + + @Fold + public + static int tlabAlignmentReserveInHeapWords() { + return config().tlabAlignmentReserve; + } + + @Fold + public + static int threadTlabSizeOffset() { + return config().threadTlabSizeOffset; + } + + @Fold + public + static int threadAllocatedBytesOffset() { + return config().threadAllocatedBytesOffset; + } + + @Fold + public + static int klassStateFullyInitialized() { + return config().klassStateFullyInitialized; + } + + @Fold + public + static int tlabRefillWasteLimitOffset() { + return config().tlabRefillWasteLimitOffset; + } + + @Fold + public + static int tlabNumberOfRefillsOffset() { + return config().tlabNumberOfRefillsOffset; + } + + @Fold + public + static int tlabFastRefillWasteOffset() { + return config().tlabFastRefillWasteOffset; + } + + @Fold + public + static int tlabSlowAllocationsOffset() { + return config().tlabSlowAllocationsOffset; + } + + @Fold + public + static int tlabRefillWasteIncrement() { + return config().tlabRefillWasteIncrement; + } + + @Fold + public + static boolean tlabStats() { + return config().tlabStats; + } + + @Fold + public static int layoutHelperOffset() { + return config().layoutHelperOffset; + } + + @Fold + public static int layoutHelperHeaderSizeShift() { + return config().layoutHelperHeaderSizeShift; + } + + @Fold + public static int layoutHelperHeaderSizeMask() { + return config().layoutHelperHeaderSizeMask; + } + + @Fold + public static int layoutHelperLog2ElementSizeShift() { + return config().layoutHelperLog2ElementSizeShift; + } + + @Fold + public static int layoutHelperLog2ElementSizeMask() { + return config().layoutHelperLog2ElementSizeMask; + } + + @Fold + public static int layoutHelperElementTypeShift() { + return config().layoutHelperElementTypeShift; + } + + @Fold + public static int layoutHelperElementTypeMask() { + return config().layoutHelperElementTypeMask; + } + + static { + assert arrayIndexScale(Kind.Byte) == 1; + assert arrayIndexScale(Kind.Boolean) == 1; + assert arrayIndexScale(Kind.Char) == 2; + assert arrayIndexScale(Kind.Short) == 2; + assert arrayIndexScale(Kind.Int) == 4; + assert arrayIndexScale(Kind.Long) == 8; + assert arrayIndexScale(Kind.Float) == 4; + assert arrayIndexScale(Kind.Double) == 8; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSnippets.java Tue Dec 11 08:48:12 2012 +0100 @@ -0,0 +1,53 @@ +/* + * 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.snippets; + +import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*; + +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.snippets.*; + +@ClassSubstitution(java.lang.Object.class) +public class ObjectSnippets implements SnippetsInterface { + @InstanceMethodSubstitution("getClass") + public static Class<?> getClassSnippet(final Object thisObj) { + Word hub = loadHub(thisObj); + return (Class<?>) loadObjectFromWord(hub, classMirrorOffset()); + } + + @InstanceMethodSubstitution + public static int hashCode(final Object thisObj) { + Word mark = loadWordFromObject(thisObj, markOffset()); + + // this code is independent from biased locking (although it does not look that way) + final Word biasedLock = mark.and(biasedLockMaskInPlace()); + if (biasedLock.toLong() == unlockedMask()) { + int hash = (int) (mark.toLong() >>> identityHashCodeShift()); + if (hash != uninitializedIdentityHashCodeValue()) { + return hash; + } + } + + return IdentityHashCodeStubCall.call(thisObj); + } +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java Mon Dec 10 22:19:07 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java Tue Dec 11 08:48:12 2012 +0100 @@ -23,9 +23,12 @@ package com.oracle.graal.hotspot.snippets; import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; +import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.snippets.*; @@ -46,7 +49,25 @@ return callLong(JAVA_TIME_NANOS); } + public static int identityHashCode(Object x) { + if (x == null) { + return 0; + } + + Word mark = loadWordFromObject(x, markOffset()); + + // this code is independent from biased locking (although it does not look that way) + final Word biasedLock = mark.and(biasedLockMaskInPlace()); + if (biasedLock.toLong() == unlockedMask()) { + int hash = (int) (mark.toLong() >>> identityHashCodeShift()); + if (hash != uninitializedIdentityHashCodeValue()) { + return hash; + } + } + + return IdentityHashCodeStubCall.call(x); + } + @NodeIntrinsic(value = RuntimeCallNode.class, setStampFromReturnType = true) public static native long callLong(@ConstantNodeParameter Descriptor descriptor); - }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSnippets.java Tue Dec 11 08:48:12 2012 +0100 @@ -0,0 +1,51 @@ +/* + * 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.snippets; + +import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*; + +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.snippets.*; + + +@ClassSubstitution(java.lang.Thread.class) +public class ThreadSnippets implements SnippetsInterface { + public static Thread currentThread() { + return CurrentThread.get(threadObjectOffset()); + } + + @InstanceMethodSubstitution + @SuppressWarnings("unused") + private static boolean isInterrupted(final Thread thisObject, boolean clearInterrupted) { + Thread thread = CurrentThread.get(threadObjectOffset()); + if (thisObject == thread) { + Word osThread = loadWordFromObject(thisObject, osThreadOffset()); + boolean interrupted = loadIntFromWord(osThread, osThreadInterruptedOffset()) == 1; + if (!interrupted || !clearInterrupted) { + return interrupted; + } + } + + return ThreadIsInterruptedStubCall.call(thisObject); + } +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/UnsafeSnippets.java Mon Dec 10 22:19:07 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/UnsafeSnippets.java Tue Dec 11 08:48:12 2012 +0100 @@ -68,6 +68,12 @@ MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); } + public void putOrderedObject(Object o, long offset, Object x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putObject(o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + public int getInt(Object o, long offset) { Integer value = UnsafeLoadNode.load(o, 0, offset, Kind.Int); return value; @@ -90,6 +96,12 @@ MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); } + public void putOrderedInt(Object o, long offset, int x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putInt(o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + public boolean getBoolean(Object o, long offset) { @JavacBug(id = 6995200) Boolean result = UnsafeLoadNode.load(o, 0, offset, Kind.Boolean); @@ -205,6 +217,12 @@ MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); } + public void putOrderedLong(Object o, long offset, long x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putLong(o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + public float getFloat(Object o, long offset) { @JavacBug(id = 6995200) Float result = UnsafeLoadNode.load(o, 0, offset, Kind.Float);
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Mon Dec 10 22:19:07 2012 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Tue Dec 11 08:48:12 2012 +0100 @@ -65,9 +65,7 @@ // make sure that the displacement word of the call ends up word aligned int offset = masm.codeBuffer.position(); offset += tasm.target.arch.getMachineCodeCallDisplacementOffset(); - while (offset++ % tasm.target.wordSize != 0) { - masm.nop(); - } + masm.nop(tasm.target.wordSize - offset % tasm.target.wordSize); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Mon Dec 10 22:19:07 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Tue Dec 11 08:48:12 2012 +0100 @@ -22,8 +22,8 @@ */ package com.oracle.graal.nodes.extended; +import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.ResolvedJavaType.Representation; -import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Mon Dec 10 22:19:07 2012 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Tue Dec 11 08:48:12 2012 +0100 @@ -90,9 +90,13 @@ } private static InlineInfo logNotInlinedMethodAndReturnNull(Invoke invoke, ResolvedJavaMethod method, String msg) { + return logNotInlinedMethodAndReturnNull(invoke, method, msg, new Object[0]); + } + + private static InlineInfo logNotInlinedMethodAndReturnNull(Invoke invoke, ResolvedJavaMethod method, String msg, Object... args) { if (shouldLogInliningDecision()) { String methodString = methodName(method, invoke); - logInliningDecision(methodString, false, msg, new Object[0]); + logInliningDecision(methodString, false, msg, args); } return null; } @@ -285,7 +289,7 @@ @Override public String toString() { - return "type-checked " + MetaUtil.format("%H.%n(%p):%r", concrete); + return "type-checked with type " + type.getName() + " and method " + MetaUtil.format("%H.%n(%p):%r", concrete); } } @@ -594,10 +598,21 @@ @Override public String toString() { StringBuilder builder = new StringBuilder(shouldFallbackToInvoke() ? "megamorphic" : "polymorphic"); - builder.append(String.format(", %d methods with %d type checks:", concretes.size(), ptypes.length)); + builder.append(", "); + builder.append(concretes.size()); + builder.append(" methods [ "); for (int i = 0; i < concretes.size(); i++) { builder.append(MetaUtil.format(" %H.%n(%p):%r", concretes.get(i))); } + builder.append(" ], "); + builder.append(ptypes.length); + builder.append(" type checks [ "); + for (int i = 0; i < ptypes.length; i++) { + builder.append(" "); + builder.append(ptypes[i].getType().getName()); + builder.append(ptypes[i].getProbability()); + } + builder.append(" ]"); return builder.toString(); } } @@ -720,12 +735,11 @@ } else { invoke.setPolymorphic(true); - if (!optimisticOpts.inlinePolymorphicCalls() && notRecordedTypeProbability == 0) { - return logNotInlinedMethodAndReturnNull(invoke, targetMethod, "inlining polymorphic calls is disabled"); + return logNotInlinedMethodAndReturnNull(invoke, targetMethod, "inlining polymorphic calls is disabled (%d types)", ptypes.length); } if (!optimisticOpts.inlineMegamorphicCalls() && notRecordedTypeProbability > 0) { - return logNotInlinedMethodAndReturnNull(invoke, targetMethod, "inlining megamorphic calls is disabled"); + return logNotInlinedMethodAndReturnNull(invoke, targetMethod, "inlining megamorphic calls is disabled (%d types, %f %% not recorded types)", ptypes.length, notRecordedTypeProbability * 100); } // TODO (chaeubl) inlining of multiple methods should work differently
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Mon Dec 10 22:19:07 2012 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Tue Dec 11 08:48:12 2012 +0100 @@ -198,6 +198,15 @@ public static boolean OptTailDuplication = true; public static boolean OptEliminatePartiallyRedundantGuards = true; + // Intrinsification settings + public static boolean IntrinsifyArrayCopy = false; + public static boolean IntrinsifyObjectMethods = true; + public static boolean IntrinsifySystemMethods = true; + public static boolean IntrinsifyClassMethods = true; + public static boolean IntrinsifyThreadMethods = true; + public static boolean IntrinsifyUnsafeMethods = true; + public static boolean IntrinsifyMathMethods = true; + /** * Counts the various paths taken through snippets. */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/IntrinsificationTest.java Tue Dec 11 08:48:12 2012 +0100 @@ -0,0 +1,393 @@ +/* + * 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 static org.junit.Assert.*; + +import java.util.concurrent.*; + +import org.junit.*; + +import sun.misc.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; + + +public class IntrinsificationTest extends GraalCompilerTest { + @Test + public void testObjectIntrinsics() { + test("getClassSnippet"); + test("objectHashCodeSnippet"); + } + + @SuppressWarnings("all") + public static boolean getClassSnippet(Object obj) { + return obj.getClass() == String.class; + } + @SuppressWarnings("all") + public static int objectHashCodeSnippet(A obj) { + return obj.hashCode(); + } + + + @Test + public void testClassIntrinsics() { + test("getModifiersSnippet"); +// test("isInstanceSnippet"); + test("isInterfaceSnippet"); + test("isArraySnippet"); + test("isPrimitiveSnippet"); + test("getSuperClassSnippet"); + test("getComponentTypeSnippet"); + } + + @SuppressWarnings("all") + public static int getModifiersSnippet(Class<?> clazz) { + return clazz.getModifiers(); + } + @SuppressWarnings("all") + public static boolean isInstanceSnippet(Class<?> clazz) { + return clazz.isInstance(Number.class); + } + @SuppressWarnings("all") + public static boolean isInterfaceSnippet(Class<?> clazz) { + return clazz.isInterface(); + } + @SuppressWarnings("all") + public static boolean isArraySnippet(Class<?> clazz) { + return clazz.isArray(); + } + @SuppressWarnings("all") + public static boolean isPrimitiveSnippet(Class<?> clazz) { + return clazz.isPrimitive(); + } + @SuppressWarnings("all") + public static Class<?> getSuperClassSnippet(Class<?> clazz) { + return clazz.getSuperclass(); + } + @SuppressWarnings("all") + public static Class<?> getComponentTypeSnippet(Class<?> clazz) { + return clazz.getComponentType(); + } + + + @Test + public void testThreadIntrinsics() { + test("currentThreadSnippet"); + test("threadIsInterruptedSnippet"); + test("threadInterruptedSnippet"); + } + + @SuppressWarnings("all") + public static Thread currentThreadSnippet() { + return Thread.currentThread(); + } + @SuppressWarnings("all") + public static boolean threadIsInterruptedSnippet(Thread thread) { + return thread.isInterrupted(); + } + @SuppressWarnings("all") + public static boolean threadInterruptedSnippet() { + return Thread.interrupted(); + } + + + @Test + public void testSystemIntrinsics() { + test("systemTimeSnippet"); + test("systemIdentityHashCode"); +// test("arraycopySnippet"); + } + + @SuppressWarnings("all") + public static long systemTimeSnippet() { + return System.currentTimeMillis() + System.nanoTime(); + } + @SuppressWarnings("all") + public static int systemIdentityHashCode(Object obj) { + return System.identityHashCode(obj); + } + @SuppressWarnings("all") + public static void arraycopySnippet(int[] src, int srcPos, int[] dest, int destPos, int length) { + System.arraycopy(src, srcPos, dest, destPos, length); + } + + + @Test + public void testUnsafeIntrinsics() { + test("unsafeCompareAndSwapIntSnippet"); + test("unsafeCompareAndSwapLongSnippet"); + test("unsafeCompareAndSwapObjectSnippet"); + + test("unsafeGetBooleanSnippet"); + test("unsafeGetByteSnippet"); + test("unsafeGetShortSnippet"); + test("unsafeGetCharSnippet"); + test("unsafeGetIntSnippet"); + test("unsafeGetFloatSnippet"); + test("unsafeGetDoubleSnippet"); + test("unsafeGetObjectSnippet"); + + test("unsafePutBooleanSnippet"); + test("unsafePutByteSnippet"); + test("unsafePutShortSnippet"); + test("unsafePutCharSnippet"); + test("unsafePutIntSnippet"); + test("unsafePutFloatSnippet"); + test("unsafePutDoubleSnippet"); + test("unsafePutObjectSnippet"); + + // test("unsafeDirectMemoryReadSnippet"); + // test("unsafeDirectMemoryWriteSnippet"); + } + + @SuppressWarnings("all") + public static boolean unsafeCompareAndSwapIntSnippet(Unsafe unsafe, Object obj, long offset) { + return unsafe.compareAndSwapInt(obj, offset, 0, 1); + } + @SuppressWarnings("all") + public static boolean unsafeCompareAndSwapLongSnippet(Unsafe unsafe, Object obj, long offset) { + return unsafe.compareAndSwapLong(obj, offset, 0, 1); + } + @SuppressWarnings("all") + public static boolean unsafeCompareAndSwapObjectSnippet(Unsafe unsafe, Object obj, long offset) { + return unsafe.compareAndSwapObject(obj, offset, null, new Object()); + } + @SuppressWarnings("all") + public static boolean unsafeGetBooleanSnippet(Unsafe unsafe, Object obj, long offset) { + return unsafe.getBoolean(obj, offset) && + unsafe.getBooleanVolatile(obj, offset); + } + @SuppressWarnings("all") + public static int unsafeGetByteSnippet(Unsafe unsafe, Object obj, long offset) { + return unsafe.getByte(obj, offset) + + unsafe.getByteVolatile(obj, offset); + } + @SuppressWarnings("all") + public static int unsafeGetShortSnippet(Unsafe unsafe, Object obj, long offset) { + return unsafe.getShort(obj, offset) + + unsafe.getShortVolatile(obj, offset); + } + @SuppressWarnings("all") + public static int unsafeGetCharSnippet(Unsafe unsafe, Object obj, long offset) { + return unsafe.getChar(obj, offset) + + unsafe.getCharVolatile(obj, offset); + } + @SuppressWarnings("all") + public static int unsafeGetIntSnippet(Unsafe unsafe, Object obj, long offset) { + return unsafe.getInt(obj, offset) + + unsafe.getIntVolatile(obj, offset); + } + @SuppressWarnings("all") + public static long unsafeGetLongSnippet(Unsafe unsafe, Object obj, long offset) { + return unsafe.getLong(obj, offset) + + unsafe.getLongVolatile(obj, offset); + } + @SuppressWarnings("all") + public static float unsafeGetFloatSnippet(Unsafe unsafe, Object obj, long offset) { + return unsafe.getFloat(obj, offset) + + unsafe.getFloatVolatile(obj, offset); + } + @SuppressWarnings("all") + public static double unsafeGetDoubleSnippet(Unsafe unsafe, Object obj, long offset) { + return unsafe.getDouble(obj, offset) + + unsafe.getDoubleVolatile(obj, offset); + } + @SuppressWarnings("all") + public static boolean unsafeGetObjectSnippet(Unsafe unsafe, Object obj, long offset) { + return unsafe.getObject(obj, offset) == unsafe.getObjectVolatile(obj, offset); + } + @SuppressWarnings("all") + public static void unsafePutBooleanSnippet(Unsafe unsafe, Object obj, long offset, boolean value) { + unsafe.putBoolean(obj, offset, value); + unsafe.putBooleanVolatile(obj, offset, value); + } + @SuppressWarnings("all") + public static void unsafePutByteSnippet(Unsafe unsafe, Object obj, long offset, byte value) { + unsafe.putByte(obj, offset, value); + unsafe.putByteVolatile(obj, offset, value); + } + @SuppressWarnings("all") + public static void unsafePutShortSnippet(Unsafe unsafe, Object obj, long offset, short value) { + unsafe.putShort(obj, offset, value); + unsafe.putShortVolatile(obj, offset, value); + } + @SuppressWarnings("all") + public static void unsafePutCharSnippet(Unsafe unsafe, Object obj, long offset, char value) { + unsafe.putChar(obj, offset, value); + unsafe.putCharVolatile(obj, offset, value); + } + @SuppressWarnings("all") + public static void unsafePutIntSnippet(Unsafe unsafe, Object obj, long offset, int value) { + unsafe.putInt(obj, offset, value); + unsafe.putIntVolatile(obj, offset, value); + unsafe.putOrderedInt(obj, offset, value); + } + @SuppressWarnings("all") + public static void unsafePutLongSnippet(Unsafe unsafe, Object obj, long offset, long value) { + unsafe.putLong(obj, offset, value); + unsafe.putLongVolatile(obj, offset, value); + unsafe.putOrderedLong(obj, offset, value); + } + @SuppressWarnings("all") + public static void unsafePutFloatSnippet(Unsafe unsafe, Object obj, long offset, float value) { + unsafe.putFloat(obj, offset, value); + unsafe.putFloatVolatile(obj, offset, value); + } + @SuppressWarnings("all") + public static void unsafePutDoubleSnippet(Unsafe unsafe, Object obj, long offset, double value) { + unsafe.putDouble(obj, offset, value); + unsafe.putDoubleVolatile(obj, offset, value); + } + @SuppressWarnings("all") + public static void unsafePutObjectSnippet(Unsafe unsafe, Object obj, long offset, Object value) { + unsafe.putObject(obj, offset, value); + unsafe.putObjectVolatile(obj, offset, value); + unsafe.putOrderedObject(obj, offset, value); + } + @SuppressWarnings("all") + public static double unsafeDirectMemoryReadSnippet(Unsafe unsafe, long address) { + // Unsafe.getBoolean(long) and Unsafe.getObject(long) do not exist + return unsafe.getByte(address) + + unsafe.getShort(address) + + unsafe.getChar(address) + + unsafe.getInt(address) + + unsafe.getLong(address) + + unsafe.getFloat(address) + + unsafe.getDouble(address); + } + @SuppressWarnings("all") + public static void unsafeDirectMemoryWriteSnippet(Unsafe unsafe, long address, byte value) { + // Unsafe.putBoolean(long) and Unsafe.putObject(long) do not exist + unsafe.putByte(address, value); + unsafe.putShort(address, value); + unsafe.putChar(address, (char) value); + unsafe.putInt(address, value); + unsafe.putLong(address, value); + unsafe.putFloat(address, value); + unsafe.putDouble(address, value); + } + + + @Test + public void testMathIntrinsics() { + test("mathSnippet"); + } + + @SuppressWarnings("all") + public static double mathSnippet(double value) { + return Math.abs(value) + + Math.sqrt(value) + + Math.log(value) + + Math.log10(value) + + Math.sin(value) + + Math.cos(value) + + Math.tan(value); +// Math.exp(value) + +// Math.pow(value, 13); + } + + + @Test + public void testIntegerIntrinsics() { + // TODO (chaeubl): some methods have Java implementations -> check more than Invoke nodes + test("integerSnippet"); + } + + @SuppressWarnings("all") + public static int integerSnippet(int value) { + return Integer.reverseBytes(value) + + Integer.numberOfLeadingZeros(value) + + Integer.numberOfTrailingZeros(value); + } + + + @Test + public void testLongIntrinsics() { + test("longSnippet"); + } + + @SuppressWarnings("all") + public static long longSnippet(long value) { + return Long.reverseBytes(value) + + Long.numberOfLeadingZeros(value) + + Long.numberOfTrailingZeros(value); + } + + + @Test + public void testFloatIntrinsics() { + test("floatSnippet"); + } + + @SuppressWarnings("all") + public static float floatSnippet(float value) { + return Float.intBitsToFloat(Float.floatToIntBits(value)); + } + + + @Test + public void testDoubleIntrinsics() { + test("doubleSnippet"); + } + + @SuppressWarnings("all") + public static double doubleSnippet(double value) { + return Double.longBitsToDouble(Double.doubleToLongBits(value)); + } + + + private StructuredGraph test(final String snippet) { + return Debug.scope("IntrinsificationTest", new DebugDumpScope(snippet), new Callable<StructuredGraph>() { + @Override + public StructuredGraph call() { + StructuredGraph graph = parse(snippet); + PhasePlan phasePlan = getDefaultPhasePlan(); + Assumptions assumptions = new Assumptions(true); + Debug.dump(graph, "Graph"); + new InliningPhase(null, runtime(), null, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); + Debug.dump(graph, "Graph"); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new DeadCodeEliminationPhase().apply(graph); + + assertNoInvokes(graph); + return graph; + } + }); + } + + private static boolean assertNoInvokes(StructuredGraph graph) { + for (Invoke invoke: graph.getInvokes()) { + fail(invoke.toString()); + } + return false; + } + + private static class A { + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceMethodSubstitution.java Tue Dec 11 08:48:12 2012 +0100 @@ -0,0 +1,34 @@ +/* + * 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 java.lang.annotation.*; + +/** + * Denotes a method that substitutes a method of another class. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface InstanceMethodSubstitution { + String value() default ""; +}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Mon Dec 10 22:19:07 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Tue Dec 11 08:48:12 2012 +0100 @@ -91,7 +91,7 @@ throw new RuntimeException("Snippet must not be abstract or native"); } ResolvedJavaMethod snippet = runtime.lookupJavaMethod(method); - assert snippet.getCompilerStorage().get(Graph.class) == null; + assert snippet.getCompilerStorage().get(Graph.class) == null : method; StructuredGraph graph = makeGraph(snippet, inliningPolicy(snippet)); //System.out.println("snippet: " + graph); snippet.getCompilerStorage().put(Graph.class, graph); @@ -105,7 +105,19 @@ continue; } try { - Method originalMethod = originalClazz.getDeclaredMethod(method.getName(), method.getParameterTypes()); + InstanceMethodSubstitution methodSubstitution = method.getAnnotation(InstanceMethodSubstitution.class); + String originalName = method.getName(); + Class<?>[] originalParameters = method.getParameterTypes(); + if (methodSubstitution != null) { + if (!methodSubstitution.value().isEmpty()) { + originalName = methodSubstitution.value(); + } + assert originalParameters.length >= 1 : "must be a static method with the this object as its first parameter"; + Class<?>[] newParameters = new Class<?>[originalParameters.length - 1]; + System.arraycopy(originalParameters, 1, newParameters, 0, newParameters.length); + originalParameters = newParameters; + } + Method originalMethod = originalClazz.getDeclaredMethod(originalName, originalParameters); if (!originalMethod.getReturnType().isAssignableFrom(method.getReturnType())) { throw new RuntimeException("Snippet has incompatible return type"); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetProvider.java Tue Dec 11 08:48:12 2012 +0100 @@ -0,0 +1,30 @@ +/* + * 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.*; + + +public interface SnippetProvider { + void installSnippets(SnippetInstaller installer, Assumptions assumptions); +}
--- a/make/windows/makefiles/projectcreator.make Mon Dec 10 22:19:07 2012 +0100 +++ b/make/windows/makefiles/projectcreator.make Tue Dec 11 08:48:12 2012 +0100 @@ -144,6 +144,9 @@ -ignorePath_TARGET tiered \ -ignorePath_TARGET c1_ +ProjectCreatorIDEOptionsIgnoreGraal=\ + -ignorePath_TARGET graal + ProjectCreatorIDEOptionsIgnoreCompiler2=\ -ignorePath_TARGET compiler2 \ -ignorePath_TARGET tiered \ @@ -230,15 +233,18 @@ -define_compiler1 COMPILER1 \ -ignorePath_compiler1 core \ -ignorePath_compiler1 src/share/vm/graal \ -$(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=compiler1) + $(ProjectCreatorIDEOptionsIgnoreGraal:TARGET=compiler1) \ + $(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=compiler1) ################################################## # Graal compiler specific options ################################################## ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \ - -define_graal COMPILER1 \ -define_graal GRAAL \ -$(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=graal) + -ignorePath_graal core \ + -ignorePath_graal src/share/vm/c1 \ + $(ProjectCreatorIDEOptionsIgnoreCompiler1:TARGET=graal) \ + $(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=graal) ################################################## # Server(C2) compiler specific options @@ -260,6 +266,7 @@ -additionalFile_compiler2 ad_$(Platform_arch_model)_pipeline.cpp \ -additionalFile_compiler2 adGlobals_$(Platform_arch_model).hpp \ -additionalFile_compiler2 dfa_$(Platform_arch_model).cpp \ + $(ProjectCreatorIDEOptionsIgnoreGraal:TARGET=compiler2) \ $(ProjectCreatorIDEOptionsIgnoreCompiler1:TARGET=compiler2) # Add in the jvmti (JSR-163) options
--- a/make/windows/makefiles/vm.make Mon Dec 10 22:19:07 2012 +0100 +++ b/make/windows/makefiles/vm.make Tue Dec 11 08:48:12 2012 +0100 @@ -61,7 +61,7 @@ !endif !if "$(Variant)" == "graal" -CPP_FLAGS=$(CPP_FLAGS) /D "COMPILER1" /D "GRAAL" +CPP_FLAGS=$(CPP_FLAGS) /D "GRAAL" !endif !if "$(BUILDARCH)" == "i486"
--- a/src/cpu/x86/vm/c1_globals_x86.hpp Mon Dec 10 22:19:07 2012 +0100 +++ b/src/cpu/x86/vm/c1_globals_x86.hpp Tue Dec 11 08:48:12 2012 +0100 @@ -57,6 +57,7 @@ define_pd_global(bool, CICompileOSR, true ); #endif // !TIERED define_pd_global(bool, UseTypeProfile, false); +define_pd_global(intx, TypeProfileWidth, 0); define_pd_global(bool, RoundFPResults, true ); define_pd_global(bool, LIRFillDelaySlots, false);
--- a/src/cpu/x86/vm/graalGlobals_x86.hpp Mon Dec 10 22:19:07 2012 +0100 +++ b/src/cpu/x86/vm/graalGlobals_x86.hpp Tue Dec 11 08:48:12 2012 +0100 @@ -43,7 +43,6 @@ define_pd_global(intx, FreqInlineSize, 325 ); define_pd_global(intx, NewSizeThreadIncrease, 4*K ); define_pd_global(uintx,MetaspaceSize, 12*M ); -define_pd_global(uintx,MaxPermSize, 64*M ); define_pd_global(bool, NeverActAsServerClassMachine, true ); define_pd_global(uint64_t,MaxRAM, 1ULL*G); define_pd_global(bool, CICompileOSR, true ); @@ -58,13 +57,6 @@ define_pd_global(uintx,CodeCacheMinBlockLength, 4); define_pd_global(intx, TypeProfileWidth, 8); -define_pd_global(bool, RoundFPResults, true ); - -define_pd_global(bool, LIRFillDelaySlots, false); -define_pd_global(bool, OptimizeSinglePrecision, true ); -define_pd_global(bool, CSEArrayLength, false); -define_pd_global(bool, TwoOperandLIRForm, true ); - define_pd_global(intx, SafepointPollOffset, 256 ); #endif // CPU_X86_VM_GRAALGLOBALS_X86_HPP
--- a/src/cpu/x86/vm/graalRuntime_x86.cpp Mon Dec 10 22:19:07 2012 +0100 +++ b/src/cpu/x86/vm/graalRuntime_x86.cpp Tue Dec 11 08:48:12 2012 +0100 @@ -1153,6 +1153,35 @@ break; } + case graal_identity_hash_code_id: { + Register obj = j_rarg0; // Incoming + __ set_info("identity_hash_code", dont_gc_arguments); + __ enter(); + OopMap* map = save_live_registers(sasm, 1); + int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_identity_hash_code), obj); + oop_maps = new OopMapSet(); + oop_maps->add_gc_map(call_offset, map); + restore_live_registers_except_rax(sasm); + __ leave(); + __ ret(0); + break; + } + case graal_thread_is_interrupted_id: { + Register thread = j_rarg0; + Register clear_interrupted = j_rarg1; + + __ set_info("identity_hash_code", dont_gc_arguments); + __ enter(); + OopMap* map = save_live_registers(sasm, 1); + int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_thread_is_interrupted), thread, clear_interrupted); + oop_maps = new OopMapSet(); + oop_maps->add_gc_map(call_offset, map); + restore_live_registers_except_rax(sasm); + __ leave(); + __ ret(0); + break; + } + default: { GraalStubFrame f(sasm, "unimplemented entry", dont_gc_arguments); __ movptr(rax, (int)id);
--- a/src/share/vm/graal/graalCompiler.cpp Mon Dec 10 22:19:07 2012 +0100 +++ b/src/share/vm/graal/graalCompiler.cpp Tue Dec 11 08:48:12 2012 +0100 @@ -49,8 +49,8 @@ JavaThread* THREAD = JavaThread::current(); TRACE_graal_1("GraalCompiler::initialize"); - unsigned long heap_end = (long) Universe::heap()->reserved_region().end(); - unsigned long allocation_end = heap_end + 16l * 1024 * 1024 * 1024; + uintptr_t heap_end = (uintptr_t) Universe::heap()->reserved_region().end(); + uintptr_t allocation_end = heap_end + ((uintptr_t)16) * 1024 * 1024 * 1024; guarantee(heap_end < allocation_end, "heap end too close to end of address space (might lead to erroneous TLAB allocations)"); NOT_LP64(error("check TLAB allocation code for address space conflicts"));
--- a/src/share/vm/graal/graalCompilerToVM.cpp Mon Dec 10 22:19:07 2012 +0100 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Tue Dec 11 08:48:12 2012 +0100 @@ -1,972 +1,984 @@ -/* - * Copyright (c) 2011, 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. - */ - -#include "precompiled.hpp" -#include "runtime/fieldDescriptor.hpp" -#include "memory/oopFactory.hpp" -#include "oops/generateOopMap.hpp" -#include "oops/fieldStreams.hpp" -#include "runtime/javaCalls.hpp" -#include "graal/graalRuntime.hpp" -#include "compiler/compileBroker.hpp" -#include "compiler/compilerOracle.hpp" -#include "graal/graalCompilerToVM.hpp" -#include "graal/graalCompiler.hpp" -#include "graal/graalEnv.hpp" -#include "graal/graalJavaAccess.hpp" -#include "graal/graalCodeInstaller.hpp" -#include "graal/graalVMToCompiler.hpp" -#include "graal/graalVmIds.hpp" - - -Method* getMethodFromHotSpotMethod(oop hotspot_method) { - assert(hotspot_method != NULL && hotspot_method->is_a(HotSpotResolvedJavaMethod::klass()), "sanity"); - return asMethod(HotSpotResolvedJavaMethod::metaspaceMethod(hotspot_method)); -} - -// Entry to native method implementation that transitions current thread to '_thread_in_vm'. -#define C2V_VMENTRY(result_type, name, signature) \ - JNIEXPORT result_type JNICALL c2v_ ## name signature { \ - TRACE_graal_3("CompilerToVM::" #name); \ - GRAAL_VM_ENTRY_MARK; \ - -// Entry to native method implementation that calls a JNI function -// and hence cannot transition current thread to '_thread_in_vm'. -#define C2V_ENTRY(result_type, name, signature) \ - JNIEXPORT result_type JNICALL c2v_ ## name signature { \ - TRACE_graal_3("CompilerToVM::" #name); \ - -#define C2V_END } - -C2V_ENTRY(jbyteArray, initializeBytecode, (JNIEnv *env, jobject, jlong metaspace_method, jbyteArray result)) - methodHandle method = asMethod(metaspace_method); - ResourceMark rm; - - int code_size = method->code_size(); - jbyte* reconstituted_code = NULL; - - // replace all breakpoints - must be done before undoing any rewriting - if (method->number_of_breakpoints() > 0) { - reconstituted_code = NEW_RESOURCE_ARRAY(jbyte, code_size); - memcpy(reconstituted_code, (jbyte *) method->code_base(), code_size); - BreakpointInfo* bp = InstanceKlass::cast(method->method_holder())->breakpoints(); - for (; bp != NULL; bp = bp->next()) { - if (bp->match(method())) { - jbyte code = bp->orig_bytecode(); - reconstituted_code[bp->bci()] = code; - } - } - } - - // iterate over all bytecodes and replace non-Java bytecodes - if (RewriteBytecodes || RewriteFrequentPairs || InstanceKlass::cast(method->method_holder())->is_rewritten()) { - if (reconstituted_code == NULL) { - reconstituted_code = NEW_RESOURCE_ARRAY(jbyte, code_size); - memcpy(reconstituted_code, (jbyte *) method->code_base(), code_size); - } - BytecodeStream s(method); - while(!s.is_last_bytecode()) { - s.next(); - Bytecodes::Code opcode = s.raw_code(); - if (!Bytecodes::is_java_code(opcode)) { - jbyte original_opcode = Bytecodes::java_code(opcode); - int bci = s.bci(); - reconstituted_code[bci] = original_opcode; - if (opcode == Bytecodes::_fast_aldc_w) { - int cpci = Bytes::get_native_u2((address) reconstituted_code + bci + 1); - int i = method->constants()->object_to_cp_index(cpci); - assert(i < method->constants()->length(), "sanity check"); - Bytes::put_Java_u2((address) reconstituted_code + bci + 1, (u2)i); - } else if (opcode == Bytecodes::_fast_aldc) { - int cpci = reconstituted_code[bci + 1] & 0xff; - int i = method->constants()->object_to_cp_index(cpci); - assert(i < method->constants()->length(), "sanity check"); - reconstituted_code[bci + 1] = (jbyte)i; - } - } - } - } - - if (reconstituted_code == NULL) { - env->SetByteArrayRegion(result, 0, code_size, (jbyte *) method->code_base()); - } else { - env->SetByteArrayRegion(result, 0, code_size, reconstituted_code); - } - - return result; -C2V_END - -C2V_VMENTRY(jstring, getSignature, (JNIEnv *env, jobject, jlong metaspace_method)) - Method* method = asMethod(metaspace_method); - assert(method != NULL && method->signature() != NULL, "signature required"); - return VmIds::toString<jstring>(method->signature(), THREAD); -C2V_END - -C2V_VMENTRY(jobjectArray, initializeExceptionHandlers, (JNIEnv *, jobject, jlong metaspace_method, jobjectArray java_handlers)) - ResourceMark rm; - methodHandle method = asMethod(metaspace_method); - int handler_count = method->exception_table_length(); - objArrayHandle array = (objArrayOop) JNIHandles::resolve(java_handlers); - assert(array->length() == handler_count, "wrong length"); - ExceptionTableElement* handlers = handler_count == 0 ? NULL : method->exception_table_start(); - - for (int i = 0; i < handler_count; i++) { - ExceptionTableElement* handler = handlers + i; - Handle entry = array->obj_at(i); - assert(!entry.is_null(), "entry should not be null"); - ExceptionHandler::set_startBCI(entry, handler->start_pc); - ExceptionHandler::set_endBCI(entry, handler->end_pc); - ExceptionHandler::set_handlerBCI(entry, handler->handler_pc); - int catch_class_index = handler->catch_type_index; - ExceptionHandler::set_catchTypeCPI(entry, catch_class_index); - - if (catch_class_index == 0) { - ExceptionHandler::set_catchType(entry, NULL); - } else { - ConstantPool* cp = InstanceKlass::cast(method->method_holder())->constants(); - KlassHandle loading_klass = method->method_holder(); - Handle catch_class = GraalCompiler::get_JavaType(cp, catch_class_index, loading_klass, CHECK_NULL); - if (catch_class->klass() == HotSpotResolvedObjectType::klass() && java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(catch_class)) == SystemDictionary::Throwable_klass()) { - ExceptionHandler::set_catchType(entry, NULL); - ExceptionHandler::set_catchTypeCPI(entry, 0); - } else { - ExceptionHandler::set_catchType(entry, catch_class()); - } - } - array->obj_at_put(i, entry()); - } - - return (jobjectArray) JNIHandles::make_local(array()); -C2V_END - -C2V_VMENTRY(jint, hasBalancedMonitors, (JNIEnv *, jobject, jlong metaspace_method)) - - // Analyze the method to see if monitors are used properly. - methodHandle method(THREAD, asMethod(metaspace_method)); - assert(method->has_monitor_bytecodes(), "should have checked this"); - - // Check to see if a previous compilation computed the monitor-matching analysis. - if (method->guaranteed_monitor_matching()) { - return true; - } - - { - EXCEPTION_MARK; - ResourceMark rm(THREAD); - GeneratePairingInfo gpi(method); - gpi.compute_map(CATCH); - if (!gpi.monitor_safe()) { - return false; - } - method->set_guaranteed_monitor_matching(); - } - return true; -C2V_END - -C2V_VMENTRY(jlong, getMetaspaceMethod, (JNIEnv *, jobject, jobject reflection_method_handle, jobject resultHolder)) - oop reflection_method = JNIHandles::resolve(reflection_method_handle); - oop reflection_holder = java_lang_reflect_Method::clazz(reflection_method); - int slot = java_lang_reflect_Method::slot(reflection_method); - Klass* holder = java_lang_Class::as_Klass(reflection_holder); - methodHandle method = InstanceKlass::cast(holder)->method_with_idnum(slot); - Handle type = GraalCompiler::createHotSpotResolvedObjectType(method, CHECK_0); - objArrayOop(JNIHandles::resolve(resultHolder))->obj_at_put(0, type()); - return (jlong) (address) method(); -} - -C2V_VMENTRY(jlong, getMetaspaceConstructor, (JNIEnv *, jobject, jobject reflection_ctor_handle, jobject resultHolder)) - oop reflection_ctor = JNIHandles::resolve(reflection_ctor_handle); - oop reflection_holder = java_lang_reflect_Constructor::clazz(reflection_ctor); - int slot = java_lang_reflect_Constructor::slot(reflection_ctor); - Klass* holder = java_lang_Class::as_Klass(reflection_holder); - methodHandle method = InstanceKlass::cast(holder)->method_with_idnum(slot); - Handle type = GraalCompiler::createHotSpotResolvedObjectType(method, CHECK_0); - objArrayOop(JNIHandles::resolve(resultHolder))->obj_at_put(0, type()); - return (jlong) (address) method(); -} - -C2V_VMENTRY(jobject, getJavaField, (JNIEnv *, jobject, jobject reflection_field_handle)) - oop reflection_field = JNIHandles::resolve(reflection_field_handle); - oop reflection_holder = java_lang_reflect_Field::clazz(reflection_field); - int slot = java_lang_reflect_Field::slot(reflection_field); - InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(reflection_holder)); - - int offset = holder->field_offset(slot); - int flags = holder->field_access_flags(slot); - Symbol* field_name = holder->field_name(slot); - Handle field_holder = GraalCompiler::get_JavaTypeFromClass(reflection_holder, CHECK_NULL); - Handle field_type = GraalCompiler::get_JavaTypeFromClass(java_lang_reflect_Field::type(reflection_field), CHECK_NULL); - - Handle ret = GraalCompiler::get_JavaField(offset, flags, field_name, field_holder, field_type, CHECK_NULL); - return JNIHandles::make_local(THREAD, ret()); -} - -C2V_VMENTRY(jlong, getUniqueConcreteMethod, (JNIEnv *, jobject, jlong metaspace_method, jobject resultHolder)) - methodHandle method = asMethod(metaspace_method); - KlassHandle holder = method->method_holder(); - if (holder->is_interface()) { - // Cannot trust interfaces. Because of: - // interface I { void foo(); } - // class A { public void foo() {} } - // class B extends A implements I { } - // class C extends B { public void foo() { } } - // class D extends B { } - // Would lead to identify C.foo() as the unique concrete method for I.foo() without seeing A.foo(). - return 0L; - } - methodHandle ucm; - { - ResourceMark rm; - MutexLocker locker(Compile_lock); - ucm = Dependencies::find_unique_concrete_method(holder(), method()); - } - - if (ucm.is_null()) { - return 0L; - } - - Handle type = GraalCompiler::createHotSpotResolvedObjectType(ucm(), CHECK_0); - objArrayOop(JNIHandles::resolve(resultHolder))->obj_at_put(0, type()); - return (jlong) (address) ucm(); -C2V_END - -C2V_ENTRY(jint, getInvocationCount, (JNIEnv *, jobject, jlong metaspace_method)) - Method* method = asMethod(metaspace_method); - return method->invocation_count(); -C2V_END - -C2V_VMENTRY(void, initializeMethod,(JNIEnv *, jobject, jlong metaspace_method, jobject hotspot_method)) - methodHandle method = asMethod(metaspace_method); - Handle name = VmIds::toString<Handle>(method->name(), CHECK); - InstanceKlass::cast(HotSpotResolvedJavaMethod::klass())->initialize(CHECK); - HotSpotResolvedJavaMethod::set_name(hotspot_method, name()); - HotSpotResolvedJavaMethod::set_codeSize(hotspot_method, method->code_size()); - HotSpotResolvedJavaMethod::set_exceptionHandlerCount(hotspot_method, method->exception_table_length()); -C2V_END - -C2V_VMENTRY(jboolean, isMethodCompilable,(JNIEnv *, jobject, jlong metaspace_method)) - methodHandle method = asMethod(metaspace_method); - return !method->is_not_compilable() && !CompilerOracle::should_not_inline(method); -C2V_END - -C2V_VMENTRY(void, initializeMethodData,(JNIEnv *, jobject, jlong metaspace_method_data, jobject hotspot_method_data)) - MethodData* method_data = asMethodData(metaspace_method_data); - HotSpotMethodData::set_normalDataSize(hotspot_method_data, method_data->data_size()); - HotSpotMethodData::set_extraDataSize(hotspot_method_data, method_data->extra_data_size()); -C2V_END - -// ------------------------------------------------------------------ -// Adjust a CounterData count to be commensurate with -// interpreter_invocation_count. If the MDO exists for -// only 25% of the time the method exists, then the -// counts in the MDO should be scaled by 4X, so that -// they can be usefully and stably compared against the -// invocation counts in methods. -int scale_count(MethodData* method_data, int count) { - if (count > 0) { - int counter_life; - int method_life = method_data->method()->interpreter_invocation_count(); - int current_mileage = MethodData::mileage_of(method_data->method()); - int creation_mileage = method_data->creation_mileage(); - counter_life = current_mileage - creation_mileage; - - // counter_life due to backedge_counter could be > method_life - if (counter_life > method_life) - counter_life = method_life; - if (0 < counter_life && counter_life <= method_life) { - count = (int)((double)count * method_life / counter_life + 0.5); - count = (count > 0) ? count : 1; - } - } - return count; -} - -C2V_ENTRY(jint, getCompiledCodeSize, (JNIEnv *env, jobject, jlong metaspace_method)) - nmethod* code = (asMethod(metaspace_method))->code(); - return code == NULL ? 0 : code->insts_size(); -C2V_END - -C2V_VMENTRY(jobject, lookupType, (JNIEnv *env, jobject, jstring jname, jobject accessingClass, jboolean eagerResolve)) - ResourceMark rm; - - Symbol* nameSymbol = VmIds::toSymbol(jname); - Handle name = JNIHandles::resolve(jname); - assert(nameSymbol != NULL, "name to symbol creation failed"); - - oop result = NULL; - if (nameSymbol == vmSymbols::int_signature()) { - result = VMToCompiler::createPrimitiveJavaType((int) T_INT, THREAD); - } else if (nameSymbol == vmSymbols::long_signature()) { - result = VMToCompiler::createPrimitiveJavaType((int) T_LONG, THREAD); - } else if (nameSymbol == vmSymbols::bool_signature()) { - result = VMToCompiler::createPrimitiveJavaType((int) T_BOOLEAN, THREAD); - } else if (nameSymbol == vmSymbols::char_signature()) { - result = VMToCompiler::createPrimitiveJavaType((int) T_CHAR, THREAD); - } else if (nameSymbol == vmSymbols::short_signature()) { - result = VMToCompiler::createPrimitiveJavaType((int) T_SHORT, THREAD); - } else if (nameSymbol == vmSymbols::byte_signature()) { - result = VMToCompiler::createPrimitiveJavaType((int) T_BYTE, THREAD); - } else if (nameSymbol == vmSymbols::double_signature()) { - result = VMToCompiler::createPrimitiveJavaType((int) T_DOUBLE, THREAD); - } else if (nameSymbol == vmSymbols::float_signature()) { - result = VMToCompiler::createPrimitiveJavaType((int) T_FLOAT, THREAD); - } else if (nameSymbol == vmSymbols::void_signature()) { - result = VMToCompiler::createPrimitiveJavaType((int) T_VOID, THREAD); - } else { - Klass* resolved_type = NULL; - Handle classloader; - Handle protectionDomain; - if (JNIHandles::resolve(accessingClass) != NULL) { - classloader = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(accessingClass))->class_loader(); - protectionDomain = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(accessingClass))->protection_domain(); - } - - if (eagerResolve) { - resolved_type = SystemDictionary::resolve_or_fail(nameSymbol, classloader, protectionDomain, true, THREAD); - } else { - resolved_type = SystemDictionary::resolve_or_null(nameSymbol, classloader, protectionDomain, THREAD); - } - - if (!HAS_PENDING_EXCEPTION) { - if (resolved_type == NULL) { - assert(!eagerResolve, "failed eager resolution should have caused an exception"); - Handle type = VMToCompiler::createUnresolvedJavaType(name, THREAD); - result = type(); - } else { - Handle type = GraalCompiler::createHotSpotResolvedObjectType(resolved_type, name, CHECK_NULL); - result = type(); - } - } - } - - return JNIHandles::make_local(THREAD, result); -C2V_END - -C2V_VMENTRY(jobject, lookupConstantInPool, (JNIEnv *env, jobject, jobject type, jint index)) - - ConstantPool* cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants(); - - oop result = NULL; - constantTag tag = cp->tag_at(index); - if (tag.is_int()) { - result = VMToCompiler::createConstant(Kind::Int(), cp->int_at(index), CHECK_0); - } else if (tag.is_long()) { - result = VMToCompiler::createConstant(Kind::Long(), cp->long_at(index), CHECK_0); - } else if (tag.is_float()) { - result = VMToCompiler::createConstantFloat(cp->float_at(index), CHECK_0); - } else if (tag.is_double()) { - result = VMToCompiler::createConstantDouble(cp->double_at(index), CHECK_0); - } else if (tag.is_string()) { - oop string = NULL; - if (cp->is_pseudo_string_at(index)) { - int obj_index = cp->cp_to_object_index(index); - string = cp->pseudo_string_at(index, obj_index); - } else { - string = cp->string_at(index, THREAD); - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - // TODO: Gracefully exit compilation. - fatal("out of memory during compilation!"); - return NULL; - } - } - result = VMToCompiler::createConstantObject(string, CHECK_0); - } else if (tag.is_klass() || tag.is_unresolved_klass()) { - Handle type = GraalCompiler::get_JavaType(cp, index, cp->pool_holder(), CHECK_NULL); - result = type(); - } else if (tag.is_object()) { - oop obj = cp->object_at(index); - assert(obj->is_instance(), "must be an instance"); - result = VMToCompiler::createConstantObject(obj, CHECK_NULL); - } else { - tty->print("unknown constant pool tag (%s) at cpi %d in %s: ", tag.internal_name(), index, cp->pool_holder()->name()->as_C_string()); - ShouldNotReachHere(); - } - - return JNIHandles::make_local(THREAD, result); -C2V_END - -C2V_VMENTRY(jobject, lookupMethodInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte opcode)) - index = GraalCompiler::to_cp_index_u2(index); - constantPoolHandle cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants(); - instanceKlassHandle pool_holder(cp->pool_holder()); - - Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF); - methodHandle method = GraalEnv::get_method_by_index(cp, index, bc, pool_holder); - if (!method.is_null()) { - Handle holder = GraalCompiler::get_JavaType(method->method_holder(), CHECK_NULL); - return JNIHandles::make_local(THREAD, VMToCompiler::createResolvedJavaMethod(holder, method(), THREAD)); - } else { - // Get the method's name and signature. - Handle name = VmIds::toString<Handle>(cp->name_ref_at(index), CHECK_NULL); - Handle signature = VmIds::toString<Handle>(cp->signature_ref_at(index), CHECK_NULL); - int holder_index = cp->klass_ref_index_at(index); - Handle type = GraalCompiler::get_JavaType(cp, holder_index, cp->pool_holder(), CHECK_NULL); - return JNIHandles::make_local(THREAD, VMToCompiler::createUnresolvedJavaMethod(name, signature, type, THREAD)); - } -C2V_END - -C2V_VMENTRY(jobject, lookupTypeInPool, (JNIEnv *env, jobject, jobject type, jint index)) - - ConstantPool* cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants(); - Handle result = GraalCompiler::get_JavaType(cp, index, cp->pool_holder(), CHECK_NULL); - return JNIHandles::make_local(THREAD, result()); -C2V_END - -C2V_VMENTRY(void, lookupReferencedTypeInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte op)) - ConstantPool* cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants(); - int opcode = (op & 0xFF); - if (opcode != Bytecodes::_checkcast && opcode != Bytecodes::_instanceof && opcode != Bytecodes::_new && opcode != Bytecodes::_anewarray - && opcode != Bytecodes::_multianewarray && opcode != Bytecodes::_ldc && opcode != Bytecodes::_ldc_w && opcode != Bytecodes::_ldc2_w) - { - index = cp->remap_instruction_operand_from_cache(GraalCompiler::to_cp_index_u2(index)); - } - constantTag tag = cp->tag_at(index); - if (tag.is_field_or_method()) { - index = cp->uncached_klass_ref_index_at(index); - tag = cp->tag_at(index); - } - - if (tag.is_unresolved_klass() || tag.is_klass()) { - Klass* klass = cp->klass_at(index, CHECK); - if (klass->oop_is_instance()) { - InstanceKlass::cast(klass)->initialize(CHECK); - } - } -C2V_END - -C2V_VMENTRY(jobject, lookupFieldInPool, (JNIEnv *env, jobject, jobject constantPoolHolder, jint index, jbyte opcode)) - ResourceMark rm; - - index = GraalCompiler::to_cp_index_u2(index); - constantPoolHandle cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(constantPoolHolder)))->constants(); - - int nt_index = cp->name_and_type_ref_index_at(index); - int sig_index = cp->signature_ref_index_at(nt_index); - Symbol* signature = cp->symbol_at(sig_index); - int name_index = cp->name_ref_index_at(nt_index); - Symbol* name = cp->symbol_at(name_index); - int holder_index = cp->klass_ref_index_at(index); - Handle holder = GraalCompiler::get_JavaType(cp, holder_index, cp->pool_holder(), CHECK_NULL); - instanceKlassHandle holder_klass; - - Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF); - int offset = -1; - AccessFlags flags; - BasicType basic_type; - if (holder->klass() == SystemDictionary::HotSpotResolvedObjectType_klass()) { - FieldAccessInfo result; - LinkResolver::resolve_field(result, cp, index, - Bytecodes::java_code(code), - true, false, Thread::current()); - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - } else { - offset = result.field_offset(); - flags = result.access_flags(); - holder_klass = result.klass()(); - basic_type = result.field_type(); - holder = GraalCompiler::get_JavaType(holder_klass, CHECK_NULL); - } - } - - Handle type = GraalCompiler::get_JavaTypeFromSignature(signature, cp->pool_holder(), CHECK_NULL); - Handle field_handle = GraalCompiler::get_JavaField(offset, flags.as_int(), name, holder, type, THREAD); - - return JNIHandles::make_local(THREAD, field_handle()); -C2V_END - -C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject resolved_type, jstring name, jstring signature)) - - assert(JNIHandles::resolve(resolved_type) != NULL, ""); - Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(resolved_type)); - Symbol* name_symbol = VmIds::toSymbol(name); - Symbol* signature_symbol = VmIds::toSymbol(signature); - methodHandle method = klass->lookup_method(name_symbol, signature_symbol); - if (method.is_null()) { - if (TraceGraal >= 3) { - ResourceMark rm; - tty->print_cr("Could not resolve method %s %s on klass %s", name_symbol->as_C_string(), signature_symbol->as_C_string(), klass->name()->as_C_string()); - } - return NULL; - } - Handle holder = GraalCompiler::get_JavaType(method->method_holder(), CHECK_NULL); - return JNIHandles::make_local(THREAD, VMToCompiler::createResolvedJavaMethod(holder, method(), THREAD)); -C2V_END - -C2V_VMENTRY(jboolean, isTypeInitialized,(JNIEnv *, jobject, jobject hotspot_klass)) - Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(hotspot_klass)); - assert(klass != NULL, "method must not be called for primitive types"); - return InstanceKlass::cast(klass)->is_initialized(); -C2V_END - -C2V_VMENTRY(void, initializeType, (JNIEnv *, jobject, jobject hotspot_klass)) - Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(hotspot_klass)); - assert(klass != NULL, "method must not be called for primitive types"); - InstanceKlass::cast(klass)->initialize(JavaThread::current()); -C2V_END - -C2V_VMENTRY(jobject, getInstanceFields, (JNIEnv *, jobject, jobject klass)) - ResourceMark rm; - - instanceKlassHandle k = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(klass)); - GrowableArray<Handle> fields(k->java_fields_count()); - - for (AllFieldStream fs(k()); !fs.done(); fs.next()) { - if (!fs.access_flags().is_static()) { - Handle type = GraalCompiler::get_JavaTypeFromSignature(fs.signature(), k, Thread::current()); - int flags = fs.access_flags().as_int(); - bool internal = fs.access_flags().is_internal(); - Handle name = VmIds::toString<Handle>(fs.name(), Thread::current()); - Handle field = VMToCompiler::createJavaField(JNIHandles::resolve(klass), name, type, fs.offset(), flags, internal, Thread::current()); - fields.append(field()); - } - } - objArrayHandle field_array = oopFactory::new_objArray(SystemDictionary::HotSpotResolvedJavaField_klass(), fields.length(), CHECK_NULL); - for (int i = 0; i < fields.length(); ++i) { - field_array->obj_at_put(i, fields.at(i)()); - } - return JNIHandles::make_local(field_array()); -C2V_END - -C2V_VMENTRY(jlong, getMaxCallTargetOffset, (JNIEnv *env, jobject, jlong stub)) - address target_addr = (address) stub; - if (target_addr != 0x0) { - int64_t off_low = (int64_t)target_addr - ((int64_t)CodeCache::low_bound() + sizeof(int)); - int64_t off_high = (int64_t)target_addr - ((int64_t)CodeCache::high_bound() + sizeof(int)); - return MAX2(ABS(off_low), ABS(off_high)); - } - return -1; -C2V_END - -C2V_VMENTRY(jobject, getResolvedType, (JNIEnv *env, jobject, jobject javaClass)) - oop java_mirror = JNIHandles::resolve(javaClass); - assert(java_mirror != NULL, "argument to CompilerToVM.getResolvedType must not be NULL"); - Handle type = GraalCompiler::get_JavaTypeFromClass(java_mirror, CHECK_NULL); - return JNIHandles::make_local(THREAD, type()); -C2V_END - - -// helpers used to set fields in the HotSpotVMConfig object -jfieldID getFieldID(JNIEnv* env, jobject obj, const char* name, const char* sig) { - jfieldID id = env->GetFieldID(env->GetObjectClass(obj), name, sig); - if (id == NULL) { - fatal(err_msg("field not found: %s (%s)", name, sig)); - } - return id; -} - -BasicType basicTypes[] = { T_BOOLEAN, T_BYTE, T_SHORT, T_CHAR, T_INT, T_FLOAT, T_LONG, T_DOUBLE, T_OBJECT }; -int basicTypeCount = sizeof(basicTypes) / sizeof(BasicType); - -C2V_ENTRY(void, initializeConfiguration, (JNIEnv *env, jobject, jobject config)) - -#define set_boolean(name, value) do { env->SetBooleanField(config, getFieldID(env, config, name, "Z"), value); } while (0) -#define set_int(name, value) do { env->SetIntField(config, getFieldID(env, config, name, "I"), value); } while (0) -#define set_long(name, value) do { env->SetLongField(config, getFieldID(env, config, name, "J"), value); } while (0) -#define set_object(name, value) do { env->SetObjectField(config, getFieldID(env, config, name, "Ljava/lang/Object;"), value); } while (0) -#define set_int_array(name, value) do { env->SetObjectField(config, getFieldID(env, config, name, "[I"), value); } while (0) - - guarantee(HeapWordSize == sizeof(char*), "Graal assumption that HeadWordSize == machine word size is wrong"); -#ifdef _WIN64 - set_boolean(env, config, "windowsOs", true); -#else - set_boolean("windowsOs", false); -#endif - set_boolean("verifyOops", VerifyOops); - set_boolean("useFastLocking", UseFastLocking); - set_boolean("useFastNewObjectArray", UseFastNewObjectArray); - set_boolean("useBiasedLocking", UseBiasedLocking); - set_boolean("useFastNewTypeArray", UseFastNewTypeArray); - set_boolean("useTLAB", UseTLAB); - set_int("codeEntryAlignment", CodeEntryAlignment); - set_int("vmPageSize", os::vm_page_size()); - set_int("stackShadowPages", StackShadowPages); - set_int("hubOffset", oopDesc::klass_offset_in_bytes()); - set_int("markOffset", oopDesc::mark_offset_in_bytes()); - set_int("prototypeMarkWordOffset", in_bytes(Klass::prototype_header_offset())); - set_int("superCheckOffsetOffset", in_bytes(Klass::super_check_offset_offset())); - set_int("secondarySuperCacheOffset", in_bytes(Klass::secondary_super_cache_offset())); - set_int("secondarySupersOffset", in_bytes(Klass::secondary_supers_offset())); - set_int("subklassOffset", in_bytes(Klass::subklass_offset())); - set_int("nextSiblingOffset", in_bytes(Klass::next_sibling_offset())); - set_int("arrayLengthOffset", arrayOopDesc::length_offset_in_bytes()); - set_int("klassStateOffset", in_bytes(InstanceKlass::init_state_offset())); - set_int("klassStateFullyInitialized", (int)InstanceKlass::fully_initialized); - set_int("threadTlabTopOffset", in_bytes(JavaThread::tlab_top_offset())); - set_int("threadTlabEndOffset", in_bytes(JavaThread::tlab_end_offset())); - set_int("threadObjectOffset", in_bytes(JavaThread::threadObj_offset())); - set_int("unlockedMask", (int) markOopDesc::unlocked_value); - set_int("biasedLockMaskInPlace", (int) markOopDesc::biased_lock_mask_in_place); - set_int("ageMaskInPlace", (int) markOopDesc::age_mask_in_place); - set_int("epochMaskInPlace", (int) markOopDesc::epoch_mask_in_place); - set_int("biasedLockPattern", (int) markOopDesc::biased_lock_pattern); - set_int("methodMaxLocalsOffset", in_bytes(Method::size_of_locals_offset())); - set_int("methodMaxStackOffset", in_bytes(Method::max_stack_offset())); - set_int("extraStackEntries", Method::extra_stack_entries()); - set_int("methodAccessFlagsOffset", in_bytes(Method::access_flags_offset())); - set_int("klassHasFinalizerFlag", JVM_ACC_HAS_FINALIZER); - set_int("threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset())); - set_int("threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset())); - set_long("safepointPollingAddress", (jlong)(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); - set_boolean("isPollingPageFar", Assembler::is_polling_page_far()); - set_int("classMirrorOffset", in_bytes(Klass::java_mirror_offset())); - set_int("runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes); - set_int("klassModifierFlagsOffset", in_bytes(Klass::modifier_flags_offset())); - set_int("klassAccessFlagsOffset", in_bytes(Klass::access_flags_offset())); - set_int("klassOffset", java_lang_Class::klass_offset_in_bytes()); - set_int("graalMirrorInClassOffset", java_lang_Class::graal_mirror_offset_in_bytes()); - set_int("methodDataOffset", in_bytes(Method::method_data_offset())); - set_int("nmethodEntryOffset", nmethod::verified_entry_point_offset()); - set_int("methodCompiledEntryOffset", in_bytes(Method::from_compiled_offset())); - set_int("basicLockSize", sizeof(BasicLock)); - set_int("basicLockDisplacedHeaderOffset", BasicLock::displaced_header_offset_in_bytes()); - - set_int("metaspaceArrayLengthOffset", Array<Klass*>::length_offset_in_bytes()); - set_int("metaspaceArrayBaseOffset", Array<Klass*>::base_offset_in_bytes()); - set_int("methodDataOopDataOffset", in_bytes(MethodData::data_offset())); - set_int("methodDataOopTrapHistoryOffset", in_bytes(MethodData::trap_history_offset())); - set_int("dataLayoutHeaderSize", DataLayout::header_size_in_bytes()); - set_int("dataLayoutTagOffset", in_bytes(DataLayout::tag_offset())); - set_int("dataLayoutFlagsOffset", in_bytes(DataLayout::flags_offset())); - set_int("dataLayoutBCIOffset", in_bytes(DataLayout::bci_offset())); - set_int("dataLayoutCellsOffset", in_bytes(DataLayout::cell_offset(0))); - set_int("dataLayoutCellSize", DataLayout::cell_size); - set_int("bciProfileWidth", BciProfileWidth); - set_int("typeProfileWidth", TypeProfileWidth); - - set_int("tlabAlignmentReserve", (int32_t)ThreadLocalAllocBuffer::alignment_reserve()); - set_long("tlabIntArrayMarkWord", (intptr_t)markOopDesc::prototype()->copy_set_hash(0x2)); - set_long("heapTopAddress", (jlong)(address) Universe::heap()->top_addr()); - set_long("heapEndAddress", (jlong)(address) Universe::heap()->end_addr()); - set_int("threadTlabStartOffset", in_bytes(JavaThread::tlab_start_offset())); - set_int("threadTlabSizeOffset", in_bytes(JavaThread::tlab_size_offset())); - set_int("threadAllocatedBytesOffset", in_bytes(JavaThread::allocated_bytes_offset())); - set_int("tlabSlowAllocationsOffset", in_bytes(JavaThread::tlab_slow_allocations_offset())); - set_int("tlabFastRefillWasteOffset", in_bytes(JavaThread::tlab_fast_refill_waste_offset())); - set_int("tlabNumberOfRefillsOffset", in_bytes(JavaThread::tlab_number_of_refills_offset())); - set_int("tlabRefillWasteLimitOffset", in_bytes(JavaThread::tlab_refill_waste_limit_offset())); - set_int("tlabRefillWasteIncrement", (int32_t) ThreadLocalAllocBuffer::refill_waste_limit_increment()); - set_int("klassInstanceSizeOffset", in_bytes(Klass::layout_helper_offset())); - set_boolean("tlabStats", TLABStats); - set_boolean("inlineContiguousAllocationSupported", !CMSIncrementalMode && Universe::heap()->supports_inline_contig_alloc()); - - set_long("arrayPrototypeMarkWord", (intptr_t)markOopDesc::prototype()); - set_int("layoutHelperLog2ElementSizeShift", Klass::_lh_log2_element_size_shift); - set_int("layoutHelperLog2ElementSizeMask", Klass::_lh_log2_element_size_mask); - set_int("layoutHelperElementTypeShift", Klass::_lh_element_type_shift); - set_int("layoutHelperElementTypeMask", Klass::_lh_element_type_mask); - set_int("layoutHelperHeaderSizeShift", Klass::_lh_header_size_shift); - set_int("layoutHelperHeaderSizeMask", Klass::_lh_header_size_mask); - set_int("layoutHelperOffset", in_bytes(Klass::layout_helper_offset())); - - set_long("debugStub", VmIds::addStub((address)warning)); - set_long("instanceofStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_slow_subtype_check_id))); - set_long("newInstanceStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_instance_id))); - set_long("newArrayStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_array_id))); - set_long("newMultiArrayStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_multi_array_id))); - set_long("inlineCacheMissStub", VmIds::addStub(SharedRuntime::get_ic_miss_stub())); - set_long("handleExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_handle_exception_nofpu_id))); - set_long("handleDeoptStub", VmIds::addStub(SharedRuntime::deopt_blob()->unpack())); - set_long("monitorEnterStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_monitorenter_id))); - set_long("monitorExitStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_monitorexit_id))); - set_long("verifyOopStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_verify_oop_id))); - set_long("vmErrorStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_vm_error_id))); - set_long("deoptimizeStub", VmIds::addStub(SharedRuntime::deopt_blob()->uncommon_trap())); - set_long("unwindExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_unwind_exception_call_id))); - set_long("osrMigrationEndStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_OSR_migration_end_id))); - set_long("registerFinalizerStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_register_finalizer_id))); - set_long("setDeoptInfoStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_set_deopt_info_id))); - set_long("createNullPointerExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_create_null_pointer_exception_id))); - set_long("createOutOfBoundsExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_create_out_of_bounds_exception_id))); - set_long("javaTimeMillisStub", VmIds::addStub(CAST_FROM_FN_PTR(address, os::javaTimeMillis))); - set_long("javaTimeNanosStub", VmIds::addStub(CAST_FROM_FN_PTR(address, os::javaTimeNanos))); - set_long("arithmeticFremStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_arithmetic_frem_id))); - set_long("arithmeticDremStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_arithmetic_drem_id))); - set_long("arithmeticSinStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dsin))); - set_long("arithmeticCosStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dcos))); - set_long("arithmeticTanStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dtan))); - set_long("logPrimitiveStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_primitive_id))); - set_long("logObjectStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_object_id))); - set_long("logPrintfStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_printf_id))); - - - BarrierSet* bs = Universe::heap()->barrier_set(); - switch (bs->kind()) { - case BarrierSet::CardTableModRef: - case BarrierSet::CardTableExtension: { - jlong base = (jlong)((CardTableModRefBS*)bs)->byte_map_base; - assert(base != 0, "unexpected byte_map_base"); - set_long("cardtableStartAddress", base); - set_int("cardtableShift", CardTableModRefBS::card_shift); - break; - } - case BarrierSet::ModRef: - case BarrierSet::Other: - set_long("cardtableStartAddress", 0); - set_int("cardtableShift", 0); - // No post barriers - break; -#ifndef SERIALGC - case BarrierSet::G1SATBCT: - case BarrierSet::G1SATBCTLogging: -#endif // SERIALGC - default: - ShouldNotReachHere(); - break; - } - - set_int("arrayClassElementOffset", in_bytes(ObjArrayKlass::element_klass_offset())); - -#undef set_boolean -#undef set_int -#undef set_long -#undef set_object -#undef set_int_array - -C2V_END - -C2V_VMENTRY(jint, installCode0, (JNIEnv *jniEnv, jobject, jobject compResult, jobject installed_code, jobject info)) - ResourceMark rm; - HandleMark hm; - Handle compResultHandle = JNIHandles::resolve(compResult); - nmethod* nm = NULL; - methodHandle method = getMethodFromHotSpotMethod(HotSpotCompilationResult::method(compResult)); - Handle installed_code_handle = JNIHandles::resolve(installed_code); - GraalEnv::CodeInstallResult result; - CodeInstaller installer(compResultHandle, method, result, nm, installed_code_handle); - - if (result != GraalEnv::ok) { - assert(nm == NULL, "should be"); - } else { - if (info != NULL) { - arrayOop codeCopy = oopFactory::new_byteArray(nm->code_size(), CHECK_0); - memcpy(codeCopy->base(T_BYTE), nm->code_begin(), nm->code_size()); - HotSpotCodeInfo::set_code(info, codeCopy); - HotSpotCodeInfo::set_start(info, (jlong) nm->code_begin()); - } - - if (!installed_code_handle.is_null()) { - assert(installed_code_handle->is_a(HotSpotInstalledCode::klass()), "wrong type"); - HotSpotInstalledCode::set_nmethod(installed_code_handle, (jlong) nm); - HotSpotInstalledCode::set_method(installed_code_handle, HotSpotCompilationResult::method(compResult)); - assert(nm == NULL || !installed_code_handle->is_scavengable() || nm->on_scavenge_root_list(), "nm should be scavengable if installed_code is scavengable"); - } - } - return result; -C2V_END - -C2V_VMENTRY(jobject, disassembleNative, (JNIEnv *jniEnv, jobject, jbyteArray code, jlong start_address)) - ResourceMark rm; - HandleMark hm; - - stringStream(st); - arrayOop code_oop = (arrayOop) JNIHandles::resolve(code); - int len = code_oop->length(); - address begin = (address) code_oop->base(T_BYTE); - address end = begin + len; - Disassembler::decode(begin, end, &st); - - Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL); - return JNIHandles::make_local(result()); -C2V_END - -C2V_VMENTRY(jobject, getStackTraceElement, (JNIEnv *env, jobject, jlong metaspace_method, int bci)) - ResourceMark rm; - HandleMark hm; - - methodHandle method = asMethod(metaspace_method); - oop element = java_lang_StackTraceElement::create(method, bci, CHECK_NULL); - return JNIHandles::make_local(element); -C2V_END - -C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jlong metaspace_method, jlong metaspace_nmethod, jobject args)) - ResourceMark rm; - HandleMark hm; - - assert(metaspace_method != 0, "just checking"); - methodHandle mh = asMethod(metaspace_method); - Symbol* signature = mh->signature(); - JavaCallArguments jca; - - JavaArgumentUnboxer jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static()); - JavaValue result(jap.get_ret_type()); - - nmethod* nm = (nmethod*) (address) metaspace_nmethod; - if (nm == NULL || !nm->is_alive()) { - THROW_0(vmSymbols::MethodInvalidatedException()); - } - - JavaCalls::call(&result, mh, nm, &jca, CHECK_NULL); - - if (jap.get_ret_type() == T_VOID) { - return NULL; - } else if (jap.get_ret_type() == T_OBJECT || jap.get_ret_type() == T_ARRAY) { - return JNIHandles::make_local((oop) result.get_jobject()); - } else { - oop o = java_lang_boxing_object::create(jap.get_ret_type(), (jvalue *) result.get_value_addr(), CHECK_NULL); - return JNIHandles::make_local(o); - } -C2V_END - -C2V_VMENTRY(jobject, executeCompiledMethod, (JNIEnv *env, jobject, jlong metaspace_method, jlong metaspace_nmethod, jobject arg1, jobject arg2, jobject arg3)) - ResourceMark rm; - HandleMark hm; - - methodHandle method = asMethod(metaspace_method); - assert(!method.is_null(), "just checking"); - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(JNIHandles::resolve(arg1)); - args.push_oop(JNIHandles::resolve(arg2)); - args.push_oop(JNIHandles::resolve(arg3)); - - nmethod* nm = (nmethod*) (address) metaspace_nmethod; - if (nm == NULL || !nm->is_alive()) { - THROW_0(vmSymbols::MethodInvalidatedException()); - } - - JavaCalls::call(&result, method, nm, &args, CHECK_NULL); - - return JNIHandles::make_local((oop) result.get_jobject()); -C2V_END - -C2V_VMENTRY(jint, getVtableEntryOffset, (JNIEnv *, jobject, jlong metaspace_method)) - - Method* method = asMethod(metaspace_method); - assert(!InstanceKlass::cast(method->method_holder())->is_interface(), "vtableEntryOffset cannot be called for interface methods"); - assert(InstanceKlass::cast(method->method_holder())->is_linked(), "vtableEntryOffset cannot be called is holder is not linked"); - - // get entry offset in words - int vtable_entry_offset = InstanceKlass::vtable_start_offset() + method->vtable_index() * vtableEntry::size(); - // convert to bytes - vtable_entry_offset = vtable_entry_offset * wordSize + vtableEntry::method_offset_in_bytes(); - - return vtable_entry_offset; -C2V_END - -C2V_VMENTRY(jobject, getDeoptedLeafGraphIds, (JNIEnv *, jobject)) - - // the contract for this method is as follows: - // returning null: no deopted leaf graphs - // returning array (size > 0): the ids of the deopted leaf graphs - // returning array (size == 0): there was an overflow, the compiler needs to clear its cache completely - - oop array = GraalCompiler::instance()->dump_deopted_leaf_graphs(CHECK_NULL); - return JNIHandles::make_local(array); -C2V_END - -C2V_VMENTRY(jobject, decodePC, (JNIEnv *, jobject, jlong pc)) - stringStream(st); - CodeBlob* blob = CodeCache::find_blob_unsafe((void*) pc); - if (blob == NULL) { - st.print("[unidentified pc]"); - } else { - st.print(blob->name()); - - nmethod* nm = blob->as_nmethod_or_null(); - if (nm != NULL && nm->method() != NULL) { - st.print(" %s.", nm->method()->method_holder()->external_name()); - nm->method()->name()->print_symbol_on(&st); - st.print(" @ %d", pc - (jlong) nm->entry_point()); - } - } - Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL); - return JNIHandles::make_local(result()); -C2V_END - - -#define CC (char*) /*cast a literal from (const char*)*/ -#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f)) - -#define RESOLVED_TYPE "Lcom/oracle/graal/api/meta/ResolvedJavaType;" -#define TYPE "Lcom/oracle/graal/api/meta/JavaType;" -#define METHOD "Lcom/oracle/graal/api/meta/JavaMethod;" -#define FIELD "Lcom/oracle/graal/api/meta/JavaField;" -#define SIGNATURE "Lcom/oracle/graal/api/meta/Signature;" -#define CONSTANT_POOL "Lcom/oracle/graal/api/meta/ConstantPool;" -#define CONSTANT "Lcom/oracle/graal/api/meta/Constant;" -#define KIND "Lcom/oracle/graal/api/meta/Kind;" -#define RUNTIME_CALL "Lcom/oracle/graal/api/code/RuntimeCall;" -#define EXCEPTION_HANDLERS "[Lcom/oracle/graal/api/meta/ExceptionHandler;" -#define REFLECT_METHOD "Ljava/lang/reflect/Method;" -#define REFLECT_CONSTRUCTOR "Ljava/lang/reflect/Constructor;" -#define REFLECT_FIELD "Ljava/lang/reflect/Field;" -#define STRING "Ljava/lang/String;" -#define OBJECT "Ljava/lang/Object;" -#define CLASS "Ljava/lang/Class;" -#define STACK_TRACE_ELEMENT "Ljava/lang/StackTraceElement;" -#define HS_RESOLVED_TYPE "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedObjectType;" -#define HS_RESOLVED_METHOD "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;" -#define HS_RESOLVED_FIELD "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaField;" -#define HS_COMP_RESULT "Lcom/oracle/graal/hotspot/HotSpotCompilationResult;" -#define HS_CONFIG "Lcom/oracle/graal/hotspot/HotSpotVMConfig;" -#define HS_METHOD "Lcom/oracle/graal/hotspot/meta/HotSpotMethod;" -#define HS_INSTALLED_CODE "Lcom/oracle/graal/hotspot/meta/HotSpotInstalledCode;" -#define HS_CODE_INFO "Lcom/oracle/graal/hotspot/meta/HotSpotCodeInfo;" -#define METHOD_DATA "Lcom/oracle/graal/hotspot/meta/HotSpotMethodData;" -#define METASPACE_METHOD "J" -#define METASPACE_METHOD_DATA "J" -#define NMETHOD "J" - -JNINativeMethod CompilerToVM_methods[] = { - {CC"initializeBytecode", CC"("METASPACE_METHOD"[B)[B", FN_PTR(initializeBytecode)}, - {CC"getSignature", CC"("METASPACE_METHOD")"STRING, FN_PTR(getSignature)}, - {CC"initializeExceptionHandlers", CC"("METASPACE_METHOD EXCEPTION_HANDLERS")"EXCEPTION_HANDLERS, FN_PTR(initializeExceptionHandlers)}, - {CC"hasBalancedMonitors", CC"("METASPACE_METHOD")Z", FN_PTR(hasBalancedMonitors)}, - {CC"getUniqueConcreteMethod", CC"("METASPACE_METHOD"["HS_RESOLVED_TYPE")"METASPACE_METHOD, FN_PTR(getUniqueConcreteMethod)}, - {CC"getStackTraceElement", CC"("METASPACE_METHOD"I)"STACK_TRACE_ELEMENT, FN_PTR(getStackTraceElement)}, - {CC"initializeMethod", CC"("METASPACE_METHOD HS_RESOLVED_METHOD")V", FN_PTR(initializeMethod)}, - {CC"initializeMethodData", CC"("METASPACE_METHOD_DATA METHOD_DATA")V", FN_PTR(initializeMethodData)}, - {CC"isMethodCompilable", CC"("METASPACE_METHOD")Z", FN_PTR(isMethodCompilable)}, - {CC"getInvocationCount", CC"("METASPACE_METHOD")I", FN_PTR(getInvocationCount)}, - {CC"getCompiledCodeSize", CC"("METASPACE_METHOD")I", FN_PTR(getCompiledCodeSize)}, - {CC"getVtableEntryOffset", CC"("METASPACE_METHOD")I", FN_PTR(getVtableEntryOffset)}, - {CC"lookupType", CC"("STRING HS_RESOLVED_TYPE"Z)"TYPE, FN_PTR(lookupType)}, - {CC"lookupConstantInPool", CC"("HS_RESOLVED_TYPE"I)"OBJECT, FN_PTR(lookupConstantInPool)}, - {CC"lookupMethodInPool", CC"("HS_RESOLVED_TYPE"IB)"METHOD, FN_PTR(lookupMethodInPool)}, - {CC"lookupTypeInPool", CC"("HS_RESOLVED_TYPE"I)"TYPE, FN_PTR(lookupTypeInPool)}, - {CC"lookupReferencedTypeInPool", CC"("HS_RESOLVED_TYPE"IB)V", FN_PTR(lookupReferencedTypeInPool)}, - {CC"lookupFieldInPool", CC"("HS_RESOLVED_TYPE"IB)"FIELD, FN_PTR(lookupFieldInPool)}, - {CC"resolveMethod", CC"("HS_RESOLVED_TYPE STRING STRING")"METHOD, FN_PTR(resolveMethod)}, - {CC"getInstanceFields", CC"("HS_RESOLVED_TYPE")["HS_RESOLVED_FIELD, FN_PTR(getInstanceFields)}, - {CC"isTypeInitialized", CC"("HS_RESOLVED_TYPE")Z", FN_PTR(isTypeInitialized)}, - {CC"initializeType", CC"("HS_RESOLVED_TYPE")V", FN_PTR(initializeType)}, - {CC"getMaxCallTargetOffset", CC"(J)J", FN_PTR(getMaxCallTargetOffset)}, - {CC"getResolvedType", CC"("CLASS")"RESOLVED_TYPE, FN_PTR(getResolvedType)}, - {CC"getMetaspaceMethod", CC"("REFLECT_METHOD"["HS_RESOLVED_TYPE")"METASPACE_METHOD, FN_PTR(getMetaspaceMethod)}, - {CC"getMetaspaceConstructor", CC"("REFLECT_CONSTRUCTOR"["HS_RESOLVED_TYPE")"METASPACE_METHOD, FN_PTR(getMetaspaceConstructor)}, - {CC"getJavaField", CC"("REFLECT_FIELD")"HS_RESOLVED_FIELD, FN_PTR(getJavaField)}, - {CC"initializeConfiguration", CC"("HS_CONFIG")V", FN_PTR(initializeConfiguration)}, - {CC"installCode0", CC"("HS_COMP_RESULT HS_INSTALLED_CODE HS_CODE_INFO")I", FN_PTR(installCode0)}, - {CC"disassembleNative", CC"([BJ)"STRING, FN_PTR(disassembleNative)}, - {CC"executeCompiledMethod", CC"("METASPACE_METHOD NMETHOD OBJECT OBJECT OBJECT")"OBJECT, FN_PTR(executeCompiledMethod)}, - {CC"executeCompiledMethodVarargs", CC"("METASPACE_METHOD NMETHOD "["OBJECT")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, - {CC"getDeoptedLeafGraphIds", CC"()[J", FN_PTR(getDeoptedLeafGraphIds)}, - {CC"decodePC", CC"(J)"STRING, FN_PTR(decodePC)}, -}; - -int CompilerToVM_methods_count() { - return sizeof(CompilerToVM_methods) / sizeof(JNINativeMethod); -} - +/* + * Copyright (c) 2011, 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. + */ + +#include "precompiled.hpp" +#include "runtime/fieldDescriptor.hpp" +#include "memory/oopFactory.hpp" +#include "oops/generateOopMap.hpp" +#include "oops/fieldStreams.hpp" +#include "runtime/javaCalls.hpp" +#include "graal/graalRuntime.hpp" +#include "compiler/compileBroker.hpp" +#include "compiler/compilerOracle.hpp" +#include "graal/graalCompilerToVM.hpp" +#include "graal/graalCompiler.hpp" +#include "graal/graalEnv.hpp" +#include "graal/graalJavaAccess.hpp" +#include "graal/graalCodeInstaller.hpp" +#include "graal/graalVMToCompiler.hpp" +#include "graal/graalVmIds.hpp" + + +Method* getMethodFromHotSpotMethod(oop hotspot_method) { + assert(hotspot_method != NULL && hotspot_method->is_a(HotSpotResolvedJavaMethod::klass()), "sanity"); + return asMethod(HotSpotResolvedJavaMethod::metaspaceMethod(hotspot_method)); +} + +// Entry to native method implementation that transitions current thread to '_thread_in_vm'. +#define C2V_VMENTRY(result_type, name, signature) \ + JNIEXPORT result_type JNICALL c2v_ ## name signature { \ + TRACE_graal_3("CompilerToVM::" #name); \ + GRAAL_VM_ENTRY_MARK; \ + +// Entry to native method implementation that calls a JNI function +// and hence cannot transition current thread to '_thread_in_vm'. +#define C2V_ENTRY(result_type, name, signature) \ + JNIEXPORT result_type JNICALL c2v_ ## name signature { \ + TRACE_graal_3("CompilerToVM::" #name); \ + +#define C2V_END } + +C2V_ENTRY(jbyteArray, initializeBytecode, (JNIEnv *env, jobject, jlong metaspace_method, jbyteArray result)) + methodHandle method = asMethod(metaspace_method); + ResourceMark rm; + + int code_size = method->code_size(); + jbyte* reconstituted_code = NULL; + + // replace all breakpoints - must be done before undoing any rewriting + if (method->number_of_breakpoints() > 0) { + reconstituted_code = NEW_RESOURCE_ARRAY(jbyte, code_size); + memcpy(reconstituted_code, (jbyte *) method->code_base(), code_size); + BreakpointInfo* bp = InstanceKlass::cast(method->method_holder())->breakpoints(); + for (; bp != NULL; bp = bp->next()) { + if (bp->match(method())) { + jbyte code = bp->orig_bytecode(); + reconstituted_code[bp->bci()] = code; + } + } + } + + // iterate over all bytecodes and replace non-Java bytecodes + if (RewriteBytecodes || RewriteFrequentPairs || InstanceKlass::cast(method->method_holder())->is_rewritten()) { + if (reconstituted_code == NULL) { + reconstituted_code = NEW_RESOURCE_ARRAY(jbyte, code_size); + memcpy(reconstituted_code, (jbyte *) method->code_base(), code_size); + } + BytecodeStream s(method); + while(!s.is_last_bytecode()) { + s.next(); + Bytecodes::Code opcode = s.raw_code(); + if (!Bytecodes::is_java_code(opcode)) { + jbyte original_opcode = Bytecodes::java_code(opcode); + int bci = s.bci(); + reconstituted_code[bci] = original_opcode; + if (opcode == Bytecodes::_fast_aldc_w) { + int cpci = Bytes::get_native_u2((address) reconstituted_code + bci + 1); + int i = method->constants()->object_to_cp_index(cpci); + assert(i < method->constants()->length(), "sanity check"); + Bytes::put_Java_u2((address) reconstituted_code + bci + 1, (u2)i); + } else if (opcode == Bytecodes::_fast_aldc) { + int cpci = reconstituted_code[bci + 1] & 0xff; + int i = method->constants()->object_to_cp_index(cpci); + assert(i < method->constants()->length(), "sanity check"); + reconstituted_code[bci + 1] = (jbyte)i; + } + } + } + } + + if (reconstituted_code == NULL) { + env->SetByteArrayRegion(result, 0, code_size, (jbyte *) method->code_base()); + } else { + env->SetByteArrayRegion(result, 0, code_size, reconstituted_code); + } + + return result; +C2V_END + +C2V_VMENTRY(jstring, getSignature, (JNIEnv *env, jobject, jlong metaspace_method)) + Method* method = asMethod(metaspace_method); + assert(method != NULL && method->signature() != NULL, "signature required"); + return VmIds::toString<jstring>(method->signature(), THREAD); +C2V_END + +C2V_VMENTRY(jobjectArray, initializeExceptionHandlers, (JNIEnv *, jobject, jlong metaspace_method, jobjectArray java_handlers)) + ResourceMark rm; + methodHandle method = asMethod(metaspace_method); + int handler_count = method->exception_table_length(); + objArrayHandle array = (objArrayOop) JNIHandles::resolve(java_handlers); + assert(array->length() == handler_count, "wrong length"); + ExceptionTableElement* handlers = handler_count == 0 ? NULL : method->exception_table_start(); + + for (int i = 0; i < handler_count; i++) { + ExceptionTableElement* handler = handlers + i; + Handle entry = array->obj_at(i); + assert(!entry.is_null(), "entry should not be null"); + ExceptionHandler::set_startBCI(entry, handler->start_pc); + ExceptionHandler::set_endBCI(entry, handler->end_pc); + ExceptionHandler::set_handlerBCI(entry, handler->handler_pc); + int catch_class_index = handler->catch_type_index; + ExceptionHandler::set_catchTypeCPI(entry, catch_class_index); + + if (catch_class_index == 0) { + ExceptionHandler::set_catchType(entry, NULL); + } else { + ConstantPool* cp = InstanceKlass::cast(method->method_holder())->constants(); + KlassHandle loading_klass = method->method_holder(); + Handle catch_class = GraalCompiler::get_JavaType(cp, catch_class_index, loading_klass, CHECK_NULL); + if (catch_class->klass() == HotSpotResolvedObjectType::klass() && java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(catch_class)) == SystemDictionary::Throwable_klass()) { + ExceptionHandler::set_catchType(entry, NULL); + ExceptionHandler::set_catchTypeCPI(entry, 0); + } else { + ExceptionHandler::set_catchType(entry, catch_class()); + } + } + array->obj_at_put(i, entry()); + } + + return (jobjectArray) JNIHandles::make_local(array()); +C2V_END + +C2V_VMENTRY(jint, hasBalancedMonitors, (JNIEnv *, jobject, jlong metaspace_method)) + + // Analyze the method to see if monitors are used properly. + methodHandle method(THREAD, asMethod(metaspace_method)); + assert(method->has_monitor_bytecodes(), "should have checked this"); + + // Check to see if a previous compilation computed the monitor-matching analysis. + if (method->guaranteed_monitor_matching()) { + return true; + } + + { + EXCEPTION_MARK; + ResourceMark rm(THREAD); + GeneratePairingInfo gpi(method); + gpi.compute_map(CATCH); + if (!gpi.monitor_safe()) { + return false; + } + method->set_guaranteed_monitor_matching(); + } + return true; +C2V_END + +C2V_VMENTRY(jlong, getMetaspaceMethod, (JNIEnv *, jobject, jobject reflection_method_handle, jobject resultHolder)) + oop reflection_method = JNIHandles::resolve(reflection_method_handle); + oop reflection_holder = java_lang_reflect_Method::clazz(reflection_method); + int slot = java_lang_reflect_Method::slot(reflection_method); + Klass* holder = java_lang_Class::as_Klass(reflection_holder); + methodHandle method = InstanceKlass::cast(holder)->method_with_idnum(slot); + Handle type = GraalCompiler::createHotSpotResolvedObjectType(method, CHECK_0); + objArrayOop(JNIHandles::resolve(resultHolder))->obj_at_put(0, type()); + return (jlong) (address) method(); +} + +C2V_VMENTRY(jlong, getMetaspaceConstructor, (JNIEnv *, jobject, jobject reflection_ctor_handle, jobject resultHolder)) + oop reflection_ctor = JNIHandles::resolve(reflection_ctor_handle); + oop reflection_holder = java_lang_reflect_Constructor::clazz(reflection_ctor); + int slot = java_lang_reflect_Constructor::slot(reflection_ctor); + Klass* holder = java_lang_Class::as_Klass(reflection_holder); + methodHandle method = InstanceKlass::cast(holder)->method_with_idnum(slot); + Handle type = GraalCompiler::createHotSpotResolvedObjectType(method, CHECK_0); + objArrayOop(JNIHandles::resolve(resultHolder))->obj_at_put(0, type()); + return (jlong) (address) method(); +} + +C2V_VMENTRY(jobject, getJavaField, (JNIEnv *, jobject, jobject reflection_field_handle)) + oop reflection_field = JNIHandles::resolve(reflection_field_handle); + oop reflection_holder = java_lang_reflect_Field::clazz(reflection_field); + int slot = java_lang_reflect_Field::slot(reflection_field); + InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(reflection_holder)); + + int offset = holder->field_offset(slot); + int flags = holder->field_access_flags(slot); + Symbol* field_name = holder->field_name(slot); + Handle field_holder = GraalCompiler::get_JavaTypeFromClass(reflection_holder, CHECK_NULL); + Handle field_type = GraalCompiler::get_JavaTypeFromClass(java_lang_reflect_Field::type(reflection_field), CHECK_NULL); + + Handle ret = GraalCompiler::get_JavaField(offset, flags, field_name, field_holder, field_type, CHECK_NULL); + return JNIHandles::make_local(THREAD, ret()); +} + +C2V_VMENTRY(jlong, getUniqueConcreteMethod, (JNIEnv *, jobject, jlong metaspace_method, jobject resultHolder)) + methodHandle method = asMethod(metaspace_method); + KlassHandle holder = method->method_holder(); + if (holder->is_interface()) { + // Cannot trust interfaces. Because of: + // interface I { void foo(); } + // class A { public void foo() {} } + // class B extends A implements I { } + // class C extends B { public void foo() { } } + // class D extends B { } + // Would lead to identify C.foo() as the unique concrete method for I.foo() without seeing A.foo(). + return 0L; + } + methodHandle ucm; + { + ResourceMark rm; + MutexLocker locker(Compile_lock); + ucm = Dependencies::find_unique_concrete_method(holder(), method()); + } + + if (ucm.is_null()) { + return 0L; + } + + Handle type = GraalCompiler::createHotSpotResolvedObjectType(ucm(), CHECK_0); + objArrayOop(JNIHandles::resolve(resultHolder))->obj_at_put(0, type()); + return (jlong) (address) ucm(); +C2V_END + +C2V_ENTRY(jint, getInvocationCount, (JNIEnv *, jobject, jlong metaspace_method)) + Method* method = asMethod(metaspace_method); + return method->invocation_count(); +C2V_END + +C2V_VMENTRY(void, initializeMethod,(JNIEnv *, jobject, jlong metaspace_method, jobject hotspot_method)) + methodHandle method = asMethod(metaspace_method); + Handle name = VmIds::toString<Handle>(method->name(), CHECK); + InstanceKlass::cast(HotSpotResolvedJavaMethod::klass())->initialize(CHECK); + HotSpotResolvedJavaMethod::set_name(hotspot_method, name()); + HotSpotResolvedJavaMethod::set_codeSize(hotspot_method, method->code_size()); + HotSpotResolvedJavaMethod::set_exceptionHandlerCount(hotspot_method, method->exception_table_length()); +C2V_END + +C2V_VMENTRY(jboolean, isMethodCompilable,(JNIEnv *, jobject, jlong metaspace_method)) + methodHandle method = asMethod(metaspace_method); + return !method->is_not_compilable() && !CompilerOracle::should_not_inline(method); +C2V_END + +C2V_VMENTRY(void, initializeMethodData,(JNIEnv *, jobject, jlong metaspace_method_data, jobject hotspot_method_data)) + MethodData* method_data = asMethodData(metaspace_method_data); + HotSpotMethodData::set_normalDataSize(hotspot_method_data, method_data->data_size()); + HotSpotMethodData::set_extraDataSize(hotspot_method_data, method_data->extra_data_size()); +C2V_END + +// ------------------------------------------------------------------ +// Adjust a CounterData count to be commensurate with +// interpreter_invocation_count. If the MDO exists for +// only 25% of the time the method exists, then the +// counts in the MDO should be scaled by 4X, so that +// they can be usefully and stably compared against the +// invocation counts in methods. +int scale_count(MethodData* method_data, int count) { + if (count > 0) { + int counter_life; + int method_life = method_data->method()->interpreter_invocation_count(); + int current_mileage = MethodData::mileage_of(method_data->method()); + int creation_mileage = method_data->creation_mileage(); + counter_life = current_mileage - creation_mileage; + + // counter_life due to backedge_counter could be > method_life + if (counter_life > method_life) + counter_life = method_life; + if (0 < counter_life && counter_life <= method_life) { + count = (int)((double)count * method_life / counter_life + 0.5); + count = (count > 0) ? count : 1; + } + } + return count; +} + +C2V_ENTRY(jint, getCompiledCodeSize, (JNIEnv *env, jobject, jlong metaspace_method)) + nmethod* code = (asMethod(metaspace_method))->code(); + return code == NULL ? 0 : code->insts_size(); +C2V_END + +C2V_VMENTRY(jobject, lookupType, (JNIEnv *env, jobject, jstring jname, jobject accessingClass, jboolean eagerResolve)) + ResourceMark rm; + + Symbol* nameSymbol = VmIds::toSymbol(jname); + Handle name = JNIHandles::resolve(jname); + assert(nameSymbol != NULL, "name to symbol creation failed"); + + oop result = NULL; + if (nameSymbol == vmSymbols::int_signature()) { + result = VMToCompiler::createPrimitiveJavaType((int) T_INT, THREAD); + } else if (nameSymbol == vmSymbols::long_signature()) { + result = VMToCompiler::createPrimitiveJavaType((int) T_LONG, THREAD); + } else if (nameSymbol == vmSymbols::bool_signature()) { + result = VMToCompiler::createPrimitiveJavaType((int) T_BOOLEAN, THREAD); + } else if (nameSymbol == vmSymbols::char_signature()) { + result = VMToCompiler::createPrimitiveJavaType((int) T_CHAR, THREAD); + } else if (nameSymbol == vmSymbols::short_signature()) { + result = VMToCompiler::createPrimitiveJavaType((int) T_SHORT, THREAD); + } else if (nameSymbol == vmSymbols::byte_signature()) { + result = VMToCompiler::createPrimitiveJavaType((int) T_BYTE, THREAD); + } else if (nameSymbol == vmSymbols::double_signature()) { + result = VMToCompiler::createPrimitiveJavaType((int) T_DOUBLE, THREAD); + } else if (nameSymbol == vmSymbols::float_signature()) { + result = VMToCompiler::createPrimitiveJavaType((int) T_FLOAT, THREAD); + } else if (nameSymbol == vmSymbols::void_signature()) { + result = VMToCompiler::createPrimitiveJavaType((int) T_VOID, THREAD); + } else { + Klass* resolved_type = NULL; + Handle classloader; + Handle protectionDomain; + if (JNIHandles::resolve(accessingClass) != NULL) { + classloader = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(accessingClass))->class_loader(); + protectionDomain = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(accessingClass))->protection_domain(); + } + + if (eagerResolve) { + resolved_type = SystemDictionary::resolve_or_fail(nameSymbol, classloader, protectionDomain, true, THREAD); + } else { + resolved_type = SystemDictionary::resolve_or_null(nameSymbol, classloader, protectionDomain, THREAD); + } + + if (!HAS_PENDING_EXCEPTION) { + if (resolved_type == NULL) { + assert(!eagerResolve, "failed eager resolution should have caused an exception"); + Handle type = VMToCompiler::createUnresolvedJavaType(name, THREAD); + result = type(); + } else { + Handle type = GraalCompiler::createHotSpotResolvedObjectType(resolved_type, name, CHECK_NULL); + result = type(); + } + } + } + + return JNIHandles::make_local(THREAD, result); +C2V_END + +C2V_VMENTRY(jobject, lookupConstantInPool, (JNIEnv *env, jobject, jobject type, jint index)) + + ConstantPool* cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants(); + + oop result = NULL; + constantTag tag = cp->tag_at(index); + if (tag.is_int()) { + result = VMToCompiler::createConstant(Kind::Int(), cp->int_at(index), CHECK_0); + } else if (tag.is_long()) { + result = VMToCompiler::createConstant(Kind::Long(), cp->long_at(index), CHECK_0); + } else if (tag.is_float()) { + result = VMToCompiler::createConstantFloat(cp->float_at(index), CHECK_0); + } else if (tag.is_double()) { + result = VMToCompiler::createConstantDouble(cp->double_at(index), CHECK_0); + } else if (tag.is_string()) { + oop string = NULL; + if (cp->is_pseudo_string_at(index)) { + int obj_index = cp->cp_to_object_index(index); + string = cp->pseudo_string_at(index, obj_index); + } else { + string = cp->string_at(index, THREAD); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + // TODO: Gracefully exit compilation. + fatal("out of memory during compilation!"); + return NULL; + } + } + result = VMToCompiler::createConstantObject(string, CHECK_0); + } else if (tag.is_klass() || tag.is_unresolved_klass()) { + Handle type = GraalCompiler::get_JavaType(cp, index, cp->pool_holder(), CHECK_NULL); + result = type(); + } else if (tag.is_object()) { + oop obj = cp->object_at(index); + assert(obj->is_instance(), "must be an instance"); + result = VMToCompiler::createConstantObject(obj, CHECK_NULL); + } else { + tty->print("unknown constant pool tag (%s) at cpi %d in %s: ", tag.internal_name(), index, cp->pool_holder()->name()->as_C_string()); + ShouldNotReachHere(); + } + + return JNIHandles::make_local(THREAD, result); +C2V_END + +C2V_VMENTRY(jobject, lookupMethodInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte opcode)) + index = GraalCompiler::to_cp_index_u2(index); + constantPoolHandle cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants(); + instanceKlassHandle pool_holder(cp->pool_holder()); + + Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF); + methodHandle method = GraalEnv::get_method_by_index(cp, index, bc, pool_holder); + if (!method.is_null()) { + Handle holder = GraalCompiler::get_JavaType(method->method_holder(), CHECK_NULL); + return JNIHandles::make_local(THREAD, VMToCompiler::createResolvedJavaMethod(holder, method(), THREAD)); + } else { + // Get the method's name and signature. + Handle name = VmIds::toString<Handle>(cp->name_ref_at(index), CHECK_NULL); + Handle signature = VmIds::toString<Handle>(cp->signature_ref_at(index), CHECK_NULL); + int holder_index = cp->klass_ref_index_at(index); + Handle type = GraalCompiler::get_JavaType(cp, holder_index, cp->pool_holder(), CHECK_NULL); + return JNIHandles::make_local(THREAD, VMToCompiler::createUnresolvedJavaMethod(name, signature, type, THREAD)); + } +C2V_END + +C2V_VMENTRY(jobject, lookupTypeInPool, (JNIEnv *env, jobject, jobject type, jint index)) + + ConstantPool* cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants(); + Handle result = GraalCompiler::get_JavaType(cp, index, cp->pool_holder(), CHECK_NULL); + return JNIHandles::make_local(THREAD, result()); +C2V_END + +C2V_VMENTRY(void, lookupReferencedTypeInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte op)) + ConstantPool* cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants(); + int opcode = (op & 0xFF); + if (opcode != Bytecodes::_checkcast && opcode != Bytecodes::_instanceof && opcode != Bytecodes::_new && opcode != Bytecodes::_anewarray + && opcode != Bytecodes::_multianewarray && opcode != Bytecodes::_ldc && opcode != Bytecodes::_ldc_w && opcode != Bytecodes::_ldc2_w) + { + index = cp->remap_instruction_operand_from_cache(GraalCompiler::to_cp_index_u2(index)); + } + constantTag tag = cp->tag_at(index); + if (tag.is_field_or_method()) { + index = cp->uncached_klass_ref_index_at(index); + tag = cp->tag_at(index); + } + + if (tag.is_unresolved_klass() || tag.is_klass()) { + Klass* klass = cp->klass_at(index, CHECK); + if (klass->oop_is_instance()) { + InstanceKlass::cast(klass)->initialize(CHECK); + } + } +C2V_END + +C2V_VMENTRY(jobject, lookupFieldInPool, (JNIEnv *env, jobject, jobject constantPoolHolder, jint index, jbyte opcode)) + ResourceMark rm; + + index = GraalCompiler::to_cp_index_u2(index); + constantPoolHandle cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(constantPoolHolder)))->constants(); + + int nt_index = cp->name_and_type_ref_index_at(index); + int sig_index = cp->signature_ref_index_at(nt_index); + Symbol* signature = cp->symbol_at(sig_index); + int name_index = cp->name_ref_index_at(nt_index); + Symbol* name = cp->symbol_at(name_index); + int holder_index = cp->klass_ref_index_at(index); + Handle holder = GraalCompiler::get_JavaType(cp, holder_index, cp->pool_holder(), CHECK_NULL); + instanceKlassHandle holder_klass; + + Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF); + int offset = -1; + AccessFlags flags; + BasicType basic_type; + if (holder->klass() == SystemDictionary::HotSpotResolvedObjectType_klass()) { + FieldAccessInfo result; + LinkResolver::resolve_field(result, cp, index, + Bytecodes::java_code(code), + true, false, Thread::current()); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + } else { + offset = result.field_offset(); + flags = result.access_flags(); + holder_klass = result.klass()(); + basic_type = result.field_type(); + holder = GraalCompiler::get_JavaType(holder_klass, CHECK_NULL); + } + } + + Handle type = GraalCompiler::get_JavaTypeFromSignature(signature, cp->pool_holder(), CHECK_NULL); + Handle field_handle = GraalCompiler::get_JavaField(offset, flags.as_int(), name, holder, type, THREAD); + + return JNIHandles::make_local(THREAD, field_handle()); +C2V_END + +C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject resolved_type, jstring name, jstring signature)) + + assert(JNIHandles::resolve(resolved_type) != NULL, ""); + Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(resolved_type)); + Symbol* name_symbol = VmIds::toSymbol(name); + Symbol* signature_symbol = VmIds::toSymbol(signature); + methodHandle method = klass->lookup_method(name_symbol, signature_symbol); + if (method.is_null()) { + if (TraceGraal >= 3) { + ResourceMark rm; + tty->print_cr("Could not resolve method %s %s on klass %s", name_symbol->as_C_string(), signature_symbol->as_C_string(), klass->name()->as_C_string()); + } + return NULL; + } + Handle holder = GraalCompiler::get_JavaType(method->method_holder(), CHECK_NULL); + return JNIHandles::make_local(THREAD, VMToCompiler::createResolvedJavaMethod(holder, method(), THREAD)); +C2V_END + +C2V_VMENTRY(jboolean, isTypeInitialized,(JNIEnv *, jobject, jobject hotspot_klass)) + Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(hotspot_klass)); + assert(klass != NULL, "method must not be called for primitive types"); + return InstanceKlass::cast(klass)->is_initialized(); +C2V_END + +C2V_VMENTRY(void, initializeType, (JNIEnv *, jobject, jobject hotspot_klass)) + Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(hotspot_klass)); + assert(klass != NULL, "method must not be called for primitive types"); + InstanceKlass::cast(klass)->initialize(JavaThread::current()); +C2V_END + +C2V_VMENTRY(jobject, getInstanceFields, (JNIEnv *, jobject, jobject klass)) + ResourceMark rm; + + instanceKlassHandle k = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(klass)); + GrowableArray<Handle> fields(k->java_fields_count()); + + for (AllFieldStream fs(k()); !fs.done(); fs.next()) { + if (!fs.access_flags().is_static()) { + Handle type = GraalCompiler::get_JavaTypeFromSignature(fs.signature(), k, Thread::current()); + int flags = fs.access_flags().as_int(); + bool internal = fs.access_flags().is_internal(); + Handle name = VmIds::toString<Handle>(fs.name(), Thread::current()); + Handle field = VMToCompiler::createJavaField(JNIHandles::resolve(klass), name, type, fs.offset(), flags, internal, Thread::current()); + fields.append(field()); + } + } + objArrayHandle field_array = oopFactory::new_objArray(SystemDictionary::HotSpotResolvedJavaField_klass(), fields.length(), CHECK_NULL); + for (int i = 0; i < fields.length(); ++i) { + field_array->obj_at_put(i, fields.at(i)()); + } + return JNIHandles::make_local(field_array()); +C2V_END + +C2V_VMENTRY(jlong, getMaxCallTargetOffset, (JNIEnv *env, jobject, jlong stub)) + address target_addr = (address) stub; + if (target_addr != 0x0) { + int64_t off_low = (int64_t)target_addr - ((int64_t)CodeCache::low_bound() + sizeof(int)); + int64_t off_high = (int64_t)target_addr - ((int64_t)CodeCache::high_bound() + sizeof(int)); + return MAX2(ABS(off_low), ABS(off_high)); + } + return -1; +C2V_END + +C2V_VMENTRY(jobject, getResolvedType, (JNIEnv *env, jobject, jobject javaClass)) + oop java_mirror = JNIHandles::resolve(javaClass); + assert(java_mirror != NULL, "argument to CompilerToVM.getResolvedType must not be NULL"); + Handle type = GraalCompiler::get_JavaTypeFromClass(java_mirror, CHECK_NULL); + return JNIHandles::make_local(THREAD, type()); +C2V_END + + +// helpers used to set fields in the HotSpotVMConfig object +jfieldID getFieldID(JNIEnv* env, jobject obj, const char* name, const char* sig) { + jfieldID id = env->GetFieldID(env->GetObjectClass(obj), name, sig); + if (id == NULL) { + fatal(err_msg("field not found: %s (%s)", name, sig)); + } + return id; +} + +BasicType basicTypes[] = { T_BOOLEAN, T_BYTE, T_SHORT, T_CHAR, T_INT, T_FLOAT, T_LONG, T_DOUBLE, T_OBJECT }; +int basicTypeCount = sizeof(basicTypes) / sizeof(BasicType); + +C2V_ENTRY(void, initializeConfiguration, (JNIEnv *env, jobject, jobject config)) + +#define set_boolean(name, value) do { env->SetBooleanField(config, getFieldID(env, config, name, "Z"), value); } while (0) +#define set_int(name, value) do { env->SetIntField(config, getFieldID(env, config, name, "I"), value); } while (0) +#define set_long(name, value) do { env->SetLongField(config, getFieldID(env, config, name, "J"), value); } while (0) +#define set_object(name, value) do { env->SetObjectField(config, getFieldID(env, config, name, "Ljava/lang/Object;"), value); } while (0) +#define set_int_array(name, value) do { env->SetObjectField(config, getFieldID(env, config, name, "[I"), value); } while (0) + + guarantee(HeapWordSize == sizeof(char*), "Graal assumption that HeadWordSize == machine word size is wrong"); +#ifdef _WIN64 + set_boolean(env, config, "windowsOs", true); +#else + set_boolean("windowsOs", false); +#endif + set_boolean("verifyOops", VerifyOops); + set_boolean("useFastLocking", UseFastLocking); + set_boolean("useFastNewObjectArray", UseFastNewObjectArray); + set_boolean("useBiasedLocking", UseBiasedLocking); + set_boolean("useFastNewTypeArray", UseFastNewTypeArray); + set_boolean("useTLAB", UseTLAB); + set_int("codeEntryAlignment", CodeEntryAlignment); + set_int("vmPageSize", os::vm_page_size()); + set_int("stackShadowPages", StackShadowPages); + set_int("hubOffset", oopDesc::klass_offset_in_bytes()); + set_int("markOffset", oopDesc::mark_offset_in_bytes()); + set_int("prototypeMarkWordOffset", in_bytes(Klass::prototype_header_offset())); + set_int("superCheckOffsetOffset", in_bytes(Klass::super_check_offset_offset())); + set_int("secondarySuperCacheOffset", in_bytes(Klass::secondary_super_cache_offset())); + set_int("secondarySupersOffset", in_bytes(Klass::secondary_supers_offset())); + set_int("subklassOffset", in_bytes(Klass::subklass_offset())); + set_int("nextSiblingOffset", in_bytes(Klass::next_sibling_offset())); + set_int("arrayLengthOffset", arrayOopDesc::length_offset_in_bytes()); + set_int("klassStateOffset", in_bytes(InstanceKlass::init_state_offset())); + set_int("klassStateFullyInitialized", (int)InstanceKlass::fully_initialized); + set_int("threadTlabTopOffset", in_bytes(JavaThread::tlab_top_offset())); + set_int("threadTlabEndOffset", in_bytes(JavaThread::tlab_end_offset())); + set_int("threadObjectOffset", in_bytes(JavaThread::threadObj_offset())); + set_int("osThreadOffset", in_bytes(JavaThread::osthread_offset())); + set_int("osThreadInterruptedOffset", in_bytes(OSThread::interrupted_offset())); + set_int("unlockedMask", (int) markOopDesc::unlocked_value); + set_int("biasedLockMaskInPlace", (int) markOopDesc::biased_lock_mask_in_place); + set_int("ageMaskInPlace", (int) markOopDesc::age_mask_in_place); + set_int("epochMaskInPlace", (int) markOopDesc::epoch_mask_in_place); + set_int("biasedLockPattern", (int) markOopDesc::biased_lock_pattern); + set_int("methodMaxLocalsOffset", in_bytes(Method::size_of_locals_offset())); + set_int("methodMaxStackOffset", in_bytes(Method::max_stack_offset())); + set_int("extraStackEntries", Method::extra_stack_entries()); + set_int("methodAccessFlagsOffset", in_bytes(Method::access_flags_offset())); + set_int("klassHasFinalizerFlag", JVM_ACC_HAS_FINALIZER); + set_int("threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset())); + set_int("threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset())); + set_long("safepointPollingAddress", (jlong)(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); + set_boolean("isPollingPageFar", Assembler::is_polling_page_far()); + set_int("classMirrorOffset", in_bytes(Klass::java_mirror_offset())); + set_int("runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes); + set_int("klassModifierFlagsOffset", in_bytes(Klass::modifier_flags_offset())); + set_int("klassAccessFlagsOffset", in_bytes(Klass::access_flags_offset())); + set_int("klassOffset", java_lang_Class::klass_offset_in_bytes()); + set_int("graalMirrorInClassOffset", java_lang_Class::graal_mirror_offset_in_bytes()); + set_int("klassLayoutHelperOffset", in_bytes(Klass::layout_helper_offset())); + set_int("klassSuperKlassOffset", in_bytes(Klass::super_offset())); + set_int("methodDataOffset", in_bytes(Method::method_data_offset())); + set_int("nmethodEntryOffset", nmethod::verified_entry_point_offset()); + set_int("methodCompiledEntryOffset", in_bytes(Method::from_compiled_offset())); + set_int("basicLockSize", sizeof(BasicLock)); + set_int("basicLockDisplacedHeaderOffset", BasicLock::displaced_header_offset_in_bytes()); + set_int("uninitializedIdentityHashCodeValue", markOopDesc::no_hash); + set_int("identityHashCodeShift", markOopDesc::hash_shift); + + set_int("arrayKlassLayoutHelperIdentifier", 0x80000000); + assert((Klass::_lh_array_tag_obj_value & Klass::_lh_array_tag_type_value & 0x80000000) != 0, "obj_array and type_array must have first bit set"); + set_int("arrayKlassComponentMirrorOffset", in_bytes(ArrayKlass::component_mirror_offset())); + + set_int("metaspaceArrayLengthOffset", Array<Klass*>::length_offset_in_bytes()); + set_int("metaspaceArrayBaseOffset", Array<Klass*>::base_offset_in_bytes()); + set_int("methodDataOopDataOffset", in_bytes(MethodData::data_offset())); + set_int("methodDataOopTrapHistoryOffset", in_bytes(MethodData::trap_history_offset())); + set_int("dataLayoutHeaderSize", DataLayout::header_size_in_bytes()); + set_int("dataLayoutTagOffset", in_bytes(DataLayout::tag_offset())); + set_int("dataLayoutFlagsOffset", in_bytes(DataLayout::flags_offset())); + set_int("dataLayoutBCIOffset", in_bytes(DataLayout::bci_offset())); + set_int("dataLayoutCellsOffset", in_bytes(DataLayout::cell_offset(0))); + set_int("dataLayoutCellSize", DataLayout::cell_size); + set_int("bciProfileWidth", BciProfileWidth); + set_int("typeProfileWidth", TypeProfileWidth); + + set_int("tlabAlignmentReserve", (int32_t)ThreadLocalAllocBuffer::alignment_reserve()); + set_long("tlabIntArrayMarkWord", (intptr_t)markOopDesc::prototype()->copy_set_hash(0x2)); + set_long("heapTopAddress", (jlong)(address) Universe::heap()->top_addr()); + set_long("heapEndAddress", (jlong)(address) Universe::heap()->end_addr()); + set_int("threadTlabStartOffset", in_bytes(JavaThread::tlab_start_offset())); + set_int("threadTlabSizeOffset", in_bytes(JavaThread::tlab_size_offset())); + set_int("threadAllocatedBytesOffset", in_bytes(JavaThread::allocated_bytes_offset())); + set_int("tlabSlowAllocationsOffset", in_bytes(JavaThread::tlab_slow_allocations_offset())); + set_int("tlabFastRefillWasteOffset", in_bytes(JavaThread::tlab_fast_refill_waste_offset())); + set_int("tlabNumberOfRefillsOffset", in_bytes(JavaThread::tlab_number_of_refills_offset())); + set_int("tlabRefillWasteLimitOffset", in_bytes(JavaThread::tlab_refill_waste_limit_offset())); + set_int("tlabRefillWasteIncrement", (int32_t) ThreadLocalAllocBuffer::refill_waste_limit_increment()); + set_int("klassInstanceSizeOffset", in_bytes(Klass::layout_helper_offset())); + set_boolean("tlabStats", TLABStats); + set_boolean("inlineContiguousAllocationSupported", !CMSIncrementalMode && Universe::heap()->supports_inline_contig_alloc()); + + set_long("arrayPrototypeMarkWord", (intptr_t)markOopDesc::prototype()); + set_int("layoutHelperLog2ElementSizeShift", Klass::_lh_log2_element_size_shift); + set_int("layoutHelperLog2ElementSizeMask", Klass::_lh_log2_element_size_mask); + set_int("layoutHelperElementTypeShift", Klass::_lh_element_type_shift); + set_int("layoutHelperElementTypeMask", Klass::_lh_element_type_mask); + set_int("layoutHelperHeaderSizeShift", Klass::_lh_header_size_shift); + set_int("layoutHelperHeaderSizeMask", Klass::_lh_header_size_mask); + set_int("layoutHelperOffset", in_bytes(Klass::layout_helper_offset())); + + set_long("debugStub", VmIds::addStub((address)warning)); + set_long("instanceofStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_slow_subtype_check_id))); + set_long("newInstanceStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_instance_id))); + set_long("newArrayStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_array_id))); + set_long("newMultiArrayStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_multi_array_id))); + set_long("identityHashCodeStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_identity_hash_code_id))); + set_long("threadIsInterruptedStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_thread_is_interrupted_id))); + set_long("inlineCacheMissStub", VmIds::addStub(SharedRuntime::get_ic_miss_stub())); + set_long("handleExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_handle_exception_nofpu_id))); + set_long("handleDeoptStub", VmIds::addStub(SharedRuntime::deopt_blob()->unpack())); + set_long("monitorEnterStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_monitorenter_id))); + set_long("monitorExitStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_monitorexit_id))); + set_long("verifyOopStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_verify_oop_id))); + set_long("vmErrorStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_vm_error_id))); + set_long("deoptimizeStub", VmIds::addStub(SharedRuntime::deopt_blob()->uncommon_trap())); + set_long("unwindExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_unwind_exception_call_id))); + set_long("osrMigrationEndStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_OSR_migration_end_id))); + set_long("registerFinalizerStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_register_finalizer_id))); + set_long("setDeoptInfoStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_set_deopt_info_id))); + set_long("createNullPointerExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_create_null_pointer_exception_id))); + set_long("createOutOfBoundsExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_create_out_of_bounds_exception_id))); + set_long("javaTimeMillisStub", VmIds::addStub(CAST_FROM_FN_PTR(address, os::javaTimeMillis))); + set_long("javaTimeNanosStub", VmIds::addStub(CAST_FROM_FN_PTR(address, os::javaTimeNanos))); + set_long("arithmeticFremStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_arithmetic_frem_id))); + set_long("arithmeticDremStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_arithmetic_drem_id))); + set_long("arithmeticSinStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dsin))); + set_long("arithmeticCosStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dcos))); + set_long("arithmeticTanStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dtan))); + set_long("logPrimitiveStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_primitive_id))); + set_long("logObjectStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_object_id))); + set_long("logPrintfStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_printf_id))); + + + BarrierSet* bs = Universe::heap()->barrier_set(); + switch (bs->kind()) { + case BarrierSet::CardTableModRef: + case BarrierSet::CardTableExtension: { + jlong base = (jlong)((CardTableModRefBS*)bs)->byte_map_base; + assert(base != 0, "unexpected byte_map_base"); + set_long("cardtableStartAddress", base); + set_int("cardtableShift", CardTableModRefBS::card_shift); + break; + } + case BarrierSet::ModRef: + case BarrierSet::Other: + set_long("cardtableStartAddress", 0); + set_int("cardtableShift", 0); + // No post barriers + break; +#ifndef SERIALGC + case BarrierSet::G1SATBCT: + case BarrierSet::G1SATBCTLogging: +#endif // SERIALGC + default: + ShouldNotReachHere(); + break; + } + + set_int("arrayClassElementOffset", in_bytes(ObjArrayKlass::element_klass_offset())); + +#undef set_boolean +#undef set_int +#undef set_long +#undef set_object +#undef set_int_array + +C2V_END + +C2V_VMENTRY(jint, installCode0, (JNIEnv *jniEnv, jobject, jobject compResult, jobject installed_code, jobject info)) + ResourceMark rm; + HandleMark hm; + Handle compResultHandle = JNIHandles::resolve(compResult); + nmethod* nm = NULL; + methodHandle method = getMethodFromHotSpotMethod(HotSpotCompilationResult::method(compResult)); + Handle installed_code_handle = JNIHandles::resolve(installed_code); + GraalEnv::CodeInstallResult result; + CodeInstaller installer(compResultHandle, method, result, nm, installed_code_handle); + + if (result != GraalEnv::ok) { + assert(nm == NULL, "should be"); + } else { + if (info != NULL) { + arrayOop codeCopy = oopFactory::new_byteArray(nm->code_size(), CHECK_0); + memcpy(codeCopy->base(T_BYTE), nm->code_begin(), nm->code_size()); + HotSpotCodeInfo::set_code(info, codeCopy); + HotSpotCodeInfo::set_start(info, (jlong) nm->code_begin()); + } + + if (!installed_code_handle.is_null()) { + assert(installed_code_handle->is_a(HotSpotInstalledCode::klass()), "wrong type"); + HotSpotInstalledCode::set_nmethod(installed_code_handle, (jlong) nm); + HotSpotInstalledCode::set_method(installed_code_handle, HotSpotCompilationResult::method(compResult)); + assert(nm == NULL || !installed_code_handle->is_scavengable() || nm->on_scavenge_root_list(), "nm should be scavengable if installed_code is scavengable"); + } + } + return result; +C2V_END + +C2V_VMENTRY(jobject, disassembleNative, (JNIEnv *jniEnv, jobject, jbyteArray code, jlong start_address)) + ResourceMark rm; + HandleMark hm; + + stringStream(st); + arrayOop code_oop = (arrayOop) JNIHandles::resolve(code); + int len = code_oop->length(); + address begin = (address) code_oop->base(T_BYTE); + address end = begin + len; + Disassembler::decode(begin, end, &st); + + Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL); + return JNIHandles::make_local(result()); +C2V_END + +C2V_VMENTRY(jobject, getStackTraceElement, (JNIEnv *env, jobject, jlong metaspace_method, int bci)) + ResourceMark rm; + HandleMark hm; + + methodHandle method = asMethod(metaspace_method); + oop element = java_lang_StackTraceElement::create(method, bci, CHECK_NULL); + return JNIHandles::make_local(element); +C2V_END + +C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jlong metaspace_method, jlong metaspace_nmethod, jobject args)) + ResourceMark rm; + HandleMark hm; + + assert(metaspace_method != 0, "just checking"); + methodHandle mh = asMethod(metaspace_method); + Symbol* signature = mh->signature(); + JavaCallArguments jca; + + JavaArgumentUnboxer jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static()); + JavaValue result(jap.get_ret_type()); + + nmethod* nm = (nmethod*) (address) metaspace_nmethod; + if (nm == NULL || !nm->is_alive()) { + THROW_0(vmSymbols::MethodInvalidatedException()); + } + + JavaCalls::call(&result, mh, nm, &jca, CHECK_NULL); + + if (jap.get_ret_type() == T_VOID) { + return NULL; + } else if (jap.get_ret_type() == T_OBJECT || jap.get_ret_type() == T_ARRAY) { + return JNIHandles::make_local((oop) result.get_jobject()); + } else { + oop o = java_lang_boxing_object::create(jap.get_ret_type(), (jvalue *) result.get_value_addr(), CHECK_NULL); + return JNIHandles::make_local(o); + } +C2V_END + +C2V_VMENTRY(jobject, executeCompiledMethod, (JNIEnv *env, jobject, jlong metaspace_method, jlong metaspace_nmethod, jobject arg1, jobject arg2, jobject arg3)) + ResourceMark rm; + HandleMark hm; + + methodHandle method = asMethod(metaspace_method); + assert(!method.is_null(), "just checking"); + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(JNIHandles::resolve(arg1)); + args.push_oop(JNIHandles::resolve(arg2)); + args.push_oop(JNIHandles::resolve(arg3)); + + nmethod* nm = (nmethod*) (address) metaspace_nmethod; + if (nm == NULL || !nm->is_alive()) { + THROW_0(vmSymbols::MethodInvalidatedException()); + } + + JavaCalls::call(&result, method, nm, &args, CHECK_NULL); + + return JNIHandles::make_local((oop) result.get_jobject()); +C2V_END + +C2V_VMENTRY(jint, getVtableEntryOffset, (JNIEnv *, jobject, jlong metaspace_method)) + + Method* method = asMethod(metaspace_method); + assert(!InstanceKlass::cast(method->method_holder())->is_interface(), "vtableEntryOffset cannot be called for interface methods"); + assert(InstanceKlass::cast(method->method_holder())->is_linked(), "vtableEntryOffset cannot be called is holder is not linked"); + + // get entry offset in words + int vtable_entry_offset = InstanceKlass::vtable_start_offset() + method->vtable_index() * vtableEntry::size(); + // convert to bytes + vtable_entry_offset = vtable_entry_offset * wordSize + vtableEntry::method_offset_in_bytes(); + + return vtable_entry_offset; +C2V_END + +C2V_VMENTRY(jobject, getDeoptedLeafGraphIds, (JNIEnv *, jobject)) + + // the contract for this method is as follows: + // returning null: no deopted leaf graphs + // returning array (size > 0): the ids of the deopted leaf graphs + // returning array (size == 0): there was an overflow, the compiler needs to clear its cache completely + + oop array = GraalCompiler::instance()->dump_deopted_leaf_graphs(CHECK_NULL); + return JNIHandles::make_local(array); +C2V_END + +C2V_VMENTRY(jobject, decodePC, (JNIEnv *, jobject, jlong pc)) + stringStream(st); + CodeBlob* blob = CodeCache::find_blob_unsafe((void*) pc); + if (blob == NULL) { + st.print("[unidentified pc]"); + } else { + st.print(blob->name()); + + nmethod* nm = blob->as_nmethod_or_null(); + if (nm != NULL && nm->method() != NULL) { + st.print(" %s.", nm->method()->method_holder()->external_name()); + nm->method()->name()->print_symbol_on(&st); + st.print(" @ %d", pc - (jlong) nm->entry_point()); + } + } + Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL); + return JNIHandles::make_local(result()); +C2V_END + + +#define CC (char*) /*cast a literal from (const char*)*/ +#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f)) + +#define RESOLVED_TYPE "Lcom/oracle/graal/api/meta/ResolvedJavaType;" +#define TYPE "Lcom/oracle/graal/api/meta/JavaType;" +#define METHOD "Lcom/oracle/graal/api/meta/JavaMethod;" +#define FIELD "Lcom/oracle/graal/api/meta/JavaField;" +#define SIGNATURE "Lcom/oracle/graal/api/meta/Signature;" +#define CONSTANT_POOL "Lcom/oracle/graal/api/meta/ConstantPool;" +#define CONSTANT "Lcom/oracle/graal/api/meta/Constant;" +#define KIND "Lcom/oracle/graal/api/meta/Kind;" +#define RUNTIME_CALL "Lcom/oracle/graal/api/code/RuntimeCall;" +#define EXCEPTION_HANDLERS "[Lcom/oracle/graal/api/meta/ExceptionHandler;" +#define REFLECT_METHOD "Ljava/lang/reflect/Method;" +#define REFLECT_CONSTRUCTOR "Ljava/lang/reflect/Constructor;" +#define REFLECT_FIELD "Ljava/lang/reflect/Field;" +#define STRING "Ljava/lang/String;" +#define OBJECT "Ljava/lang/Object;" +#define CLASS "Ljava/lang/Class;" +#define STACK_TRACE_ELEMENT "Ljava/lang/StackTraceElement;" +#define HS_RESOLVED_TYPE "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedObjectType;" +#define HS_RESOLVED_METHOD "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;" +#define HS_RESOLVED_FIELD "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaField;" +#define HS_COMP_RESULT "Lcom/oracle/graal/hotspot/HotSpotCompilationResult;" +#define HS_CONFIG "Lcom/oracle/graal/hotspot/HotSpotVMConfig;" +#define HS_METHOD "Lcom/oracle/graal/hotspot/meta/HotSpotMethod;" +#define HS_INSTALLED_CODE "Lcom/oracle/graal/hotspot/meta/HotSpotInstalledCode;" +#define HS_CODE_INFO "Lcom/oracle/graal/hotspot/meta/HotSpotCodeInfo;" +#define METHOD_DATA "Lcom/oracle/graal/hotspot/meta/HotSpotMethodData;" +#define METASPACE_METHOD "J" +#define METASPACE_METHOD_DATA "J" +#define NMETHOD "J" + +JNINativeMethod CompilerToVM_methods[] = { + {CC"initializeBytecode", CC"("METASPACE_METHOD"[B)[B", FN_PTR(initializeBytecode)}, + {CC"getSignature", CC"("METASPACE_METHOD")"STRING, FN_PTR(getSignature)}, + {CC"initializeExceptionHandlers", CC"("METASPACE_METHOD EXCEPTION_HANDLERS")"EXCEPTION_HANDLERS, FN_PTR(initializeExceptionHandlers)}, + {CC"hasBalancedMonitors", CC"("METASPACE_METHOD")Z", FN_PTR(hasBalancedMonitors)}, + {CC"getUniqueConcreteMethod", CC"("METASPACE_METHOD"["HS_RESOLVED_TYPE")"METASPACE_METHOD, FN_PTR(getUniqueConcreteMethod)}, + {CC"getStackTraceElement", CC"("METASPACE_METHOD"I)"STACK_TRACE_ELEMENT, FN_PTR(getStackTraceElement)}, + {CC"initializeMethod", CC"("METASPACE_METHOD HS_RESOLVED_METHOD")V", FN_PTR(initializeMethod)}, + {CC"initializeMethodData", CC"("METASPACE_METHOD_DATA METHOD_DATA")V", FN_PTR(initializeMethodData)}, + {CC"isMethodCompilable", CC"("METASPACE_METHOD")Z", FN_PTR(isMethodCompilable)}, + {CC"getInvocationCount", CC"("METASPACE_METHOD")I", FN_PTR(getInvocationCount)}, + {CC"getCompiledCodeSize", CC"("METASPACE_METHOD")I", FN_PTR(getCompiledCodeSize)}, + {CC"getVtableEntryOffset", CC"("METASPACE_METHOD")I", FN_PTR(getVtableEntryOffset)}, + {CC"lookupType", CC"("STRING HS_RESOLVED_TYPE"Z)"TYPE, FN_PTR(lookupType)}, + {CC"lookupConstantInPool", CC"("HS_RESOLVED_TYPE"I)"OBJECT, FN_PTR(lookupConstantInPool)}, + {CC"lookupMethodInPool", CC"("HS_RESOLVED_TYPE"IB)"METHOD, FN_PTR(lookupMethodInPool)}, + {CC"lookupTypeInPool", CC"("HS_RESOLVED_TYPE"I)"TYPE, FN_PTR(lookupTypeInPool)}, + {CC"lookupReferencedTypeInPool", CC"("HS_RESOLVED_TYPE"IB)V", FN_PTR(lookupReferencedTypeInPool)}, + {CC"lookupFieldInPool", CC"("HS_RESOLVED_TYPE"IB)"FIELD, FN_PTR(lookupFieldInPool)}, + {CC"resolveMethod", CC"("HS_RESOLVED_TYPE STRING STRING")"METHOD, FN_PTR(resolveMethod)}, + {CC"getInstanceFields", CC"("HS_RESOLVED_TYPE")["HS_RESOLVED_FIELD, FN_PTR(getInstanceFields)}, + {CC"isTypeInitialized", CC"("HS_RESOLVED_TYPE")Z", FN_PTR(isTypeInitialized)}, + {CC"initializeType", CC"("HS_RESOLVED_TYPE")V", FN_PTR(initializeType)}, + {CC"getMaxCallTargetOffset", CC"(J)J", FN_PTR(getMaxCallTargetOffset)}, + {CC"getResolvedType", CC"("CLASS")"RESOLVED_TYPE, FN_PTR(getResolvedType)}, + {CC"getMetaspaceMethod", CC"("REFLECT_METHOD"["HS_RESOLVED_TYPE")"METASPACE_METHOD, FN_PTR(getMetaspaceMethod)}, + {CC"getMetaspaceConstructor", CC"("REFLECT_CONSTRUCTOR"["HS_RESOLVED_TYPE")"METASPACE_METHOD, FN_PTR(getMetaspaceConstructor)}, + {CC"getJavaField", CC"("REFLECT_FIELD")"HS_RESOLVED_FIELD, FN_PTR(getJavaField)}, + {CC"initializeConfiguration", CC"("HS_CONFIG")V", FN_PTR(initializeConfiguration)}, + {CC"installCode0", CC"("HS_COMP_RESULT HS_INSTALLED_CODE HS_CODE_INFO")I", FN_PTR(installCode0)}, + {CC"disassembleNative", CC"([BJ)"STRING, FN_PTR(disassembleNative)}, + {CC"executeCompiledMethod", CC"("METASPACE_METHOD NMETHOD OBJECT OBJECT OBJECT")"OBJECT, FN_PTR(executeCompiledMethod)}, + {CC"executeCompiledMethodVarargs", CC"("METASPACE_METHOD NMETHOD "["OBJECT")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, + {CC"getDeoptedLeafGraphIds", CC"()[J", FN_PTR(getDeoptedLeafGraphIds)}, + {CC"decodePC", CC"(J)"STRING, FN_PTR(decodePC)}, +}; + +int CompilerToVM_methods_count() { + return sizeof(CompilerToVM_methods) / sizeof(JNINativeMethod); +} +
--- a/src/share/vm/graal/graalGlobals.hpp Mon Dec 10 22:19:07 2012 +0100 +++ b/src/share/vm/graal/graalGlobals.hpp Tue Dec 11 08:48:12 2012 +0100 @@ -51,7 +51,7 @@ "Bootstrap Graal before running Java main method") \ \ product(ccstr, GraalClassPath, NULL, \ - "Use the class path for Graal classes") \ + "Use this path, zip, or jar, to locate Graal-specific classes") \ \ product(intx, TraceGraal, 0, \ "Trace level for Graal") \ @@ -62,9 +62,6 @@ product_pd(intx, SafepointPollOffset, \ "Offset added to polling address (Intel only)") \ \ - develop(bool, UseFastNewInstance, true, \ - "Use fast inlined instance allocation") \ - \ develop(bool, UseFastNewTypeArray, true, \ "Use fast inlined type array allocation") \ \
--- a/src/share/vm/graal/graalRuntime.cpp Mon Dec 10 22:19:07 2012 +0100 +++ b/src/share/vm/graal/graalRuntime.cpp Tue Dec 11 08:48:12 2012 +0100 @@ -1,586 +1,606 @@ -/* - * 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. - */ - -#include "precompiled.hpp" -#include "runtime/interfaceSupport.hpp" -#include "prims/jvm.h" -#include "graal/graalRuntime.hpp" -#include "graal/graalVMToCompiler.hpp" -#include "asm/codeBuffer.hpp" -#include "runtime/biasedLocking.hpp" - -// Implementation of GraalStubAssembler - -GraalStubAssembler::GraalStubAssembler(CodeBuffer* code, const char * name, int stub_id) : MacroAssembler(code) { - _name = name; - _must_gc_arguments = false; - _frame_size = no_frame_size; - _num_rt_args = 0; - _stub_id = stub_id; -} - - -void GraalStubAssembler::set_info(const char* name, bool must_gc_arguments) { - _name = name; - _must_gc_arguments = must_gc_arguments; -} - - -void GraalStubAssembler::set_frame_size(int size) { - if (_frame_size == no_frame_size) { - _frame_size = size; - } - assert(_frame_size == size, "can't change the frame size"); -} - - -void GraalStubAssembler::set_num_rt_args(int args) { - if (_num_rt_args == 0) { - _num_rt_args = args; - } - assert(_num_rt_args == args, "can't change the number of args"); -} - -// Implementation of GraalRuntime - -CodeBlob* GraalRuntime::_blobs[GraalRuntime::number_of_ids]; -const char *GraalRuntime::_blob_names[] = { - GRAAL_STUBS(STUB_NAME, LAST_STUB_NAME) -}; - -// Simple helper to see if the caller of a runtime stub which -// entered the VM has been deoptimized - -static bool caller_is_deopted() { - JavaThread* thread = JavaThread::current(); - RegisterMap reg_map(thread, false); - frame runtime_frame = thread->last_frame(); - frame caller_frame = runtime_frame.sender(®_map); - assert(caller_frame.is_compiled_frame(), "must be compiled"); - return caller_frame.is_deoptimized_frame(); -} - -// Stress deoptimization -static void deopt_caller() { - if ( !caller_is_deopted()) { - JavaThread* thread = JavaThread::current(); - RegisterMap reg_map(thread, false); - frame runtime_frame = thread->last_frame(); - frame caller_frame = runtime_frame.sender(®_map); - Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint); - assert(caller_is_deopted(), "Must be deoptimized"); - } -} - -static bool setup_code_buffer(CodeBuffer* code) { - // Preinitialize the consts section to some large size: - int locs_buffer_size = 1 * (relocInfo::length_limit + sizeof(relocInfo)); - char* locs_buffer = NEW_RESOURCE_ARRAY(char, locs_buffer_size); - code->insts()->initialize_shared_locs((relocInfo*)locs_buffer, - locs_buffer_size / sizeof(relocInfo)); - - // Global stubs have neither constants nor local stubs - code->initialize_consts_size(0); - code->initialize_stubs_size(0); - - return true; -} - -void GraalRuntime::generate_blob_for(BufferBlob* buffer_blob, StubID id) { - assert(0 <= id && id < number_of_ids, "illegal stub id"); - ResourceMark rm; - // create code buffer for code storage - CodeBuffer code(buffer_blob); - - setup_code_buffer(&code); - - // create assembler for code generation - GraalStubAssembler* sasm = new GraalStubAssembler(&code, name_for(id), id); - // generate code for runtime stub - OopMapSet* oop_maps; - oop_maps = generate_code_for(id, sasm); - assert(oop_maps == NULL || sasm->frame_size() != no_frame_size, - "if stub has an oop map it must have a valid frame size"); - -#ifdef ASSERT - // Make sure that stubs that need oopmaps have them - switch (id) { - // These stubs don't need to have an oopmap - case graal_slow_subtype_check_id: -#if defined(SPARC) || defined(PPC) - case handle_exception_nofpu_id: // Unused on sparc -#endif -#ifdef GRAAL - case graal_verify_oop_id: - case graal_unwind_exception_call_id: - case graal_OSR_migration_end_id: - case graal_arithmetic_frem_id: - case graal_arithmetic_drem_id: - case graal_set_deopt_info_id: -#endif - break; - - // All other stubs should have oopmaps - default: - assert(oop_maps != NULL, "must have an oopmap"); - } -#endif - - // align so printing shows nop's instead of random code at the end (SimpleStubs are aligned) - sasm->align(BytesPerWord); - // make sure all code is in code buffer - sasm->flush(); - // create blob - distinguish a few special cases - CodeBlob* blob = RuntimeStub::new_runtime_stub(name_for(id), - &code, - CodeOffsets::frame_never_safe, - sasm->frame_size(), - oop_maps, - sasm->must_gc_arguments()); - // install blob - assert(blob != NULL, "blob must exist"); - _blobs[id] = blob; -} - - -void GraalRuntime::initialize(BufferBlob* blob) { - // generate stubs - for (int id = 0; id < number_of_ids; id++) generate_blob_for(blob, (StubID)id); - // printing -#ifndef PRODUCT - if (PrintSimpleStubs) { - ResourceMark rm; - for (int id = 0; id < number_of_ids; id++) { - _blobs[id]->print(); - if (_blobs[id]->oop_maps() != NULL) { - _blobs[id]->oop_maps()->print(); - } - } - } -#endif -} - - -CodeBlob* GraalRuntime::blob_for(StubID id) { - assert(0 <= id && id < number_of_ids, "illegal stub id"); - return _blobs[id]; -} - - -const char* GraalRuntime::name_for(StubID id) { - assert(0 <= id && id < number_of_ids, "illegal stub id"); - return _blob_names[id]; -} - -const char* GraalRuntime::name_for_address(address entry) { - for (int id = 0; id < number_of_ids; id++) { - if (entry == entry_for((StubID)id)) return name_for((StubID)id); - } - -#define FUNCTION_CASE(a, f) \ - if ((intptr_t)a == CAST_FROM_FN_PTR(intptr_t, f)) return #f - - FUNCTION_CASE(entry, os::javaTimeMillis); - FUNCTION_CASE(entry, os::javaTimeNanos); - FUNCTION_CASE(entry, SharedRuntime::OSR_migration_end); - FUNCTION_CASE(entry, SharedRuntime::d2f); - FUNCTION_CASE(entry, SharedRuntime::d2i); - FUNCTION_CASE(entry, SharedRuntime::d2l); - FUNCTION_CASE(entry, SharedRuntime::dcos); - FUNCTION_CASE(entry, SharedRuntime::dexp); - FUNCTION_CASE(entry, SharedRuntime::dlog); - FUNCTION_CASE(entry, SharedRuntime::dlog10); - FUNCTION_CASE(entry, SharedRuntime::dpow); - FUNCTION_CASE(entry, SharedRuntime::drem); - FUNCTION_CASE(entry, SharedRuntime::dsin); - FUNCTION_CASE(entry, SharedRuntime::dtan); - FUNCTION_CASE(entry, SharedRuntime::f2i); - FUNCTION_CASE(entry, SharedRuntime::f2l); - FUNCTION_CASE(entry, SharedRuntime::frem); - FUNCTION_CASE(entry, SharedRuntime::l2d); - FUNCTION_CASE(entry, SharedRuntime::l2f); - FUNCTION_CASE(entry, SharedRuntime::ldiv); - FUNCTION_CASE(entry, SharedRuntime::lmul); - FUNCTION_CASE(entry, SharedRuntime::lrem); - FUNCTION_CASE(entry, SharedRuntime::lrem); - FUNCTION_CASE(entry, SharedRuntime::dtrace_method_entry); - FUNCTION_CASE(entry, SharedRuntime::dtrace_method_exit); -#ifdef TRACE_HAVE_INTRINSICS - FUNCTION_CASE(entry, TRACE_TIME_METHOD); -#endif - -#undef FUNCTION_CASE -} - - -JRT_ENTRY(void, GraalRuntime::new_instance(JavaThread* thread, Klass* klass)) - assert(klass->is_klass(), "not a class"); - instanceKlassHandle h(thread, klass); - h->check_valid_for_instantiation(true, CHECK); - // make sure klass is initialized - h->initialize(CHECK); - // allocate instance and return via TLS - oop obj = h->allocate_instance(CHECK); - thread->set_vm_result(obj); -JRT_END - -JRT_ENTRY(void, GraalRuntime::new_array(JavaThread* thread, Klass* array_klass, jint length)) - // Note: no handle for klass needed since they are not used - // anymore after new_objArray() and no GC can happen before. - // (This may have to change if this code changes!) - assert(array_klass->is_klass(), "not a class"); - oop obj; - if (array_klass->oop_is_typeArray()) { - BasicType elt_type = TypeArrayKlass::cast(array_klass)->element_type(); - obj = oopFactory::new_typeArray(elt_type, length, CHECK); - } else { - Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass(); - obj = oopFactory::new_objArray(elem_klass, length, CHECK); - } - thread->set_vm_result(obj); - // This is pretty rare but this runtime patch is stressful to deoptimization - // if we deoptimize here so force a deopt to stress the path. - if (DeoptimizeALot) { - deopt_caller(); - } -JRT_END - - -JRT_ENTRY(void, GraalRuntime::new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims)) - assert(klass->is_klass(), "not a class"); - assert(rank >= 1, "rank must be nonzero"); - oop obj = ArrayKlass::cast(klass)->multi_allocate(rank, dims, CHECK); - thread->set_vm_result(obj); -JRT_END - -JRT_ENTRY(void, GraalRuntime::unimplemented_entry(JavaThread* thread, StubID id)) - tty->print_cr("GraalRuntime::entry_for(%d) returned unimplemented entry point", id); -JRT_END - -extern void vm_exit(int code); - -// Enter this method from compiled code handler below. This is where we transition -// to VM mode. This is done as a helper routine so that the method called directly -// from compiled code does not have to transition to VM. This allows the entry -// method to see if the nmethod that we have just looked up a handler for has -// been deoptimized while we were in the vm. This simplifies the assembly code -// cpu directories. -// -// We are entering here from exception stub (via the entry method below) -// If there is a compiled exception handler in this method, we will continue there; -// otherwise we will unwind the stack and continue at the caller of top frame method -// Note: we enter in Java using a special JRT wrapper. This wrapper allows us to -// control the area where we can allow a safepoint. After we exit the safepoint area we can -// check to see if the handler we are going to return is now in a nmethod that has -// been deoptimized. If that is the case we return the deopt blob -// unpack_with_exception entry instead. This makes life for the exception blob easier -// because making that same check and diverting is painful from assembly language. -JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* thread, oopDesc* ex, address pc, nmethod*& nm)) - // Reset method handle flag. - thread->set_is_method_handle_return(false); - - Handle exception(thread, ex); - nm = CodeCache::find_nmethod(pc); - assert(nm != NULL, "this is not an nmethod"); - // Adjust the pc as needed/ - if (nm->is_deopt_pc(pc)) { - RegisterMap map(thread, false); - frame exception_frame = thread->last_frame().sender(&map); - // if the frame isn't deopted then pc must not correspond to the caller of last_frame - assert(exception_frame.is_deoptimized_frame(), "must be deopted"); - pc = exception_frame.pc(); - } -#ifdef ASSERT - assert(exception.not_null(), "NULL exceptions should be handled by throw_exception"); - assert(exception->is_oop(), "just checking"); - // Check that exception is a subclass of Throwable, otherwise we have a VerifyError - if (!(exception->is_a(SystemDictionary::Throwable_klass()))) { - if (ExitVMOnVerifyError) vm_exit(-1); - ShouldNotReachHere(); - } -#endif - - // Check the stack guard pages and reenable them if necessary and there is - // enough space on the stack to do so. Use fast exceptions only if the guard - // pages are enabled. - bool guard_pages_enabled = thread->stack_yellow_zone_enabled(); - if (!guard_pages_enabled) guard_pages_enabled = thread->reguard_stack(); - - if (JvmtiExport::can_post_on_exceptions()) { - // To ensure correct notification of exception catches and throws - // we have to deoptimize here. If we attempted to notify the - // catches and throws during this exception lookup it's possible - // we could deoptimize on the way out of the VM and end back in - // the interpreter at the throw site. This would result in double - // notifications since the interpreter would also notify about - // these same catches and throws as it unwound the frame. - - RegisterMap reg_map(thread); - frame stub_frame = thread->last_frame(); - frame caller_frame = stub_frame.sender(®_map); - - // We don't really want to deoptimize the nmethod itself since we - // can actually continue in the exception handler ourselves but I - // don't see an easy way to have the desired effect. - Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint); - assert(caller_is_deopted(), "Must be deoptimized"); - - return SharedRuntime::deopt_blob()->unpack_with_exception_in_tls(); - } - - // ExceptionCache is used only for exceptions at call sites and not for implicit exceptions - if (guard_pages_enabled) { - address fast_continuation = nm->handler_for_exception_and_pc(exception, pc); - if (fast_continuation != NULL) { - // Set flag if return address is a method handle call site. - thread->set_is_method_handle_return(nm->is_method_handle_return(pc)); - return fast_continuation; - } - } - - // If the stack guard pages are enabled, check whether there is a handler in - // the current method. Otherwise (guard pages disabled), force an unwind and - // skip the exception cache update (i.e., just leave continuation==NULL). - address continuation = NULL; - if (guard_pages_enabled) { - - // New exception handling mechanism can support inlined methods - // with exception handlers since the mappings are from PC to PC - - // debugging support - // tracing - if (TraceExceptions) { - ttyLocker ttyl; - ResourceMark rm; - int offset = pc - nm->code_begin(); - tty->print_cr("Exception <%s> (0x%x) thrown in compiled method <%s> at PC " PTR_FORMAT " [" PTR_FORMAT "+%d] for thread 0x%x", - exception->print_value_string(), (address)exception(), nm->method()->print_value_string(), pc, nm->code_begin(), offset, thread); - } - // for AbortVMOnException flag - NOT_PRODUCT(Exceptions::debug_check_abort(exception)); - - // Clear out the exception oop and pc since looking up an - // exception handler can cause class loading, which might throw an - // exception and those fields are expected to be clear during - // normal bytecode execution. - thread->set_exception_oop(NULL); - thread->set_exception_pc(NULL); - - continuation = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, false, false); - // If an exception was thrown during exception dispatch, the exception oop may have changed - thread->set_exception_oop(exception()); - thread->set_exception_pc(pc); - - // the exception cache is used only by non-implicit exceptions - if (continuation != NULL && !SharedRuntime::deopt_blob()->contains(continuation)) { - nm->add_handler_for_exception_and_pc(exception, pc, continuation); - } - } - - thread->set_vm_result(exception()); - // Set flag if return address is a method handle call site. - thread->set_is_method_handle_return(nm->is_method_handle_return(pc)); - - if (TraceExceptions) { - ttyLocker ttyl; - ResourceMark rm; - tty->print_cr("Thread " PTR_FORMAT " continuing at PC " PTR_FORMAT " for exception thrown at PC " PTR_FORMAT, - thread, continuation, pc); - } - - return continuation; -JRT_END - -// Enter this method from compiled code only if there is a Java exception handler -// in the method handling the exception. -// We are entering here from exception stub. We don't do a normal VM transition here. -// We do it in a helper. This is so we can check to see if the nmethod we have just -// searched for an exception handler has been deoptimized in the meantime. -address GraalRuntime::exception_handler_for_pc(JavaThread* thread) { - oop exception = thread->exception_oop(); - address pc = thread->exception_pc(); - // Still in Java mode - DEBUG_ONLY(ResetNoHandleMark rnhm); - nmethod* nm = NULL; - address continuation = NULL; - { - // Enter VM mode by calling the helper - ResetNoHandleMark rnhm; - continuation = exception_handler_for_pc_helper(thread, exception, pc, nm); - } - // Back in JAVA, use no oops DON'T safepoint - - // Now check to see if the nmethod we were called from is now deoptimized. - // If so we must return to the deopt blob and deoptimize the nmethod - if (nm != NULL && caller_is_deopted()) { - continuation = SharedRuntime::deopt_blob()->unpack_with_exception_in_tls(); - } - - assert(continuation != NULL, "no handler found"); - return continuation; -} - -JRT_ENTRY(void, GraalRuntime::graal_create_null_exception(JavaThread* thread)) - thread->set_vm_result(Exceptions::new_exception(thread, vmSymbols::java_lang_NullPointerException(), NULL)()); -JRT_END - -JRT_ENTRY(void, GraalRuntime::graal_create_out_of_bounds_exception(JavaThread* thread, jint index)) - char message[jintAsStringSize]; - sprintf(message, "%d", index); - thread->set_vm_result(Exceptions::new_exception(thread, vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), message)()); -JRT_END - -JRT_ENTRY_NO_ASYNC(void, GraalRuntime::graal_monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock)) - if (TraceGraal >= 3) { - char type[O_BUFLEN]; - obj->klass()->name()->as_C_string(type, O_BUFLEN); - markOop mark = obj->mark(); - tty->print_cr("%s: entered locking slow case with obj=" INTPTR_FORMAT ", type=%s, mark=" INTPTR_FORMAT ", lock=" INTPTR_FORMAT, thread->name(), obj, type, mark, lock); - tty->flush(); - } -#ifdef ASSERT - if (PrintBiasedLockingStatistics) { - Atomic::inc(BiasedLocking::slow_path_entry_count_addr()); - } -#endif - Handle h_obj(thread, obj); - assert(h_obj()->is_oop(), "must be NULL or an object"); - if (UseBiasedLocking) { - // Retry fast entry if bias is revoked to avoid unnecessary inflation - ObjectSynchronizer::fast_enter(h_obj, lock, true, CHECK); - } else { - if (UseFastLocking) { - // When using fast locking, the compiled code has already tried the fast case - ObjectSynchronizer::slow_enter(h_obj, lock, THREAD); - } else { - ObjectSynchronizer::fast_enter(h_obj, lock, false, THREAD); - } - } - if (TraceGraal >= 3) { - tty->print_cr("%s: exiting locking slow with obj=" INTPTR_FORMAT, thread->name(), obj); - } -JRT_END - - -JRT_LEAF(void, GraalRuntime::graal_monitorexit(JavaThread* thread, oopDesc* obj, BasicLock* lock)) - assert(thread == JavaThread::current(), "threads must correspond"); - assert(thread->last_Java_sp(), "last_Java_sp must be set"); - // monitorexit is non-blocking (leaf routine) => no exceptions can be thrown - EXCEPTION_MARK; - -#ifdef DEBUG - if (!obj->is_oop()) { - ResetNoHandleMark rhm; - nmethod* method = thread->last_frame().cb()->as_nmethod_or_null(); - if (method != NULL) { - tty->print_cr("ERROR in monitorexit in method %s wrong obj " INTPTR_FORMAT, method->name(), obj); - } - thread->print_stack_on(tty); - assert(false, "invalid lock object pointer dected"); - } -#endif - - if (UseFastLocking) { - // When using fast locking, the compiled code has already tried the fast case - ObjectSynchronizer::slow_exit(obj, lock, THREAD); - } else { - ObjectSynchronizer::fast_exit(obj, lock, THREAD); - } - if (TraceGraal >= 3) { - char type[O_BUFLEN]; - obj->klass()->name()->as_C_string(type, O_BUFLEN); - tty->print_cr("%s: exited locking slow case with obj=" INTPTR_FORMAT ", type=%s, mark=" INTPTR_FORMAT ", lock=" INTPTR_FORMAT, thread->name(), obj, type, obj->mark(), lock); - tty->flush(); - } -JRT_END - -JRT_ENTRY(void, GraalRuntime::graal_log_object(JavaThread* thread, oop obj, jint flags)) - bool string = mask_bits_are_true(flags, LOG_OBJECT_STRING); - bool address = mask_bits_are_true(flags, LOG_OBJECT_ADDRESS); - bool newline = mask_bits_are_true(flags, LOG_OBJECT_NEWLINE); - if (!string) { - if (!address && obj->is_oop_or_null(true)) { - char buf[O_BUFLEN]; - tty->print("%s@%p", obj->klass()->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"); - char *buf = java_lang_String::as_utf8_string(obj); - tty->print(buf); - } - if (newline) { - tty->cr(); - } -JRT_END - -JRT_ENTRY(void, GraalRuntime::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); - 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); - } - report_vm_error(__FILE__, __LINE__, error_msg, detail_msg); -JRT_END - -JRT_ENTRY(void, GraalRuntime::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 - -JRT_ENTRY(void, GraalRuntime::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 - -// JVM_InitializeGraalRuntime -JVM_ENTRY(jobject, JVM_InitializeGraalRuntime(JNIEnv *env, jclass graalclass)) - return VMToCompiler::graalRuntimePermObject(); -JVM_END +/* + * 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. + */ + +#include "precompiled.hpp" +#include "runtime/interfaceSupport.hpp" +#include "prims/jvm.h" +#include "graal/graalRuntime.hpp" +#include "graal/graalVMToCompiler.hpp" +#include "asm/codeBuffer.hpp" +#include "runtime/biasedLocking.hpp" + +// Implementation of GraalStubAssembler + +GraalStubAssembler::GraalStubAssembler(CodeBuffer* code, const char * name, int stub_id) : MacroAssembler(code) { + _name = name; + _must_gc_arguments = false; + _frame_size = no_frame_size; + _num_rt_args = 0; + _stub_id = stub_id; +} + + +void GraalStubAssembler::set_info(const char* name, bool must_gc_arguments) { + _name = name; + _must_gc_arguments = must_gc_arguments; +} + + +void GraalStubAssembler::set_frame_size(int size) { + if (_frame_size == no_frame_size) { + _frame_size = size; + } + assert(_frame_size == size, "can't change the frame size"); +} + + +void GraalStubAssembler::set_num_rt_args(int args) { + if (_num_rt_args == 0) { + _num_rt_args = args; + } + assert(_num_rt_args == args, "can't change the number of args"); +} + +// Implementation of GraalRuntime + +CodeBlob* GraalRuntime::_blobs[GraalRuntime::number_of_ids]; +const char *GraalRuntime::_blob_names[] = { + GRAAL_STUBS(STUB_NAME, LAST_STUB_NAME) +}; + +// Simple helper to see if the caller of a runtime stub which +// entered the VM has been deoptimized + +static bool caller_is_deopted() { + JavaThread* thread = JavaThread::current(); + RegisterMap reg_map(thread, false); + frame runtime_frame = thread->last_frame(); + frame caller_frame = runtime_frame.sender(®_map); + assert(caller_frame.is_compiled_frame(), "must be compiled"); + return caller_frame.is_deoptimized_frame(); +} + +// Stress deoptimization +static void deopt_caller() { + if ( !caller_is_deopted()) { + JavaThread* thread = JavaThread::current(); + RegisterMap reg_map(thread, false); + frame runtime_frame = thread->last_frame(); + frame caller_frame = runtime_frame.sender(®_map); + Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint); + assert(caller_is_deopted(), "Must be deoptimized"); + } +} + +static bool setup_code_buffer(CodeBuffer* code) { + // Preinitialize the consts section to some large size: + int locs_buffer_size = 1 * (relocInfo::length_limit + sizeof(relocInfo)); + char* locs_buffer = NEW_RESOURCE_ARRAY(char, locs_buffer_size); + code->insts()->initialize_shared_locs((relocInfo*)locs_buffer, + locs_buffer_size / sizeof(relocInfo)); + + // Global stubs have neither constants nor local stubs + code->initialize_consts_size(0); + code->initialize_stubs_size(0); + + return true; +} + +void GraalRuntime::generate_blob_for(BufferBlob* buffer_blob, StubID id) { + assert(0 <= id && id < number_of_ids, "illegal stub id"); + ResourceMark rm; + // create code buffer for code storage + CodeBuffer code(buffer_blob); + + setup_code_buffer(&code); + + // create assembler for code generation + GraalStubAssembler* sasm = new GraalStubAssembler(&code, name_for(id), id); + // generate code for runtime stub + OopMapSet* oop_maps; + oop_maps = generate_code_for(id, sasm); + assert(oop_maps == NULL || sasm->frame_size() != no_frame_size, + "if stub has an oop map it must have a valid frame size"); + +#ifdef ASSERT + // Make sure that stubs that need oopmaps have them + switch (id) { + // These stubs don't need to have an oopmap + case graal_slow_subtype_check_id: +#if defined(SPARC) || defined(PPC) + case handle_exception_nofpu_id: // Unused on sparc +#endif +#ifdef GRAAL + case graal_verify_oop_id: + case graal_unwind_exception_call_id: + case graal_OSR_migration_end_id: + case graal_arithmetic_frem_id: + case graal_arithmetic_drem_id: + case graal_set_deopt_info_id: +#endif + break; + + // All other stubs should have oopmaps + default: + assert(oop_maps != NULL, "must have an oopmap"); + } +#endif + + // align so printing shows nop's instead of random code at the end (SimpleStubs are aligned) + sasm->align(BytesPerWord); + // make sure all code is in code buffer + sasm->flush(); + // create blob - distinguish a few special cases + CodeBlob* blob = RuntimeStub::new_runtime_stub(name_for(id), + &code, + CodeOffsets::frame_never_safe, + sasm->frame_size(), + oop_maps, + sasm->must_gc_arguments()); + // install blob + assert(blob != NULL, "blob must exist"); + _blobs[id] = blob; +} + + +void GraalRuntime::initialize(BufferBlob* blob) { + // generate stubs + for (int id = 0; id < number_of_ids; id++) generate_blob_for(blob, (StubID)id); + // printing +#ifndef PRODUCT + if (PrintSimpleStubs) { + ResourceMark rm; + for (int id = 0; id < number_of_ids; id++) { + _blobs[id]->print(); + if (_blobs[id]->oop_maps() != NULL) { + _blobs[id]->oop_maps()->print(); + } + } + } +#endif +} + + +CodeBlob* GraalRuntime::blob_for(StubID id) { + assert(0 <= id && id < number_of_ids, "illegal stub id"); + return _blobs[id]; +} + + +const char* GraalRuntime::name_for(StubID id) { + assert(0 <= id && id < number_of_ids, "illegal stub id"); + return _blob_names[id]; +} + +const char* GraalRuntime::name_for_address(address entry) { + for (int id = 0; id < number_of_ids; id++) { + if (entry == entry_for((StubID)id)) return name_for((StubID)id); + } + +#define FUNCTION_CASE(a, f) \ + if ((intptr_t)a == CAST_FROM_FN_PTR(intptr_t, f)) return #f + + FUNCTION_CASE(entry, os::javaTimeMillis); + FUNCTION_CASE(entry, os::javaTimeNanos); + FUNCTION_CASE(entry, SharedRuntime::OSR_migration_end); + FUNCTION_CASE(entry, SharedRuntime::d2f); + FUNCTION_CASE(entry, SharedRuntime::d2i); + FUNCTION_CASE(entry, SharedRuntime::d2l); + FUNCTION_CASE(entry, SharedRuntime::dcos); + FUNCTION_CASE(entry, SharedRuntime::dexp); + FUNCTION_CASE(entry, SharedRuntime::dlog); + FUNCTION_CASE(entry, SharedRuntime::dlog10); + FUNCTION_CASE(entry, SharedRuntime::dpow); + FUNCTION_CASE(entry, SharedRuntime::drem); + FUNCTION_CASE(entry, SharedRuntime::dsin); + FUNCTION_CASE(entry, SharedRuntime::dtan); + FUNCTION_CASE(entry, SharedRuntime::f2i); + FUNCTION_CASE(entry, SharedRuntime::f2l); + FUNCTION_CASE(entry, SharedRuntime::frem); + FUNCTION_CASE(entry, SharedRuntime::l2d); + FUNCTION_CASE(entry, SharedRuntime::l2f); + FUNCTION_CASE(entry, SharedRuntime::ldiv); + FUNCTION_CASE(entry, SharedRuntime::lmul); + FUNCTION_CASE(entry, SharedRuntime::lrem); + FUNCTION_CASE(entry, SharedRuntime::lrem); + FUNCTION_CASE(entry, SharedRuntime::dtrace_method_entry); + FUNCTION_CASE(entry, SharedRuntime::dtrace_method_exit); +#ifdef TRACE_HAVE_INTRINSICS + FUNCTION_CASE(entry, TRACE_TIME_METHOD); +#endif + + ShouldNotReachHere(); + return NULL; + +#undef FUNCTION_CASE +} + + +JRT_ENTRY(void, GraalRuntime::new_instance(JavaThread* thread, Klass* klass)) + assert(klass->is_klass(), "not a class"); + instanceKlassHandle h(thread, klass); + h->check_valid_for_instantiation(true, CHECK); + // make sure klass is initialized + h->initialize(CHECK); + // allocate instance and return via TLS + oop obj = h->allocate_instance(CHECK); + thread->set_vm_result(obj); +JRT_END + +JRT_ENTRY(void, GraalRuntime::new_array(JavaThread* thread, Klass* array_klass, jint length)) + // Note: no handle for klass needed since they are not used + // anymore after new_objArray() and no GC can happen before. + // (This may have to change if this code changes!) + assert(array_klass->is_klass(), "not a class"); + oop obj; + if (array_klass->oop_is_typeArray()) { + BasicType elt_type = TypeArrayKlass::cast(array_klass)->element_type(); + obj = oopFactory::new_typeArray(elt_type, length, CHECK); + } else { + Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass(); + obj = oopFactory::new_objArray(elem_klass, length, CHECK); + } + thread->set_vm_result(obj); + // This is pretty rare but this runtime patch is stressful to deoptimization + // if we deoptimize here so force a deopt to stress the path. + if (DeoptimizeALot) { + deopt_caller(); + } +JRT_END + + +JRT_ENTRY(void, GraalRuntime::new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims)) + assert(klass->is_klass(), "not a class"); + assert(rank >= 1, "rank must be nonzero"); + oop obj = ArrayKlass::cast(klass)->multi_allocate(rank, dims, CHECK); + thread->set_vm_result(obj); +JRT_END + +JRT_ENTRY(void, GraalRuntime::unimplemented_entry(JavaThread* thread, StubID id)) + tty->print_cr("GraalRuntime::entry_for(%d) returned unimplemented entry point", id); +JRT_END + +extern void vm_exit(int code); + +// Enter this method from compiled code handler below. This is where we transition +// to VM mode. This is done as a helper routine so that the method called directly +// from compiled code does not have to transition to VM. This allows the entry +// method to see if the nmethod that we have just looked up a handler for has +// been deoptimized while we were in the vm. This simplifies the assembly code +// cpu directories. +// +// We are entering here from exception stub (via the entry method below) +// If there is a compiled exception handler in this method, we will continue there; +// otherwise we will unwind the stack and continue at the caller of top frame method +// Note: we enter in Java using a special JRT wrapper. This wrapper allows us to +// control the area where we can allow a safepoint. After we exit the safepoint area we can +// check to see if the handler we are going to return is now in a nmethod that has +// been deoptimized. If that is the case we return the deopt blob +// unpack_with_exception entry instead. This makes life for the exception blob easier +// because making that same check and diverting is painful from assembly language. +JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* thread, oopDesc* ex, address pc, nmethod*& nm)) + // Reset method handle flag. + thread->set_is_method_handle_return(false); + + Handle exception(thread, ex); + nm = CodeCache::find_nmethod(pc); + assert(nm != NULL, "this is not an nmethod"); + // Adjust the pc as needed/ + if (nm->is_deopt_pc(pc)) { + RegisterMap map(thread, false); + frame exception_frame = thread->last_frame().sender(&map); + // if the frame isn't deopted then pc must not correspond to the caller of last_frame + assert(exception_frame.is_deoptimized_frame(), "must be deopted"); + pc = exception_frame.pc(); + } +#ifdef ASSERT + assert(exception.not_null(), "NULL exceptions should be handled by throw_exception"); + assert(exception->is_oop(), "just checking"); + // Check that exception is a subclass of Throwable, otherwise we have a VerifyError + if (!(exception->is_a(SystemDictionary::Throwable_klass()))) { + if (ExitVMOnVerifyError) vm_exit(-1); + ShouldNotReachHere(); + } +#endif + + // Check the stack guard pages and reenable them if necessary and there is + // enough space on the stack to do so. Use fast exceptions only if the guard + // pages are enabled. + bool guard_pages_enabled = thread->stack_yellow_zone_enabled(); + if (!guard_pages_enabled) guard_pages_enabled = thread->reguard_stack(); + + if (JvmtiExport::can_post_on_exceptions()) { + // To ensure correct notification of exception catches and throws + // we have to deoptimize here. If we attempted to notify the + // catches and throws during this exception lookup it's possible + // we could deoptimize on the way out of the VM and end back in + // the interpreter at the throw site. This would result in double + // notifications since the interpreter would also notify about + // these same catches and throws as it unwound the frame. + + RegisterMap reg_map(thread); + frame stub_frame = thread->last_frame(); + frame caller_frame = stub_frame.sender(®_map); + + // We don't really want to deoptimize the nmethod itself since we + // can actually continue in the exception handler ourselves but I + // don't see an easy way to have the desired effect. + Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint); + assert(caller_is_deopted(), "Must be deoptimized"); + + return SharedRuntime::deopt_blob()->unpack_with_exception_in_tls(); + } + + // ExceptionCache is used only for exceptions at call sites and not for implicit exceptions + if (guard_pages_enabled) { + address fast_continuation = nm->handler_for_exception_and_pc(exception, pc); + if (fast_continuation != NULL) { + // Set flag if return address is a method handle call site. + thread->set_is_method_handle_return(nm->is_method_handle_return(pc)); + return fast_continuation; + } + } + + // If the stack guard pages are enabled, check whether there is a handler in + // the current method. Otherwise (guard pages disabled), force an unwind and + // skip the exception cache update (i.e., just leave continuation==NULL). + address continuation = NULL; + if (guard_pages_enabled) { + + // New exception handling mechanism can support inlined methods + // with exception handlers since the mappings are from PC to PC + + // debugging support + // tracing + if (TraceExceptions) { + ttyLocker ttyl; + ResourceMark rm; + int offset = pc - nm->code_begin(); + tty->print_cr("Exception <%s> (0x%x) thrown in compiled method <%s> at PC " PTR_FORMAT " [" PTR_FORMAT "+%d] for thread 0x%x", + exception->print_value_string(), (address)exception(), nm->method()->print_value_string(), pc, nm->code_begin(), offset, thread); + } + // for AbortVMOnException flag + NOT_PRODUCT(Exceptions::debug_check_abort(exception)); + + // Clear out the exception oop and pc since looking up an + // exception handler can cause class loading, which might throw an + // exception and those fields are expected to be clear during + // normal bytecode execution. + thread->set_exception_oop(NULL); + thread->set_exception_pc(NULL); + + continuation = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, false, false); + // If an exception was thrown during exception dispatch, the exception oop may have changed + thread->set_exception_oop(exception()); + thread->set_exception_pc(pc); + + // the exception cache is used only by non-implicit exceptions + if (continuation != NULL && !SharedRuntime::deopt_blob()->contains(continuation)) { + nm->add_handler_for_exception_and_pc(exception, pc, continuation); + } + } + + thread->set_vm_result(exception()); + // Set flag if return address is a method handle call site. + thread->set_is_method_handle_return(nm->is_method_handle_return(pc)); + + if (TraceExceptions) { + ttyLocker ttyl; + ResourceMark rm; + tty->print_cr("Thread " PTR_FORMAT " continuing at PC " PTR_FORMAT " for exception thrown at PC " PTR_FORMAT, + thread, continuation, pc); + } + + return continuation; +JRT_END + +// Enter this method from compiled code only if there is a Java exception handler +// in the method handling the exception. +// We are entering here from exception stub. We don't do a normal VM transition here. +// We do it in a helper. This is so we can check to see if the nmethod we have just +// searched for an exception handler has been deoptimized in the meantime. +address GraalRuntime::exception_handler_for_pc(JavaThread* thread) { + oop exception = thread->exception_oop(); + address pc = thread->exception_pc(); + // Still in Java mode + DEBUG_ONLY(ResetNoHandleMark rnhm); + nmethod* nm = NULL; + address continuation = NULL; + { + // Enter VM mode by calling the helper + ResetNoHandleMark rnhm; + continuation = exception_handler_for_pc_helper(thread, exception, pc, nm); + } + // Back in JAVA, use no oops DON'T safepoint + + // Now check to see if the nmethod we were called from is now deoptimized. + // If so we must return to the deopt blob and deoptimize the nmethod + if (nm != NULL && caller_is_deopted()) { + continuation = SharedRuntime::deopt_blob()->unpack_with_exception_in_tls(); + } + + assert(continuation != NULL, "no handler found"); + return continuation; +} + +JRT_ENTRY(void, GraalRuntime::graal_create_null_exception(JavaThread* thread)) + thread->set_vm_result(Exceptions::new_exception(thread, vmSymbols::java_lang_NullPointerException(), NULL)()); +JRT_END + +JRT_ENTRY(void, GraalRuntime::graal_create_out_of_bounds_exception(JavaThread* thread, jint index)) + char message[jintAsStringSize]; + sprintf(message, "%d", index); + thread->set_vm_result(Exceptions::new_exception(thread, vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), message)()); +JRT_END + +JRT_ENTRY_NO_ASYNC(void, GraalRuntime::graal_monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock)) + if (TraceGraal >= 3) { + char type[O_BUFLEN]; + obj->klass()->name()->as_C_string(type, O_BUFLEN); + markOop mark = obj->mark(); + tty->print_cr("%s: entered locking slow case with obj=" INTPTR_FORMAT ", type=%s, mark=" INTPTR_FORMAT ", lock=" INTPTR_FORMAT, thread->name(), obj, type, mark, lock); + tty->flush(); + } +#ifdef ASSERT + if (PrintBiasedLockingStatistics) { + Atomic::inc(BiasedLocking::slow_path_entry_count_addr()); + } +#endif + Handle h_obj(thread, obj); + assert(h_obj()->is_oop(), "must be NULL or an object"); + if (UseBiasedLocking) { + // Retry fast entry if bias is revoked to avoid unnecessary inflation + ObjectSynchronizer::fast_enter(h_obj, lock, true, CHECK); + } else { + if (UseFastLocking) { + // When using fast locking, the compiled code has already tried the fast case + ObjectSynchronizer::slow_enter(h_obj, lock, THREAD); + } else { + ObjectSynchronizer::fast_enter(h_obj, lock, false, THREAD); + } + } + if (TraceGraal >= 3) { + tty->print_cr("%s: exiting locking slow with obj=" INTPTR_FORMAT, thread->name(), obj); + } +JRT_END + + +JRT_LEAF(void, GraalRuntime::graal_monitorexit(JavaThread* thread, oopDesc* obj, BasicLock* lock)) + assert(thread == JavaThread::current(), "threads must correspond"); + assert(thread->last_Java_sp(), "last_Java_sp must be set"); + // monitorexit is non-blocking (leaf routine) => no exceptions can be thrown + EXCEPTION_MARK; + +#ifdef DEBUG + if (!obj->is_oop()) { + ResetNoHandleMark rhm; + nmethod* method = thread->last_frame().cb()->as_nmethod_or_null(); + if (method != NULL) { + tty->print_cr("ERROR in monitorexit in method %s wrong obj " INTPTR_FORMAT, method->name(), obj); + } + thread->print_stack_on(tty); + assert(false, "invalid lock object pointer dected"); + } +#endif + + if (UseFastLocking) { + // When using fast locking, the compiled code has already tried the fast case + ObjectSynchronizer::slow_exit(obj, lock, THREAD); + } else { + ObjectSynchronizer::fast_exit(obj, lock, THREAD); + } + if (TraceGraal >= 3) { + char type[O_BUFLEN]; + obj->klass()->name()->as_C_string(type, O_BUFLEN); + tty->print_cr("%s: exited locking slow case with obj=" INTPTR_FORMAT ", type=%s, mark=" INTPTR_FORMAT ", lock=" INTPTR_FORMAT, thread->name(), obj, type, obj->mark(), lock); + tty->flush(); + } +JRT_END + +JRT_ENTRY(void, GraalRuntime::graal_log_object(JavaThread* thread, oop obj, jint flags)) + bool string = mask_bits_are_true(flags, LOG_OBJECT_STRING); + bool address = mask_bits_are_true(flags, LOG_OBJECT_ADDRESS); + bool newline = mask_bits_are_true(flags, LOG_OBJECT_NEWLINE); + if (!string) { + if (!address && obj->is_oop_or_null(true)) { + char buf[O_BUFLEN]; + tty->print("%s@%p", obj->klass()->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"); + char *buf = java_lang_String::as_utf8_string(obj); + tty->print(buf); + } + if (newline) { + tty->cr(); + } +JRT_END + +JRT_ENTRY(void, GraalRuntime::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); + 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); + } + report_vm_error(__FILE__, __LINE__, error_msg, detail_msg); +JRT_END + +JRT_ENTRY(void, GraalRuntime::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 + +JRT_ENTRY(void, GraalRuntime::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 + +JRT_ENTRY(jint, GraalRuntime::graal_identity_hash_code(JavaThread* thread, oop obj)) + return (jint) obj->identity_hash(); +JRT_END + +JRT_ENTRY(jboolean, GraalRuntime::graal_thread_is_interrupted(JavaThread* thread, oop receiver, jboolean clear_interrupted)) + // TEMP: + tty->print_cr("ThreadIsInterruptedSlowCase"); + + // Ensure that the C++ Thread and OSThread structures aren't freed before we operate + Handle receiverHandle(thread, receiver); + JRT_BLOCK + MutexLockerEx ml(thread->threadObj() == receiver ? NULL : Threads_lock); + JavaThread* receiverThread = java_lang_Thread::thread(receiverHandle()); + return (jint) Thread::is_interrupted(receiverThread, clear_interrupted != 0); + JRT_BLOCK_END +JRT_END + +// JVM_InitializeGraalRuntime +JVM_ENTRY(jobject, JVM_InitializeGraalRuntime(JNIEnv *env, jclass graalclass)) + return VMToCompiler::graalRuntimePermObject(); +JVM_END
--- a/src/share/vm/graal/graalRuntime.hpp Mon Dec 10 22:19:07 2012 +0100 +++ b/src/share/vm/graal/graalRuntime.hpp Tue Dec 11 08:48:12 2012 +0100 @@ -98,6 +98,8 @@ stub(graal_log_object) \ stub(graal_log_printf) \ stub(graal_log_primitive) \ + stub(graal_identity_hash_code) \ + stub(graal_thread_is_interrupted) \ last_entry(number_of_ids) #define DECLARE_STUB_ID(x) x ## _id , @@ -142,6 +144,9 @@ 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); + + static jint graal_identity_hash_code(JavaThread* thread, oopDesc* objd); + static jboolean graal_thread_is_interrupted(JavaThread* thread, oopDesc* obj, jboolean clear_interrupte); // Note: Must be kept in sync with constants in com.oracle.graal.snippets.Log enum {
--- a/src/share/vm/runtime/globals.hpp Mon Dec 10 22:19:07 2012 +0100 +++ b/src/share/vm/runtime/globals.hpp Tue Dec 11 08:48:12 2012 +0100 @@ -2924,7 +2924,7 @@ "if non-zero, start verifying C heap after Nth call to " \ "malloc/realloc/free") \ \ - product(intx, TypeProfileWidth, 2, \ + product_pd(intx, TypeProfileWidth, \ "number of receiver types to record in call/cast profile") \ \ develop(intx, BciProfileWidth, 2, \
--- a/src/share/vm/runtime/vframeArray.cpp Mon Dec 10 22:19:07 2012 +0100 +++ b/src/share/vm/runtime/vframeArray.cpp Tue Dec 11 08:48:12 2012 +0100 @@ -311,6 +311,10 @@ } } + if (PrintDeoptimizationDetails) { + tty->print_cr("Expressions size: %d", expressions()->size()); + } + // Unpack expression stack // If this is an intermediate frame (i.e. not top frame) then this // only unpacks the part of the expression stack not used by callee @@ -323,9 +327,25 @@ switch(value->type()) { case T_INT: *addr = value->get_int(); +#ifndef PRODUCT + if (PrintDeoptimizationDetails) { + tty->print_cr("Reconstructed expression %d (INT): %d", i, (int)(*addr)); + } +#endif break; case T_OBJECT: *addr = value->get_int(T_OBJECT); +#ifndef PRODUCT + if (PrintDeoptimizationDetails) { + tty->print("Reconstructed expression %d (OBJECT): ", i); + oop o = (oop)(*addr); + if (o == NULL) { + tty->print_cr("NULL"); + } else { + tty->print_cr(err_msg("%s", o->klass()->name()->as_C_string())); + } + } +#endif break; case T_CONFLICT: // A dead stack slot. Initialize to null in case it is an oop. @@ -344,9 +364,25 @@ switch(value->type()) { case T_INT: *addr = value->get_int(); +#ifndef PRODUCT + if (PrintDeoptimizationDetails) { + tty->print_cr("Reconstructed local %d (INT): %d", i, (int)(*addr)); + } +#endif break; case T_OBJECT: *addr = value->get_int(T_OBJECT); +#ifndef PRODUCT + if (PrintDeoptimizationDetails) { + tty->print("Reconstructed local %d (OBJECT): ", i); + oop o = (oop)(*addr); + if (o == NULL) { + tty->print_cr("NULL"); + } else { + tty->print_cr(err_msg("%s", o->klass()->name()->as_C_string())); + } + } +#endif break; case T_CONFLICT: // A dead location. If it is an oop then we need a NULL to prevent GC from following it @@ -388,18 +424,13 @@ } #ifndef PRODUCT - if (TraceDeoptimization && Verbose) { + if (PrintDeoptimizationDetails) { ttyLocker ttyl; tty->print_cr("[%d Interpreted Frame]", ++unpack_counter); iframe()->print_on(tty); RegisterMap map(thread); vframe* f = vframe::new_vframe(iframe(), &map, thread); f->print(); - - tty->print_cr("locals size %d", locals()->size()); - tty->print_cr("expression size %d", expressions()->size()); - - method()->print_value(); tty->cr(); // method()->print_codes(); } else if (TraceDeoptimization) {