# HG changeset patch # User Christian Haeubl # Date 1355210880 -3600 # Node ID fcae6d960acd5c2360eac6d0c4eac6a94477f20e # Parent 69b3b2695feac7c9c77f65ca50566f5254ff3c20 added more compiler intrinsics diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java Thu Dec 06 13:53:36 2012 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java Tue Dec 11 08:28:00 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 diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Thu Dec 06 13:53:36 2012 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Tue Dec 11 08:28:00 2012 +0100 @@ -32,6 +32,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.*; @@ -44,7 +46,6 @@ public AMD64HotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime graalRuntime) { super(config, graalRuntime); - HotSpotVMConfig c = config; Kind word = graalRuntime.getTarget().wordKind; addRuntimeCall(DEOPTIMIZE, config.deoptimizeStub, @@ -78,48 +79,58 @@ /* arg0: object */ arg(0, Kind.Object), /* arg1: lock */ arg(1, word)); - addRuntimeCall(MONITOREXIT, c.monitorExitStub, + addRuntimeCall(MONITOREXIT, config.monitorExitStub, /* temps */ new Register[] {rax, rbx}, /* ret */ ret(Kind.Void), /* arg0: object */ arg(0, Kind.Object), /* arg1: lock */ arg(1, word)); - addRuntimeCall(NEW_OBJECT_ARRAY, c.newObjectArrayStub, + addRuntimeCall(NEW_OBJECT_ARRAY, config.newObjectArrayStub, /* temps */ new Register[] {rcx, rdi, rsi}, /* ret */ rax.asValue(Kind.Object), /* arg0: hub */ rdx.asValue(word), /* arg1: length */ rbx.asValue(Kind.Int)); - addRuntimeCall(NEW_TYPE_ARRAY, c.newTypeArrayStub, + addRuntimeCall(NEW_TYPE_ARRAY, config.newTypeArrayStub, /* temps */ new Register[] {rcx, rdi, rsi}, /* ret */ rax.asValue(Kind.Object), /* arg0: hub */ rdx.asValue(word), /* arg1: length */ rbx.asValue(Kind.Int)); - addRuntimeCall(NEW_INSTANCE, c.newInstanceStub, + addRuntimeCall(NEW_INSTANCE, config.newInstanceStub, /* temps */ null, /* 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 diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Thu Dec 06 13:53:36 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Tue Dec 11 08:28:00 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 getCapability(Class 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(); } diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Thu Dec 06 13:53:36 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Dec 11 08:28:00 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; @@ -266,6 +306,8 @@ public long logPrimitiveStub; public long logObjectStub; public long logPrintfStub; + public long threadIsInterruptedStub; + public long identityHashCodeStub; public void check() { assert vmPageSize >= 16; diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Thu Dec 06 13:53:36 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Tue Dec 11 08:28:00 2012 +0100 @@ -573,7 +573,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; diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Thu Dec 06 13:53:36 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Tue Dec 11 08:28:00 2012 +0100 @@ -174,7 +174,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; diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Thu Dec 06 13:53:36 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Dec 11 08:28:00 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.*; @@ -70,7 +69,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; @@ -267,9 +266,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); @@ -664,54 +678,6 @@ @Override public StructuredGraph intrinsicGraph(ResolvedJavaMethod caller, int bci, ResolvedJavaMethod method, List 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; } diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentThread.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentThread.java Thu Dec 06 13:53:36 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentThread.java Tue Dec 11 08:28:00 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); } diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/IdentityHashCodeStubCall.java --- /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:28:00 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); +} diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java --- /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:28:00 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); +} diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSnippets.java --- /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:28:00 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; + } +} diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Thu Dec 06 13:53:36 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Tue Dec 11 08:28:00 2012 +0100 @@ -56,6 +56,21 @@ } @Fold + static int threadObjectOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().threadObjectOffset; + } + + @Fold + static int osThreadOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().osThreadOffset; + } + + @Fold + static int osThreadInterruptedOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().osThreadInterruptedOffset; + } + + @Fold static Kind wordKind() { return HotSpotGraalRuntime.getInstance().getTarget().wordKind; } @@ -86,6 +101,46 @@ } @Fold + static int klassOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().klassOffset; + } + + @Fold + static int klassModifierFlagsOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().klassModifierFlagsOffset; + } + + @Fold + static int klassAccessFlagsOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().klassAccessFlagsOffset; + } + + @Fold + static int klassLayoutHelperOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().klassLayoutHelperOffset; + } + + @Fold + static int arrayKlassLayoutHelperIdentifier() { + return HotSpotGraalRuntime.getInstance().getConfig().arrayKlassLayoutHelperIdentifier; + } + + @Fold + static int arrayKlassComponentMirrorOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().arrayKlassComponentMirrorOffset; + } + + @Fold + static int klassSuperKlassOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().klassSuperKlassOffset; + } + + @Fold + static int classMirrorOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().classMirrorOffset; + } + + @Fold static int markOffset() { return HotSpotGraalRuntime.getInstance().getConfig().markOffset; } @@ -198,6 +253,16 @@ return HotSpotGraalRuntime.getInstance().getConfig().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. */ @@ -235,6 +300,10 @@ return loadWordFromWordIntrinsic(address, 0, offset, wordKind()); } + static Object loadObjectFromWord(Word address, int offset) { + return UnsafeLoadNode.load(address, 0, offset, Kind.Object); + } + static Word loadWordFromObject(Object object, int offset) { return loadWordFromObjectIntrinsic(object, 0, offset, wordKind()); } diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSnippets.java --- /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:28:00 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); + } +} diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java Thu Dec 06 13:53:36 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java Tue Dec 11 08:28:00 2012 +0100 @@ -22,10 +22,13 @@ */ package com.oracle.graal.hotspot.snippets; +import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*; + import com.oracle.graal.api.code.RuntimeCall.Descriptor; 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); - } diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSnippets.java --- /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:28:00 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); + } +} diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Thu Dec 06 13:53:36 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Tue Dec 11 08:28:00 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.*; diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Thu Dec 06 13:53:36 2012 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Tue Dec 11 08:28:00 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. */ diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/IntrinsificationTest.java --- /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:28:00 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() { + @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 { + } +} diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceMethodSubstitution.java --- /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:28:00 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 ""; +} diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Thu Dec 06 13:53:36 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Tue Dec 11 08:28:00 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"); } diff -r 69b3b2695fea -r fcae6d960acd graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetProvider.java --- /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:28:00 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); +} diff -r 69b3b2695fea -r fcae6d960acd src/cpu/x86/vm/graalRuntime_x86.cpp --- a/src/cpu/x86/vm/graalRuntime_x86.cpp Thu Dec 06 13:53:36 2012 +0100 +++ b/src/cpu/x86/vm/graalRuntime_x86.cpp Tue Dec 11 08:28:00 2012 +0100 @@ -1179,6 +1179,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); diff -r 69b3b2695fea -r fcae6d960acd src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Thu Dec 06 13:53:36 2012 +0100 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Tue Dec 11 08:28:00 2012 +0100 @@ -630,6 +630,8 @@ set_int(env, config, "threadTlabTopOffset", in_bytes(JavaThread::tlab_top_offset())); set_int(env, config, "threadTlabEndOffset", in_bytes(JavaThread::tlab_end_offset())); set_int(env, config, "threadObjectOffset", in_bytes(JavaThread::threadObj_offset())); + set_int(env, config, "osThreadOffset", in_bytes(JavaThread::osthread_offset())); + set_int(env, config, "osThreadInterruptedOffset", in_bytes(OSThread::interrupted_offset())); set_int(env, config, "unlockedMask", (int) markOopDesc::unlocked_value); set_int(env, config, "biasedLockMaskInPlace", (int) markOopDesc::biased_lock_mask_in_place); set_int(env, config, "ageMaskInPlace", (int) markOopDesc::age_mask_in_place); @@ -648,6 +650,8 @@ set_int(env, config, "runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes); set_int(env, config, "klassModifierFlagsOffset", in_bytes(Klass::modifier_flags_offset())); set_int(env, config, "klassAccessFlagsOffset", in_bytes(Klass::access_flags_offset())); + set_int(env, config, "klassLayoutHelperOffset", in_bytes(Klass::layout_helper_offset())); + set_int(env, config, "klassSuperKlassOffset", in_bytes(Klass::super_offset())); set_int(env, config, "klassOffset", java_lang_Class::klass_offset_in_bytes()); set_int(env, config, "graalMirrorInClassOffset", java_lang_Class::graal_mirror_offset_in_bytes()); set_int(env, config, "methodDataOffset", in_bytes(Method::method_data_offset())); @@ -655,6 +659,12 @@ set_int(env, config, "methodCompiledEntryOffset", in_bytes(Method::from_compiled_offset())); set_int(env, config, "basicLockSize", sizeof(BasicLock)); set_int(env, config, "basicLockDisplacedHeaderOffset", BasicLock::displaced_header_offset_in_bytes()); + set_int(env, config, "uninitializedIdentityHashCodeValue", markOopDesc::no_hash); + set_int(env, config, "identityHashCodeShift", markOopDesc::hash_shift); + + set_int(env, config, "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(env, config, "arrayKlassComponentMirrorOffset", in_bytes(ArrayKlass::component_mirror_offset())); set_int(env, config, "metaspaceArrayLengthOffset", Array::length_offset_in_bytes()); set_int(env, config, "metaspaceArrayBaseOffset", Array::base_offset_in_bytes()); @@ -699,6 +709,8 @@ set_long(env, config, "logPrimitiveStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_primitive_id))); set_long(env, config, "logObjectStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_object_id))); set_long(env, config, "logPrintfStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_printf_id))); + set_long(env, config, "identityHashCodeStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_identity_hash_code_id))); + set_long(env, config, "threadIsInterruptedStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_thread_is_interrupted_id))); BarrierSet* bs = Universe::heap()->barrier_set(); diff -r 69b3b2695fea -r fcae6d960acd src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Thu Dec 06 13:53:36 2012 +0100 +++ b/src/share/vm/graal/graalRuntime.cpp Tue Dec 11 08:28:00 2012 +0100 @@ -595,6 +595,23 @@ } 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(); diff -r 69b3b2695fea -r fcae6d960acd src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Thu Dec 06 13:53:36 2012 +0100 +++ b/src/share/vm/graal/graalRuntime.hpp Tue Dec 11 08:28:00 2012 +0100 @@ -99,6 +99,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 , @@ -144,6 +146,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 {