# HG changeset patch # User Thomas Wuerthinger # Date 1373310761 -7200 # Node ID 2abf1c8b062a8b59d5f06f2d763172afdaffdfdd # Parent d71c56c679213541c4cad00003f71af025996050# Parent 678cdd287d60a138fb2c515f72585b43a68c3b72 Merge. diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Mon Jul 08 21:12:41 2013 +0200 @@ -241,6 +241,13 @@ } @Override + protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { + AllocatableValue targetAddress = AMD64.rax.asValue(); + emitMove(targetAddress, operand(callTarget.computedAddress())); + append(new AMD64Call.IndirectCallOp(callTarget.target(), result, parameters, temps, targetAddress, callState)); + } + + @Override public void emitOverflowCheckBranch(LabelRef destination, boolean negated) { append(new BranchOp(negated ? ConditionFlag.NoOverflow : ConditionFlag.Overflow, destination)); } diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Mon Jul 08 21:12:41 2013 +0200 @@ -38,6 +38,7 @@ import com.oracle.graal.compiler.gen.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.stubs.*; @@ -341,11 +342,15 @@ @Override protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - AllocatableValue metaspaceMethod = AMD64.rbx.asValue(); - emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod())); - AllocatableValue targetAddress = AMD64.rax.asValue(); - emitMove(targetAddress, operand(callTarget.computedAddress())); - append(new AMD64IndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState)); + if (callTarget instanceof HotSpotIndirectCallTargetNode) { + AllocatableValue metaspaceMethod = AMD64.rbx.asValue(); + emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod())); + AllocatableValue targetAddress = AMD64.rax.asValue(); + emitMove(targetAddress, operand(callTarget.computedAddress())); + append(new AMD64IndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState)); + } else { + super.emitIndirectCall(callTarget, result, parameters, temps, callState); + } } @Override diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Mon Jul 08 21:12:41 2013 +0200 @@ -184,5 +184,5 @@ * stub that does the necessary argument shuffling and a tail call via an indirect jump to the * verified entry point of the given native method. */ - private static native Object executeCompiledMethodIntrinsic(Object arg1, Object arg2, Object arg3, HotSpotInstalledCode hotspotInstalledCode); + public static native Object executeCompiledMethodIntrinsic(Object arg1, Object arg2, Object arg3, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; } diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java Mon Jul 08 21:12:41 2013 +0200 @@ -29,6 +29,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.bridge.*; /** * Implementation of {@link InstalledCode} for code installed as an nmethod. The nmethod stores a @@ -100,7 +101,11 @@ assert method.getSignature().getParameterKind(0) == Kind.Object; assert method.getSignature().getParameterKind(1) == Kind.Object; assert !Modifier.isStatic(method.getModifiers()) || method.getSignature().getParameterKind(2) == Kind.Object; - return graalRuntime().getCompilerToVM().executeCompiledMethod(arg1, arg2, arg3, this); + return executeHelper(arg1, arg2, arg3, this); + } + + private static Object executeHelper(Object arg1, Object arg2, Object arg3, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException { + return CompilerToVMImpl.executeCompiledMethodIntrinsic(arg1, arg2, arg3, hotspotInstalledCode); } private boolean checkArgs(Object... args) { diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotNmethodExecuteNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotNmethodExecuteNode.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotNmethodExecuteNode.java Mon Jul 08 21:12:41 2013 +0200 @@ -22,95 +22,45 @@ */ package com.oracle.graal.hotspot.nodes; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; - -import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.phases.common.*; - -public class HotSpotNmethodExecuteNode extends AbstractCallNode implements Lowerable, MemoryCheckpoint.Single { - - @Input private ValueNode code; - private final Class[] signature; +import com.oracle.graal.replacements.nodes.*; - public HotSpotNmethodExecuteNode(Kind kind, Class[] signature, ValueNode code, ValueNode arg1, ValueNode arg2, ValueNode arg3) { - super(StampFactory.forKind(kind), new ValueNode[]{arg1, arg2, arg3}); - this.code = code; - this.signature = signature; - } +public class HotSpotNmethodExecuteNode extends MacroNode implements Lowerable { - @Override - public LocationIdentity getLocationIdentity() { - return LocationIdentity.ANY_LOCATION; + public HotSpotNmethodExecuteNode(Invoke invoke) { + super(invoke); } @Override public void lower(LoweringTool tool, LoweringType loweringType) { - if (code.isConstant() && code.asConstant().asObject() instanceof HotSpotNmethod) { - HotSpotNmethod nmethod = (HotSpotNmethod) code.asConstant().asObject(); - InvokeNode invoke = replaceWithInvoke(tool.getRuntime()); - StructuredGraph graph = (StructuredGraph) nmethod.getGraph(); - if (graph != null) { - InliningUtil.inline(invoke, graph, false); + if (loweringType == LoweringType.AFTER_GUARDS) { + + ValueNode hotspotNmethod = arguments.get(3); + + ReadNode readNode = graph().add(new ReadNode(hotspotNmethod, 16, LocationIdentity.ANY_LOCATION, Kind.Long)); + graph().addBeforeFixed(this, readNode); + readNode.setNullCheck(true); + + int verifiedEntryOffset = HotSpotGraalRuntime.graalRuntime().getConfig().nmethodEntryOffset; + ReadNode readAddressNode = graph().add(new ReadNode(readNode, verifiedEntryOffset, LocationIdentity.ANY_LOCATION, Kind.Long)); + graph().addBeforeFixed(this, readAddressNode); + readAddressNode.setNullCheck(true); + + JavaType[] signatureTypes = new JavaType[getTargetMethod().getSignature().getParameterCount(false)]; + for (int i = 0; i < signatureTypes.length; ++i) { + signatureTypes[i] = getTargetMethod().getSignature().getParameterType(i, getTargetMethod().getDeclaringClass()); } - } else { - replaceWithInvoke(tool.getRuntime()); + + IndirectCallTargetNode callTarget = graph().add(new IndirectCallTargetNode(readAddressNode, arguments, StampFactory.object(), signatureTypes, super.getTargetMethod(), Type.JavaCall)); + InvokeNode invoke = graph().add(new InvokeNode(callTarget, super.getBci())); + invoke.setStateAfter(stateAfter()); + graph().replaceFixedWithFixed(this, invoke); } } - - protected InvokeNode replaceWithInvoke(MetaAccessProvider tool) { - ResolvedJavaMethod method = null; - ResolvedJavaField methodField = null; - ResolvedJavaField metaspaceMethodField = null; - ResolvedJavaField codeBlobField = null; - try { - method = tool.lookupJavaMethod(HotSpotNmethodExecuteNode.class.getMethod("placeholder", Object.class, Object.class, Object.class)); - methodField = tool.lookupJavaField(HotSpotNmethod.class.getDeclaredField("method")); - codeBlobField = tool.lookupJavaField(HotSpotInstalledCode.class.getDeclaredField("codeBlob")); - metaspaceMethodField = tool.lookupJavaField(HotSpotResolvedJavaMethod.class.getDeclaredField("metaspaceMethod")); - } catch (NoSuchMethodException | SecurityException | NoSuchFieldException e) { - throw new IllegalStateException(e); - } - ResolvedJavaType[] signatureTypes = new ResolvedJavaType[signature.length]; - for (int i = 0; i < signature.length; i++) { - signatureTypes[i] = tool.lookupJavaType(signature[i]); - } - final int verifiedEntryPointOffset = HotSpotReplacementsUtil.verifiedEntryPointOffset(); - - LoadFieldNode loadCodeBlob = graph().add(new LoadFieldNode(code, codeBlobField)); - UnsafeLoadNode load = graph().add(new UnsafeLoadNode(loadCodeBlob, verifiedEntryPointOffset, ConstantNode.forLong(0, graph()), graalRuntime().getTarget().wordKind)); - - LoadFieldNode loadMethod = graph().add(new LoadFieldNode(code, methodField)); - LoadFieldNode loadmetaspaceMethod = graph().add(new LoadFieldNode(loadMethod, metaspaceMethodField)); - - HotSpotIndirectCallTargetNode callTarget = graph().add( - new HotSpotIndirectCallTargetNode(loadmetaspaceMethod, load, arguments(), stamp(), signatureTypes, method, CallingConvention.Type.JavaCall)); - - InvokeNode invoke = graph().add(new InvokeNode(callTarget, 0)); - - invoke.setStateAfter(stateAfter()); - graph().replaceFixedWithFixed(this, invoke); - - graph().addBeforeFixed(invoke, loadmetaspaceMethod); - graph().addBeforeFixed(loadmetaspaceMethod, loadMethod); - graph().addBeforeFixed(invoke, load); - graph().addBeforeFixed(load, loadCodeBlob); - - return invoke; - } - - public static Object placeholder(@SuppressWarnings("unused") Object a1, @SuppressWarnings("unused") Object a2, @SuppressWarnings("unused") Object a3) { - return 1; - } - - @NodeIntrinsic - public static native T call(@ConstantNodeParameter Kind kind, @ConstantNodeParameter Class[] signature, Object code, Object arg1, Object arg2, Object arg3); - } diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNmethodSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNmethodSubstitutions.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNmethodSubstitutions.java Mon Jul 08 21:12:41 2013 +0200 @@ -22,19 +22,17 @@ */ package com.oracle.graal.hotspot.replacements; -import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.Snippet.Fold; @ClassSubstitution(HotSpotNmethod.class) public class HotSpotNmethodSubstitutions { - @MethodSubstitution(isStatic = false) - public static Object execute(HotSpotInstalledCode code, final Object arg1, final Object arg2, final Object arg3) { - return HotSpotNmethodExecuteNode.call(Kind.Object, getSignature(), code, arg1, arg2, arg3); - } + @MacroSubstitution(macro = HotSpotNmethodExecuteNode.class, isStatic = true) + public static native Object executeHelper(final Object arg1, final Object arg2, final Object arg3, HotSpotInstalledCode code); @Fold private static Class[] getSignature() { diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Mon Jul 08 21:12:41 2013 +0200 @@ -25,6 +25,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -45,6 +46,10 @@ return object; } + public GuardingPiNode(ValueNode object) { + this(object, object.graph().unique(new IsNullNode(object)), true, DeoptimizationReason.NullCheckException, DeoptimizationAction.None, object.stamp().join(StampFactory.objectNonNull())); + } + public GuardingPiNode(ValueNode object, ValueNode condition, boolean negateCondition, DeoptimizationReason reason, DeoptimizationAction action, Stamp stamp) { super(object.stamp().join(stamp)); assert stamp() != null; @@ -83,6 +88,9 @@ } @NodeIntrinsic + public static native T guardingNonNull(T object); + + @NodeIntrinsic public static native Object guardingPi(Object object, LogicNode condition, @ConstantNodeParameter boolean negateCondition, @ConstantNodeParameter DeoptimizationReason reason, @ConstantNodeParameter DeoptimizationAction action, @ConstantNodeParameter Stamp stamp); diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Jul 08 21:12:41 2013 +0200 @@ -42,7 +42,7 @@ super(object, location, stamp, guard, barrierType, compress); } - private ReadNode(ValueNode object, int displacement, LocationIdentity locationIdentity, Kind kind) { + public ReadNode(ValueNode object, int displacement, LocationIdentity locationIdentity, Kind kind) { super(object, ConstantLocationNode.create(locationIdentity, kind, displacement, object.graph()), StampFactory.forKind(kind)); } diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java Mon Jul 08 21:12:41 2013 +0200 @@ -24,9 +24,10 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -public abstract class UnsafeAccessNode extends FixedWithNextNode { +public abstract class UnsafeAccessNode extends FixedWithNextNode implements Canonicalizable { @Input private ValueNode object; @Input private ValueNode offset; @@ -57,4 +58,39 @@ public Kind accessKind() { return accessKind; } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (offset().isConstant()) { + long constantOffset = offset().asConstant().asLong(); + + // Try to canonicalize to a field access. + if (object().stamp() instanceof ObjectStamp) { + // TODO (gd) remove that once UnsafeAccess only have an object base + ObjectStamp receiverStamp = object().objectStamp(); + ResolvedJavaType receiverType = receiverStamp.type(); + if (receiverType != null) { + ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement() + constantOffset); + // No need for checking that the receiver is non-null. The field access includes + // the null check and if a field is found, the offset is so small that this is + // never a valid access of an arbitrary address. + if (field != null && field.getKind() == this.accessKind()) { + return cloneAsFieldAccess(field); + } + } + } + + if (constantOffset != 0 && Integer.MAX_VALUE - displacement() >= constantOffset) { + int intDisplacement = (int) (constantOffset + displacement()); + if (constantOffset == intDisplacement) { + return cloneWithZeroOffset(intDisplacement); + } + } + } + return this; + } + + protected abstract ValueNode cloneAsFieldAccess(ResolvedJavaField field); + + protected abstract ValueNode cloneWithZeroOffset(int intDisplacement); } diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Mon Jul 08 21:12:41 2013 +0200 @@ -25,7 +25,6 @@ import static com.oracle.graal.graph.UnsafeAccess.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @@ -35,7 +34,7 @@ * Load of a value from a location specified as an offset relative to an object. No null check is * performed before the load. */ -public class UnsafeLoadNode extends UnsafeAccessNode implements Lowerable, Virtualizable, Canonicalizable { +public class UnsafeLoadNode extends UnsafeAccessNode implements Lowerable, Virtualizable { public UnsafeLoadNode(ValueNode object, int displacement, ValueNode offset, boolean nonNull) { this(nonNull ? StampFactory.objectNonNull() : StampFactory.object(), object, displacement, offset, Kind.Object); @@ -70,29 +69,13 @@ } @Override - public ValueNode canonical(CanonicalizerTool tool) { - if (offset().isConstant()) { - long constantOffset = offset().asConstant().asLong(); - if (constantOffset != 0) { - int intDisplacement = (int) (constantOffset + displacement()); - if (constantOffset == intDisplacement) { - Graph graph = this.graph(); - return graph.add(new UnsafeLoadNode(this.stamp(), object(), intDisplacement, graph.unique(ConstantNode.forInt(0, graph)), accessKind())); - } - } else if (object().stamp() instanceof ObjectStamp) { // TODO (gd) remove that once - // UnsafeAccess only have an - // object base - ObjectStamp receiverStamp = object().objectStamp(); - ResolvedJavaType receiverType = receiverStamp.type(); - if (receiverStamp.nonNull() && receiverType != null) { - ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement()); - if (field != null) { - return this.graph().add(new LoadFieldNode(object(), field)); - } - } - } - } - return this; + protected ValueNode cloneAsFieldAccess(ResolvedJavaField field) { + return this.graph().add(new LoadFieldNode(object(), field)); + } + + @Override + protected ValueNode cloneWithZeroOffset(int intDisplacement) { + return graph().add(new UnsafeLoadNode(this.stamp(), object(), intDisplacement, graph().unique(ConstantNode.forInt(0, graph())), accessKind())); } @SuppressWarnings("unchecked") diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Mon Jul 08 21:12:41 2013 +0200 @@ -34,7 +34,7 @@ * Store of a value at a location specified as an offset relative to an object. No null check is * performed before the store. */ -public class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, Canonicalizable, MemoryCheckpoint.Single { +public class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, MemoryCheckpoint.Single { @Input private ValueNode value; @Input(notDataflow = true) private FrameState stateAfter; @@ -94,32 +94,17 @@ } @Override - public ValueNode canonical(CanonicalizerTool tool) { - if (offset().isConstant()) { - long constantOffset = offset().asConstant().asLong(); - if (constantOffset != 0) { - int intDisplacement = (int) (constantOffset + displacement()); - if (constantOffset == intDisplacement) { - UnsafeStoreNode unsafeStoreNode = graph().add(new UnsafeStoreNode(stamp(), object(), intDisplacement, ConstantNode.forInt(0, graph()), value(), accessKind())); - unsafeStoreNode.setStateAfter(stateAfter()); - return unsafeStoreNode; - } - } else if (object().stamp() instanceof ObjectStamp) { // TODO (gd) remove that once - // UnsafeAccess only have an - // object base - ObjectStamp receiverStamp = object().objectStamp(); - if (receiverStamp.nonNull()) { - ResolvedJavaType receiverType = receiverStamp.type(); - ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement()); - if (field != null) { - StoreFieldNode storeFieldNode = graph().add(new StoreFieldNode(object(), field, value())); - storeFieldNode.setStateAfter(stateAfter()); - return storeFieldNode; - } - } - } - } - return this; + protected ValueNode cloneAsFieldAccess(ResolvedJavaField field) { + StoreFieldNode storeFieldNode = graph().add(new StoreFieldNode(object(), field, value())); + storeFieldNode.setStateAfter(stateAfter()); + return storeFieldNode; + } + + @Override + protected ValueNode cloneWithZeroOffset(int intDisplacement) { + UnsafeStoreNode unsafeStoreNode = graph().add(new UnsafeStoreNode(stamp(), object(), intDisplacement, ConstantNode.forInt(0, graph()), value(), accessKind())); + unsafeStoreNode.setStateAfter(stateAfter()); + return unsafeStoreNode; } // specialized on value type until boxing/unboxing is sorted out in intrinsification diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Mon Jul 08 21:12:41 2013 +0200 @@ -331,27 +331,7 @@ assert inlineable instanceof InlineableMacroNode; Class macroNodeClass = ((InlineableMacroNode) inlineable).getMacroNodeClass(); - if (((MethodCallTargetNode) invoke.callTarget()).targetMethod() != concrete) { - assert ((MethodCallTargetNode) invoke.callTarget()).invokeKind() != InvokeKind.Static; - InliningUtil.replaceInvokeCallTarget(invoke, graph, InvokeKind.Special, concrete); - } - - FixedWithNextNode macroNode; - try { - macroNode = macroNodeClass.getConstructor(Invoke.class).newInstance(invoke); - } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) { - throw new GraalInternalError(e).addContext(invoke.asNode()).addContext("macroSubstitution", macroNodeClass); - } - - CallTargetNode callTarget = invoke.callTarget(); - if (invoke instanceof InvokeNode) { - graph.replaceFixedWithFixed((InvokeNode) invoke, graph.add(macroNode)); - } else { - InvokeWithExceptionNode invokeWithException = (InvokeWithExceptionNode) invoke; - invokeWithException.killExceptionEdge(); - graph.replaceSplitWithFixed(invokeWithException, graph.add(macroNode), invokeWithException.next()); - } - GraphUtil.killWithUnusedFloatingInputs(callTarget); + inlineMacroNode(invoke, concrete, graph, macroNodeClass); } InlinedBytecodes.add(concrete.getCodeSize()); @@ -1480,4 +1460,29 @@ public static Class getMacroNodeClass(Replacements replacements, ResolvedJavaMethod target) { return replacements.getMacroSubstitution(target); } + + public static FixedWithNextNode inlineMacroNode(Invoke invoke, ResolvedJavaMethod concrete, StructuredGraph graph, Class macroNodeClass) throws GraalInternalError { + if (((MethodCallTargetNode) invoke.callTarget()).targetMethod() != concrete) { + assert ((MethodCallTargetNode) invoke.callTarget()).invokeKind() != InvokeKind.Static; + InliningUtil.replaceInvokeCallTarget(invoke, graph, InvokeKind.Special, concrete); + } + + FixedWithNextNode macroNode; + try { + macroNode = macroNodeClass.getConstructor(Invoke.class).newInstance(invoke); + } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) { + throw new GraalInternalError(e).addContext(invoke.asNode()).addContext("macroSubstitution", macroNodeClass); + } + + CallTargetNode callTarget = invoke.callTarget(); + if (invoke instanceof InvokeNode) { + graph.replaceFixedWithFixed((InvokeNode) invoke, graph.add(macroNode)); + } else { + InvokeWithExceptionNode invokeWithException = (InvokeWithExceptionNode) invoke; + invokeWithException.killExceptionEdge(); + graph.replaceSplitWithFixed(invokeWithException, graph.add(macroNode), invokeWithException.next()); + } + GraphUtil.killWithUnusedFloatingInputs(callTarget); + return macroNode; + } } diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraySubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraySubstitutions.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraySubstitutions.java Mon Jul 08 21:12:41 2013 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.replacements; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; @@ -36,9 +34,6 @@ @MethodSubstitution public static Object newInstance(Class componentType, int length) throws NegativeArraySizeException { - if (componentType == null) { - DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.NullCheckException); - } - return DynamicNewArrayNode.newArray(componentType, length); + return DynamicNewArrayNode.newArray(GuardingPiNode.guardingNonNull(componentType), length); } } diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Mon Jul 08 21:12:41 2013 +0200 @@ -71,37 +71,39 @@ @Override public Object call(PackedFrame caller, Arguments args) { - for (;;) { - if (compiledMethod != null) { - try { - return compiledMethod.execute(this, caller, args); - } catch (InvalidInstalledCodeException ex) { - compiledMethod = null; - invokeCounter = invalidationReprofileCount; - if (TruffleFunctionInlining.getValue()) { - originalInvokeCounter += invalidationReprofileCount; - } - if (TraceTruffleCompilation.getValue()) { - OUT.printf("[truffle] invalidated %-48s |Alive %5.0fms\n", rootNode, (System.nanoTime() - timeCompilationFinished) / 1e6); - } + if (compiledMethod != null) { + try { + return compiledMethod.execute(this, caller, args); + } catch (InvalidInstalledCodeException ex) { + compiledMethod = null; + invokeCounter = invalidationReprofileCount; + if (TruffleFunctionInlining.getValue()) { + originalInvokeCounter += invalidationReprofileCount; + } + if (TraceTruffleCompilation.getValue()) { + OUT.printf("[truffle] invalidated %-48s |Alive %5.0fms\n", rootNode, (System.nanoTime() - timeCompilationFinished) / 1e6); } + return call(caller, args); + } + } else { + return interpreterCall(caller, args); + } + } + + private Object interpreterCall(PackedFrame caller, Arguments args) { + invokeCounter--; + loopAndInvokeCounter--; + if (disableCompilation || loopAndInvokeCounter > 0 || invokeCounter > 0) { + return executeHelper(caller, args); + } else { + if (TruffleFunctionInlining.getValue() && inline()) { + invokeCounter = 2; + loopAndInvokeCounter = inliningReprofileCount; + originalInvokeCounter = inliningReprofileCount; } else { - invokeCounter--; - loopAndInvokeCounter--; - if (disableCompilation || loopAndInvokeCounter > 0 || invokeCounter > 0) { - return executeHelper(caller, args); - } else { - if (TruffleFunctionInlining.getValue()) { - if (inline()) { - invokeCounter = 2; - loopAndInvokeCounter = inliningReprofileCount; - originalInvokeCounter = inliningReprofileCount; - continue; - } - } - compile(); - } + compile(); } + return call(caller, args); } } @@ -260,7 +262,7 @@ @Override public boolean visit(Node node) { - if (node instanceof RootNode && node != root) { + if (node instanceof RootNode && visitedCount > 0) { return false; } diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java Mon Jul 08 21:12:41 2013 +0200 @@ -26,7 +26,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.common.*; @@ -68,41 +67,8 @@ return ConstantNode.forObject(value, metaAccessProvider, node.graph()); } } - } else if (node instanceof UnsafeLoadNode) { - UnsafeLoadNode unsafeLoadNode = (UnsafeLoadNode) node; - if (unsafeLoadNode.offset().isConstant()) { - long offset = unsafeLoadNode.offset().asConstant().asLong() + unsafeLoadNode.displacement(); - ResolvedJavaType type = unsafeLoadNode.object().objectStamp().type(); - ResolvedJavaField field = recursiveFindFieldWithOffset(type, offset); - if (field != null) { - return node.graph().add(new LoadFieldNode(unsafeLoadNode.object(), field)); - } - } - } else if (node instanceof UnsafeStoreNode) { - UnsafeStoreNode unsafeStoreNode = (UnsafeStoreNode) node; - if (unsafeStoreNode.offset().isConstant()) { - long offset = unsafeStoreNode.offset().asConstant().asLong() + unsafeStoreNode.displacement(); - ResolvedJavaType type = unsafeStoreNode.object().objectStamp().type(); - ResolvedJavaField field = recursiveFindFieldWithOffset(type, offset); - if (field != null) { - StoreFieldNode storeFieldNode = node.graph().add(new StoreFieldNode(unsafeStoreNode.object(), field, unsafeStoreNode.value())); - storeFieldNode.setStateAfter(unsafeStoreNode.stateAfter()); - return storeFieldNode; - } - } } return node; } - - private ResolvedJavaField recursiveFindFieldWithOffset(ResolvedJavaType type, long offset) { - if (type != null) { - ResolvedJavaField field = type.findInstanceFieldWithOffset(offset); - if (field != null) { - return field; - } - return recursiveFindFieldWithOffset(type.getSuperclass(), offset); - } - return null; - } } diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Mon Jul 08 21:12:41 2013 +0200 @@ -216,25 +216,25 @@ if (invoke.callTarget() instanceof MethodCallTargetNode) { final MethodCallTargetNode methodCallTargetNode = (MethodCallTargetNode) invoke.callTarget(); if ((methodCallTargetNode.invokeKind() == InvokeKind.Special || methodCallTargetNode.invokeKind() == InvokeKind.Static) && - !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers())) { - if (methodCallTargetNode.targetMethod().getAnnotation(ExplodeLoop.class) != null) { - // Do not inline explode loop methods, they need canonicalization and forced - // unrolling. - return invoke.asNode(); - } - StructuredGraph inlinedGraph = Debug.scope("ExpandInvoke", methodCallTargetNode.targetMethod(), new Callable() { + !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers()) && methodCallTargetNode.targetMethod().getAnnotation(ExplodeLoop.class) == null) { + Class macroSubstitution = replacements.getMacroSubstitution(methodCallTargetNode.targetMethod()); + if (macroSubstitution != null) { + return InliningUtil.inlineMacroNode(invoke, methodCallTargetNode.targetMethod(), methodCallTargetNode.graph(), macroSubstitution); + } else { + StructuredGraph inlinedGraph = Debug.scope("ExpandInvoke", methodCallTargetNode.targetMethod(), new Callable() { - public StructuredGraph call() { - StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod()); - if (inlineGraph == null) { - inlineGraph = parseGraph(methodCallTargetNode.targetMethod()); + public StructuredGraph call() { + StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod()); + if (inlineGraph == null) { + inlineGraph = parseGraph(methodCallTargetNode.targetMethod()); + } + return inlineGraph; } - return inlineGraph; - } - }); - FixedNode fixedNode = (FixedNode) invoke.predecessor(); - InliningUtil.inline(invoke, inlinedGraph, true); - return fixedNode; + }); + FixedNode fixedNode = (FixedNode) invoke.predecessor(); + InliningUtil.inline(invoke, inlinedGraph, true); + return fixedNode; + } } } return invoke.asNode(); diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/UnsafeCastMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/UnsafeCastMacroNode.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/UnsafeCastMacroNode.java Mon Jul 08 21:12:41 2013 +0200 @@ -41,7 +41,10 @@ Class c = (Class) arguments.get(1).asConstant().asObject(); ResolvedJavaType lookupJavaType = tool.runtime().lookupJavaType(c); Stamp s = StampFactory.declaredNonNull(lookupJavaType); - return graph().unique(new UnsafeCastNode(arguments.get(0), s)); + ValueAnchorNode valueAnchorNode = graph().add(new ValueAnchorNode()); + UnsafeCastNode unsafeCast = graph().unique(new UnsafeCastNode(arguments.get(0), s, (GuardingNode) valueAnchorNode)); + this.replaceAtUsages(unsafeCast); + return valueAnchorNode; } return this; } diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Mon Jul 08 21:12:41 2013 +0200 @@ -57,4 +57,7 @@ @MacroSubstitution(macro = BailoutNode.class, isStatic = true) public static native void bailout(String reason); + + @MacroSubstitution(macro = UnsafeCastMacroNode.class, isStatic = true) + public static native Object unsafeCast(Object value, Class clazz); } diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java Mon Jul 08 21:12:41 2013 +0200 @@ -33,7 +33,7 @@ public class OptimizedCallTargetSubstitutions { @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false) - public static native Object call(OptimizedCallTarget target, PackedFrame caller, Arguments args); + public static native Object interpreterCall(OptimizedCallTarget target, PackedFrame caller, Arguments args); @MethodSubstitution private static FrameWithoutBoxing createFrame(FrameDescriptor descriptor, PackedFrame caller, Arguments args) { diff -r 678cdd287d60 -r 2abf1c8b062a graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Mon Jul 08 17:32:05 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Mon Jul 08 21:12:41 2013 +0200 @@ -126,4 +126,17 @@ @Target({ElementType.METHOD}) public @interface Unsafe { } + + /** + * Treats the given value as a value of the given class. The class must evaluate to a constant. + * + * @param value the value that is known to have the specified type + * @param clazz the specified type of the value + * @return the value + */ + @SuppressWarnings("unchecked") + @Unsafe + public static T unsafeCast(Object value, Class clazz) { + return (T) value; + } } diff -r 678cdd287d60 -r 2abf1c8b062a src/cpu/x86/vm/graalCodeInstaller_x86.hpp --- a/src/cpu/x86/vm/graalCodeInstaller_x86.hpp Mon Jul 08 17:32:05 2013 +0200 +++ b/src/cpu/x86/vm/graalCodeInstaller_x86.hpp Mon Jul 08 21:12:41 2013 +0200 @@ -179,7 +179,6 @@ break; } default: - fatal("invalid _next_call_type value"); break; } }