# HG changeset patch # User Christian Wimmer # Date 1400891598 25200 # Node ID 8184c00fefd22e2cb6843c615e68090ba1b5c2a7 # Parent 1aaadf06db1bea397085d56f098b0c63bd82e4f3 Factor out VM-independent part of DefaultHotSpotLoweringProvider into DefaultJavaLoweringProvider diff -r 1aaadf06db1b -r 8184c00fefd2 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Sat May 24 01:41:56 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Fri May 23 17:33:18 2014 -0700 @@ -104,7 +104,7 @@ HotSpotConstantReflectionProvider constantReflection = createConstantReflection(runtime); Value[] nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(runtime.getConfig(), codeCache.getRegisterConfig()); HotSpotHostForeignCallsProvider foreignCalls = createForeignCalls(runtime, metaAccess, codeCache, nativeABICallerSaveRegisters); - HotSpotLoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers); + HotSpotLoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers, target); // Replacements cannot have speculative optimizations since they have // to be valid for the entire run of the VM. Assumptions assumptions = new Assumptions(false); @@ -161,8 +161,9 @@ return new HotSpotSnippetReflectionProvider(); } - protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntime runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) { - return new AMD64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers); + protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntime runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, + TargetDescription target) { + return new AMD64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, target); } protected Value[] createNativeABICallerSaveRegisters(HotSpotVMConfig config, RegisterConfig regConfig) { diff -r 1aaadf06db1b -r 8184c00fefd2 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLoweringProvider.java Sat May 24 01:41:56 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLoweringProvider.java Fri May 23 17:33:18 2014 -0700 @@ -35,8 +35,8 @@ private AMD64ConvertSnippets.Templates convertSnippets; - public AMD64HotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) { - super(runtime, metaAccess, foreignCalls, registers); + public AMD64HotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, TargetDescription target) { + super(runtime, metaAccess, foreignCalls, registers, target); } @Override diff -r 1aaadf06db1b -r 8184c00fefd2 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java Sat May 24 01:41:56 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java Fri May 23 17:33:18 2014 -0700 @@ -36,8 +36,9 @@ @ServiceProvider(HotSpotBackendFactory.class) public class HSAILHotSpotBackendFactory implements HotSpotBackendFactory { - protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntime runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) { - return new HSAILHotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers); + protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntime runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, + TargetDescription target) { + return new HSAILHotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, target); } @Override @@ -46,10 +47,11 @@ HotSpotRegisters registers = new HotSpotRegisters(HSAIL.threadRegister, Register.None, Register.None); HotSpotMetaAccessProvider metaAccess = host.getMetaAccess(); - HSAILHotSpotCodeCacheProvider codeCache = new HSAILHotSpotCodeCacheProvider(runtime, createTarget()); + TargetDescription target = createTarget(); + HSAILHotSpotCodeCacheProvider codeCache = new HSAILHotSpotCodeCacheProvider(runtime, target); ConstantReflectionProvider constantReflection = host.getConstantReflection(); HotSpotForeignCallsProvider foreignCalls = new HSAILHotSpotForeignCallsProvider(runtime, metaAccess, codeCache); - HotSpotLoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers); + HotSpotLoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers, target); // Replacements cannot have speculative optimizations since they have // to be valid for the entire run of the VM. Assumptions assumptions = new Assumptions(false); diff -r 1aaadf06db1b -r 8184c00fefd2 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java Sat May 24 01:41:56 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java Fri May 23 17:33:18 2014 -0700 @@ -121,15 +121,14 @@ return strategyMap.get(n.getClass()); } - public HSAILHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) { - super(runtime, metaAccess, foreignCalls, registers); + public HSAILHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, TargetDescription target) { + super(runtime, metaAccess, foreignCalls, registers, target); initStrategyMap(); } @Override public void initialize(HotSpotProviders providers, HotSpotVMConfig config) { super.initialize(providers, config); - TargetDescription target = providers.getCodeCache().getTarget(); hsailNewObjectSnippets = new HSAILNewObjectSnippets.Templates(providers, target); } diff -r 1aaadf06db1b -r 8184c00fefd2 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java Sat May 24 01:41:56 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java Fri May 23 17:33:18 2014 -0700 @@ -221,7 +221,7 @@ final int headerSize = HotSpotGraalRuntime.getArrayBaseOffset(elementKind); // lowerer extends HotSpotLoweringProvider so we can just use that HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer(); - int log2ElementSize = CodeUtil.log2(lowerer.getScalingFactor(elementKind)); + int log2ElementSize = CodeUtil.log2(lowerer.arrayScalingFactor(elementKind)); Arguments args = new Arguments(allocateArray, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); diff -r 1aaadf06db1b -r 8184c00fefd2 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Sat May 24 01:41:56 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Fri May 23 17:33:18 2014 -0700 @@ -55,7 +55,7 @@ HotSpotConstantReflectionProvider constantReflection = new HotSpotConstantReflectionProvider(runtime); Value[] nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(runtime.getConfig(), codeCache.getRegisterConfig()); HotSpotForeignCallsProvider foreignCalls = new SPARCHotSpotForeignCallsProvider(runtime, metaAccess, codeCache, nativeABICallerSaveRegisters); - LoweringProvider lowerer = new SPARCHotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers); + LoweringProvider lowerer = new SPARCHotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, target); // Replacements cannot have speculative optimizations since they have // to be valid for the entire run of the VM. Assumptions assumptions = new Assumptions(false); diff -r 1aaadf06db1b -r 8184c00fefd2 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLoweringProvider.java Sat May 24 01:41:56 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLoweringProvider.java Fri May 23 17:33:18 2014 -0700 @@ -32,8 +32,8 @@ public class SPARCHotSpotLoweringProvider extends DefaultHotSpotLoweringProvider { - public SPARCHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) { - super(runtime, metaAccess, foreignCalls, registers); + public SPARCHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, TargetDescription target) { + super(runtime, metaAccess, foreignCalls, registers, target); } @Override diff -r 1aaadf06db1b -r 8184c00fefd2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java Sat May 24 01:41:56 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java Fri May 23 17:33:18 2014 -0700 @@ -22,22 +22,14 @@ */ package com.oracle.graal.hotspot.meta; -import static com.oracle.graal.api.code.MemoryBarriers.*; -import static com.oracle.graal.api.meta.DeoptimizationAction.*; -import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.compiler.common.GraalOptions.*; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProviderImpl.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*; -import static com.oracle.graal.nodes.java.ArrayLengthNode.*; - -import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; @@ -56,16 +48,14 @@ import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.replacements.*; /** * HotSpot implementation of {@link LoweringProvider}. */ -public class DefaultHotSpotLoweringProvider implements HotSpotLoweringProvider { +public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider implements HotSpotLoweringProvider { protected final HotSpotGraalRuntime runtime; - protected final MetaAccessProvider metaAccess; protected final ForeignCallsProvider foreignCalls; protected final HotSpotRegistersProvider registers; @@ -74,25 +64,25 @@ protected NewObjectSnippets.Templates newObjectSnippets; protected MonitorSnippets.Templates monitorSnippets; protected WriteBarrierSnippets.Templates writeBarrierSnippets; - protected BoxingSnippets.Templates boxingSnippets; protected LoadExceptionObjectSnippets.Templates exceptionObjectSnippets; protected UnsafeLoadSnippets.Templates unsafeLoadSnippets; - public DefaultHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) { + public DefaultHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, TargetDescription target) { + super(metaAccess, target); this.runtime = runtime; - this.metaAccess = metaAccess; this.foreignCalls = foreignCalls; this.registers = registers; } public void initialize(HotSpotProviders providers, HotSpotVMConfig config) { - TargetDescription target = providers.getCodeCache().getTarget(); + super.initialize(providers, providers.getSnippetReflection()); + + assert target == providers.getCodeCache().getTarget(); checkcastDynamicSnippets = new CheckCastDynamicSnippets.Templates(providers, target); instanceofSnippets = new InstanceOfSnippets.Templates(providers, target); newObjectSnippets = new NewObjectSnippets.Templates(providers, target); monitorSnippets = new MonitorSnippets.Templates(providers, target, config.useFastLocking); writeBarrierSnippets = new WriteBarrierSnippets.Templates(providers, target, config.useCompressedOops ? config.getOopEncoding() : null); - boxingSnippets = new BoxingSnippets.Templates(providers, providers.getSnippetReflection(), target); exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(providers, target); unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(providers, target); providers.getReplacements().registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(providers, target)); @@ -102,38 +92,12 @@ public void lower(Node n, LoweringTool tool) { StructuredGraph graph = (StructuredGraph) n.graph(); - if (n instanceof ArrayLengthNode) { - lowerArrayLengthNode((ArrayLengthNode) n, tool); - } else if (n instanceof Invoke) { + if (n instanceof Invoke) { lowerInvoke((Invoke) n, tool, graph); - } else if (n instanceof LoadFieldNode) { - lowerLoadFieldNode((LoadFieldNode) n, tool); - } else if (n instanceof StoreFieldNode) { - lowerStoreFieldNode((StoreFieldNode) n, tool); - } else if (n instanceof CompareAndSwapNode) { - lowerCompareAndSwapNode((CompareAndSwapNode) n); - } else if (n instanceof AtomicReadAndWriteNode) { - lowerAtomicReadAndWriteNode((AtomicReadAndWriteNode) n); - } else if (n instanceof LoadIndexedNode) { - lowerLoadIndexedNode((LoadIndexedNode) n, tool); - } else if (n instanceof StoreIndexedNode) { - lowerStoreIndexedNode((StoreIndexedNode) n, tool); - } else if (n instanceof UnsafeLoadNode) { - lowerUnsafeLoadNode((UnsafeLoadNode) n, tool); - } else if (n instanceof UnsafeStoreNode) { - lowerUnsafeStoreNode((UnsafeStoreNode) n); - } else if (n instanceof JavaReadNode) { - lowerJavaReadNode((JavaReadNode) n); - } else if (n instanceof JavaWriteNode) { - lowerJavaWriteNode((JavaWriteNode) n); - } else if (n instanceof LoadHubNode) { - lowerLoadHubNode((LoadHubNode) n); } else if (n instanceof LoadMethodNode) { lowerLoadMethodNode((LoadMethodNode) n); } else if (n instanceof StoreHubNode) { lowerStoreHubNode((StoreHubNode) n, graph); - } else if (n instanceof CommitAllocationNode) { - lowerCommitAllocationNode((CommitAllocationNode) n, tool); } else if (n instanceof OSRStartNode) { lowerOSRStartNode((OSRStartNode) n); } else if (n instanceof DynamicCounterNode) { @@ -197,26 +161,13 @@ } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) { // Nothing to do for division nodes. The HotSpot signal handler catches divisions by // zero and the MIN_VALUE / -1 cases. - } else if (n instanceof BoxNode) { - boxingSnippets.lower((BoxNode) n, tool); - } else if (n instanceof UnboxNode) { - boxingSnippets.lower((UnboxNode) n, tool); } else if (n instanceof DeoptimizeNode || n instanceof UnwindNode || n instanceof FloatRemNode) { /* No lowering, we generate LIR directly for these nodes. */ } else { - throw GraalInternalError.shouldNotReachHere("Node implementing Lowerable not handled: " + n); + super.lower(n, tool); } } - private void lowerArrayLengthNode(ArrayLengthNode arrayLengthNode, LoweringTool tool) { - StructuredGraph graph = arrayLengthNode.graph(); - ValueNode array = arrayLengthNode.array(); - ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, runtime.getConfig().arrayLengthOffset, graph), - StampFactory.positiveInt(), BarrierType.NONE, false)); - arrayLengthRead.setGuard(createNullCheck(array, arrayLengthNode, tool)); - graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead); - } - private void lowerInvoke(Invoke invoke, LoweringTool tool, StructuredGraph graph) { if (invoke.callTarget() instanceof MethodCallTargetNode) { MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); @@ -236,7 +187,7 @@ ResolvedJavaType receiverType = invoke.getReceiverType(); if (hsMethod.isInVirtualMethodTable(receiverType)) { Kind wordKind = runtime.getTarget().wordKind; - ValueNode hub = createReadHub(graph, wordKind, receiver, receiverNullCheck); + ValueNode hub = createReadHub(graph, receiver, receiverNullCheck); ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, hub, hsMethod, receiverType); // We use LocationNode.ANY_LOCATION for the reads that access the @@ -261,291 +212,54 @@ } } - private Stamp loadStamp(Stamp stamp, Kind kind) { - return loadStamp(stamp, kind, true); - } - - private Stamp loadStamp(Stamp stamp, Kind kind, boolean compressible) { - switch (kind) { - case Boolean: - case Byte: - return StampTool.narrowingConversion(stamp, 8); - - case Char: - case Short: - return StampTool.narrowingConversion(stamp, 16); - - case Object: - if (compressible && runtime.getConfig().useCompressedOops) { - return NarrowOopStamp.compressed((ObjectStamp) stamp, runtime.getConfig().getOopEncoding()); - } + @Override + protected Stamp loadStamp(Stamp stamp, Kind kind, boolean compressible) { + if (kind == Kind.Object && compressible && runtime.getConfig().useCompressedOops) { + return NarrowOopStamp.compressed((ObjectStamp) stamp, runtime.getConfig().getOopEncoding()); } - return stamp; - } - - public ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value) { - return implicitLoadConvert(graph, kind, value, true); - } - - private ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value, boolean compressible) { - switch (kind) { - case Byte: - case Short: - return graph.unique(new SignExtendNode(value, 32)); - - case Boolean: - case Char: - return graph.unique(new ZeroExtendNode(value, 32)); - - case Object: - if (compressible && runtime.getConfig().useCompressedOops) { - return CompressionNode.uncompress(value, runtime.getConfig().getOopEncoding()); - } - } - return value; - } - - private void lowerLoadFieldNode(LoadFieldNode loadField, LoweringTool tool) { - StructuredGraph graph = loadField.graph(); - HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field(); - ValueNode object = loadField.isStatic() ? ConstantNode.forConstant(HotSpotObjectConstant.forObject(field.getDeclaringClass().mirror()), metaAccess, graph) : loadField.object(); - assert loadField.getKind() != Kind.Illegal; - BarrierType barrierType = getFieldLoadBarrierType(field); - - Stamp loadStamp = loadStamp(loadField.stamp(), field.getKind()); - ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field, false), loadStamp, barrierType, false)); - ValueNode readValue = implicitLoadConvert(graph, field.getKind(), memoryRead); - - loadField.replaceAtUsages(readValue); - graph.replaceFixed(loadField, memoryRead); - - memoryRead.setGuard(createNullCheck(object, memoryRead, tool)); - - if (loadField.isVolatile()) { - MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ)); - graph.addBeforeFixed(memoryRead, preMembar); - MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_READ)); - graph.addAfterFixed(memoryRead, postMembar); - } + return super.loadStamp(stamp, kind, compressible); } - public ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value) { - return implicitStoreConvert(graph, kind, value, true); - } - - private ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value, boolean compressible) { - switch (kind) { - case Boolean: - case Byte: - return graph.unique(new NarrowNode(value, 8)); - case Char: - case Short: - return graph.unique(new NarrowNode(value, 16)); - case Object: - if (compressible && runtime.getConfig().useCompressedOops) { - return CompressionNode.compress(value, runtime.getConfig().getOopEncoding()); - } + @Override + protected ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value, boolean compressible) { + if (kind == Kind.Object && compressible && runtime.getConfig().useCompressedOops) { + return CompressionNode.uncompress(value, runtime.getConfig().getOopEncoding()); } - return value; + return super.implicitLoadConvert(graph, kind, value, compressible); } - private void lowerStoreFieldNode(StoreFieldNode storeField, LoweringTool tool) { - StructuredGraph graph = storeField.graph(); - HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field(); - ValueNode object = storeField.isStatic() ? ConstantNode.forConstant(HotSpotObjectConstant.forObject(field.getDeclaringClass().mirror()), metaAccess, graph) : storeField.object(); - BarrierType barrierType = getFieldStoreBarrierType(storeField); - - ValueNode value = implicitStoreConvert(graph, storeField.field().getKind(), storeField.value()); - WriteNode memoryWrite = graph.add(new WriteNode(object, value, createFieldLocation(graph, field, false), barrierType, false)); - memoryWrite.setStateAfter(storeField.stateAfter()); - graph.replaceFixedWithFixed(storeField, memoryWrite); - memoryWrite.setGuard(createNullCheck(object, memoryWrite, tool)); - FixedWithNextNode last = memoryWrite; - FixedWithNextNode first = memoryWrite; - - if (storeField.isVolatile()) { - MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE)); - graph.addBeforeFixed(first, preMembar); - MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE)); - graph.addAfterFixed(last, postMembar); - } - } - - private void lowerCompareAndSwapNode(CompareAndSwapNode cas) { - StructuredGraph graph = cas.graph(); - Kind valueKind = cas.getValueKind(); - LocationNode location = IndexedLocationNode.create(cas.getLocationIdentity(), valueKind, cas.displacement(), cas.offset(), graph, 1); - - ValueNode expectedValue = implicitStoreConvert(graph, valueKind, cas.expected(), true); - ValueNode newValue = implicitStoreConvert(graph, valueKind, cas.newValue(), true); - - LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, expectedValue, newValue, getCompareAndSwapBarrierType(cas), false)); - atomicNode.setStateAfter(cas.stateAfter()); - graph.replaceFixedWithFixed(cas, atomicNode); - } - - private void lowerAtomicReadAndWriteNode(AtomicReadAndWriteNode n) { - StructuredGraph graph = n.graph(); - Kind valueKind = n.getValueKind(); - LocationNode location = IndexedLocationNode.create(n.getLocationIdentity(), valueKind, 0, n.offset(), graph, 1); - - ValueNode newValue = implicitStoreConvert(graph, valueKind, n.newValue()); - - LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(n.object(), location, newValue, getAtomicReadAndWriteBarrierType(n), false)); - memoryRead.setStateAfter(n.stateAfter()); - - ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead); - - n.replaceAtUsages(readValue); - graph.replaceFixedWithFixed(n, memoryRead); + @Override + protected ValueNode staticFieldBase(StructuredGraph graph, ResolvedJavaField f) { + HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) f; + return ConstantNode.forConstant(HotSpotObjectConstant.forObject(field.getDeclaringClass().mirror()), metaAccess, graph); } - private void lowerLoadIndexedNode(LoadIndexedNode loadIndexed, LoweringTool tool) { - StructuredGraph graph = loadIndexed.graph(); - Kind elementKind = loadIndexed.elementKind(); - LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index(), false); - - Stamp loadStamp = loadStamp(loadIndexed.stamp(), elementKind); - ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadStamp, BarrierType.NONE, false)); - ValueNode readValue = implicitLoadConvert(graph, elementKind, memoryRead); - - memoryRead.setGuard(createBoundsCheck(loadIndexed, tool)); - - loadIndexed.replaceAtUsages(readValue); - graph.replaceFixed(loadIndexed, memoryRead); - } - - private void lowerStoreIndexedNode(StoreIndexedNode storeIndexed, LoweringTool tool) { - StructuredGraph graph = storeIndexed.graph(); - GuardingNode boundsCheck = createBoundsCheck(storeIndexed, tool); - Kind elementKind = storeIndexed.elementKind(); - LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index(), false); - - ValueNode value = storeIndexed.value(); - ValueNode array = storeIndexed.array(); - - CheckCastNode checkcastNode = null; - CheckCastDynamicNode checkcastDynamicNode = null; - if (elementKind == Kind.Object && !StampTool.isObjectAlwaysNull(value)) { - // Store check! - ResolvedJavaType arrayType = StampTool.typeOrNull(array); - if (arrayType != null && StampTool.isExactType(array)) { - ResolvedJavaType elementType = arrayType.getComponentType(); - if (!MetaUtil.isJavaLangObject(elementType)) { - checkcastNode = graph.add(new CheckCastNode(elementType, value, null, true)); - graph.addBeforeFixed(storeIndexed, checkcastNode); - value = checkcastNode; - } - } else { - Kind wordKind = runtime.getTarget().wordKind; - ValueNode arrayClass = createReadHub(graph, wordKind, array, boundsCheck); - LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, runtime.getConfig().arrayClassElementOffset, graph); - /* - * Anchor the read of the element klass to the cfg, because it is only valid when - * arrayClass is an object class, which might not be the case in other parts of the - * compiled method. - */ - FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, location, null, StampFactory.forKind(wordKind), BeginNode.prevBegin(storeIndexed))); - checkcastDynamicNode = graph.add(new CheckCastDynamicNode(arrayElementKlass, value, true)); - graph.addBeforeFixed(storeIndexed, checkcastDynamicNode); - value = checkcastDynamicNode; - } + @Override + protected ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value, boolean compressible) { + if (kind == Kind.Object && compressible && runtime.getConfig().useCompressedOops) { + return CompressionNode.compress(value, runtime.getConfig().getOopEncoding()); } - BarrierType barrierType = getArrayStoreBarrierType(storeIndexed); - WriteNode memoryWrite = graph.add(new WriteNode(array, implicitStoreConvert(graph, elementKind, value), arrayLocation, barrierType, false)); - memoryWrite.setGuard(boundsCheck); - memoryWrite.setStateAfter(storeIndexed.stateAfter()); - graph.replaceFixedWithFixed(storeIndexed, memoryWrite); - - // Lower the associated checkcast node. - if (checkcastNode != null) { - checkcastNode.lower(tool); - } else if (checkcastDynamicNode != null) { - checkcastDynamicSnippets.lower(checkcastDynamicNode, tool); - } + return super.implicitStoreConvert(graph, kind, value, compressible); } - private ReadNode createUnsafeRead(StructuredGraph graph, UnsafeLoadNode load, GuardingNode guard) { - boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object); - Kind readKind = load.accessKind(); - LocationNode location = createLocation(load); - Stamp loadStamp = loadStamp(load.stamp(), readKind, compressible); - ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, loadStamp, guard, BarrierType.NONE, false)); - ValueNode readValue = implicitLoadConvert(graph, readKind, memoryRead, compressible); - load.replaceAtUsages(readValue); - return memoryRead; - } - - private void lowerUnsafeLoadNode(UnsafeLoadNode load, LoweringTool tool) { - StructuredGraph graph = load.graph(); - if (load.getGuardingCondition() != null) { - ConditionAnchorNode valueAnchorNode = graph.add(new ConditionAnchorNode(load.getGuardingCondition())); - ReadNode memoryRead = createUnsafeRead(graph, load, valueAnchorNode); - graph.replaceFixedWithFixed(load, valueAnchorNode); - graph.addAfterFixed(valueAnchorNode, memoryRead); - } else if (graph.getGuardsStage().ordinal() > StructuredGraph.GuardsStage.FLOATING_GUARDS.ordinal()) { - assert load.getKind() != Kind.Illegal; - if (addReadBarrier(load)) { - unsafeLoadSnippets.lower(load, tool); - } else { - ReadNode memoryRead = createUnsafeRead(graph, load, null); - // An unsafe read must not float outside its block otherwise - // it may float above an explicit null check on its object. - memoryRead.setGuard(BeginNode.prevBegin(load)); - graph.replaceFixedWithFixed(load, memoryRead); - } - } + @Override + protected ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor) { + Kind wordKind = runtime.getTarget().wordKind; + LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, runtime.getConfig().arrayClassElementOffset, graph); + /* + * Anchor the read of the element klass to the cfg, because it is only valid when arrayClass + * is an object class, which might not be the case in other parts of the compiled method. + */ + return graph.unique(new FloatingReadNode(arrayHub, location, null, StampFactory.forKind(wordKind), BeginNode.prevBegin(anchor))); } - private void lowerUnsafeStoreNode(UnsafeStoreNode store) { - StructuredGraph graph = store.graph(); - LocationNode location = createLocation(store); - ValueNode object = store.object(); - BarrierType barrierType = getUnsafeStoreBarrierType(store); - boolean compressible = store.value().getKind() == Kind.Object; - Kind valueKind = store.accessKind(); - ValueNode value = implicitStoreConvert(graph, valueKind, store.value(), compressible); - WriteNode write = graph.add(new WriteNode(object, value, location, barrierType, false)); - write.setStateAfter(store.stateAfter()); - graph.replaceFixedWithFixed(store, write); - } - - private void lowerJavaReadNode(JavaReadNode read) { - StructuredGraph graph = read.graph(); - - Kind valueKind = read.location().getValueKind(); - Stamp loadStamp = loadStamp(read.stamp(), valueKind, read.isCompressible()); - ReadNode memoryRead = graph.add(new ReadNode(read.object(), read.location(), loadStamp, read.getBarrierType(), false)); - ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead, read.isCompressible()); - - memoryRead.setGuard(read.getGuard()); - - read.replaceAtUsages(readValue); - graph.replaceFixed(read, memoryRead); - } - - private void lowerJavaWriteNode(JavaWriteNode write) { - StructuredGraph graph = write.graph(); - - Kind valueKind = write.location().getValueKind(); - ValueNode value = implicitStoreConvert(graph, valueKind, write.value(), write.isCompressible()); - - WriteNode memoryWrite = graph.add(new WriteNode(write.object(), value, write.location(), write.getBarrierType(), false, write.isInitialization())); - memoryWrite.setStateAfter(write.stateAfter()); - graph.replaceFixedWithFixed(write, memoryWrite); - - memoryWrite.setGuard(write.getGuard()); - } - - private void lowerLoadHubNode(LoadHubNode loadHub) { - StructuredGraph graph = loadHub.graph(); - if (graph.getGuardsStage().ordinal() >= StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal()) { - Kind wordKind = runtime.getTarget().wordKind; - assert loadHub.getKind() == wordKind; - ValueNode object = loadHub.object(); - GuardingNode guard = loadHub.getGuard(); - ValueNode hub = createReadHub(graph, wordKind, object, guard); - graph.replaceFloating(loadHub, hub); + @Override + protected void lowerUnsafeLoadNode(UnsafeLoadNode load, LoweringTool tool) { + StructuredGraph graph = load.graph(); + if (load.getGuardingCondition() == null && graph.getGuardsStage().ordinal() > StructuredGraph.GuardsStage.FLOATING_GUARDS.ordinal() && addReadBarrier(load)) { + unsafeLoadSnippets.lower(load, tool); + } else { + super.lowerUnsafeLoadNode(load, tool); } } @@ -561,88 +275,14 @@ graph.replaceFixed(storeHub, hub); } - private void lowerCommitAllocationNode(CommitAllocationNode commit, LoweringTool tool) { - StructuredGraph graph = commit.graph(); - if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { - ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()]; - BitSet omittedValues = new BitSet(); - int valuePos = 0; - for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { - VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); - int entryCount = virtual.entryCount(); - FixedWithNextNode newObject; - if (virtual instanceof VirtualInstanceNode) { - newObject = graph.add(new NewInstanceNode(virtual.type(), true)); - } else { - newObject = graph.add(new NewArrayNode(((VirtualArrayNode) virtual).componentType(), ConstantNode.forInt(entryCount, graph), true)); - } - graph.addBeforeFixed(commit, newObject); - allocations[objIndex] = newObject; - for (int i = 0; i < entryCount; i++) { - ValueNode value = commit.getValues().get(valuePos); - if (value instanceof VirtualObjectNode) { - value = allocations[commit.getVirtualObjects().indexOf(value)]; - } - if (value == null) { - omittedValues.set(valuePos); - } else if (!(value.isConstant() && value.asConstant().isDefaultForKind())) { - // Constant.illegal is always the defaultForKind, so it is skipped - Kind valueKind = value.getKind(); - Kind entryKind = virtual.entryKind(i); + @Override + protected BarrierType fieldInitializationBarrier(Kind entryKind) { + return (entryKind == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.IMPRECISE : BarrierType.NONE; + } - // Truffle requires some leniency in terms of what can be put where: - Kind accessKind = valueKind.getStackKind() == entryKind.getStackKind() ? entryKind : valueKind; - assert valueKind.getStackKind() == entryKind.getStackKind() || - (valueKind == Kind.Long || valueKind == Kind.Double || (valueKind == Kind.Int && virtual instanceof VirtualArrayNode)); - ConstantLocationNode location; - BarrierType barrierType; - if (virtual instanceof VirtualInstanceNode) { - ResolvedJavaField field = ((VirtualInstanceNode) virtual).field(i); - location = ConstantLocationNode.create(INIT_LOCATION, accessKind, ((HotSpotResolvedJavaField) field).offset(), graph); - barrierType = (entryKind == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.IMPRECISE : BarrierType.NONE; - } else { - location = ConstantLocationNode.create(INIT_LOCATION, accessKind, getArrayBaseOffset(entryKind) + i * getScalingFactor(entryKind), graph); - barrierType = (entryKind == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.PRECISE : BarrierType.NONE; - } - WriteNode write = new WriteNode(newObject, implicitStoreConvert(graph, entryKind, value), location, barrierType, false); - graph.addAfterFixed(newObject, graph.add(write)); - } - valuePos++; - - } - } - valuePos = 0; - - for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { - VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); - int entryCount = virtual.entryCount(); - ValueNode newObject = allocations[objIndex]; - for (int i = 0; i < entryCount; i++) { - if (omittedValues.get(valuePos)) { - ValueNode value = commit.getValues().get(valuePos); - assert value instanceof VirtualObjectNode; - ValueNode allocValue = allocations[commit.getVirtualObjects().indexOf(value)]; - if (!(allocValue.isConstant() && allocValue.asConstant().isDefaultForKind())) { - assert virtual.entryKind(i) == Kind.Object && allocValue.getKind() == Kind.Object; - WriteNode write; - if (virtual instanceof VirtualInstanceNode) { - VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual; - write = new WriteNode(newObject, implicitStoreConvert(graph, Kind.Object, allocValue), createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i), - true), BarrierType.IMPRECISE, false); - } else { - write = new WriteNode(newObject, implicitStoreConvert(graph, Kind.Object, allocValue), createArrayLocation(graph, virtual.entryKind(i), ConstantNode.forInt(i, graph), - true), BarrierType.PRECISE, false); - } - graph.addBeforeFixed(commit, graph.add(write)); - } - } - valuePos++; - } - } - - finishAllocatedObjects(tool, commit, allocations); - graph.removeFixed(commit); - } + @Override + protected BarrierType arrayInitializationBarrier(Kind entryKind) { + return (entryKind == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.PRECISE : BarrierType.NONE; } private void lowerOSRStartNode(OSRStartNode osrStart) { @@ -729,79 +369,6 @@ } } - public static void finishAllocatedObjects(LoweringTool tool, CommitAllocationNode commit, ValueNode[] allocations) { - StructuredGraph graph = commit.graph(); - for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { - FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations[objIndex])); - allocations[objIndex] = anchor; - graph.addBeforeFixed(commit, anchor); - } - for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { - for (MonitorIdNode monitorId : commit.getLocks(objIndex)) { - MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], monitorId)); - graph.addBeforeFixed(commit, enter); - enter.lower(tool); - } - } - for (Node usage : commit.usages().snapshot()) { - AllocatedObjectNode addObject = (AllocatedObjectNode) usage; - int index = commit.getVirtualObjects().indexOf(addObject.getVirtualObject()); - graph.replaceFloating(addObject, allocations[index]); - } - } - - private static LocationNode createLocation(UnsafeAccessNode access) { - return createLocation(access.offset(), access.getLocationIdentity(), access.accessKind()); - } - - private static LocationNode createLocation(ValueNode offsetNode, LocationIdentity locationIdentity, Kind accessKind) { - ValueNode offset = offsetNode; - if (offset.isConstant()) { - long offsetValue = offset.asConstant().asLong(); - return ConstantLocationNode.create(locationIdentity, accessKind, offsetValue, offset.graph()); - } - - long displacement = 0; - int indexScaling = 1; - boolean signExtend = false; - if (offset instanceof SignExtendNode) { - SignExtendNode extend = (SignExtendNode) offset; - if (extend.getResultBits() == 64) { - signExtend = true; - offset = extend.getInput(); - } - } - if (offset instanceof IntegerAddNode) { - IntegerAddNode integerAddNode = (IntegerAddNode) offset; - if (integerAddNode.y() instanceof ConstantNode) { - displacement = integerAddNode.y().asConstant().asLong(); - offset = integerAddNode.x(); - } - } - - if (offset instanceof LeftShiftNode) { - LeftShiftNode leftShiftNode = (LeftShiftNode) offset; - if (leftShiftNode.y() instanceof ConstantNode) { - long shift = leftShiftNode.y().asConstant().asLong(); - if (shift >= 1 && shift <= 3) { - if (shift == 1) { - indexScaling = 2; - } else if (shift == 2) { - indexScaling = 4; - } else { - indexScaling = 8; - } - offset = leftShiftNode.x(); - } - } - } - if (signExtend) { - // If we were using sign extended values before restore the sign extension. - offset = offset.graph().addOrUnique(new SignExtendNode(offset, 64)); - } - return IndexedLocationNode.create(locationIdentity, accessKind, displacement, offset, offset.graph(), indexScaling); - } - private static boolean addReadBarrier(UnsafeLoadNode load) { if (useG1GC() && load.graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS && load.object().getKind() == Kind.Object && load.accessKind() == Kind.Object && !StampTool.isObjectAlwaysNull(load.object())) { @@ -825,7 +392,9 @@ return metaspaceMethod; } - private ValueNode createReadHub(StructuredGraph graph, Kind wordKind, ValueNode object, GuardingNode guard) { + @Override + protected ValueNode createReadHub(StructuredGraph graph, ValueNode object, GuardingNode guard) { + Kind wordKind = target.wordKind; HotSpotVMConfig config = runtime.getConfig(); LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.hubOffset, graph); assert !object.isConstant() || object.asConstant().isNull(); @@ -858,7 +427,9 @@ return graph.add(new WriteNode(object, writeValue, location, BarrierType.NONE, false)); } - private static BarrierType getFieldLoadBarrierType(HotSpotResolvedJavaField loadField) { + @Override + protected BarrierType fieldLoadBarrierType(ResolvedJavaField f) { + HotSpotResolvedJavaField loadField = (HotSpotResolvedJavaField) f; BarrierType barrierType = BarrierType.NONE; if (config().useG1GC && loadField.getKind() == Kind.Object && loadField.getDeclaringClass().mirror() == java.lang.ref.Reference.class && loadField.getName().equals("referent")) { barrierType = BarrierType.PRECISE; @@ -866,144 +437,32 @@ return barrierType; } - private static BarrierType getFieldStoreBarrierType(StoreFieldNode storeField) { - if (storeField.field().getKind() == Kind.Object) { - return BarrierType.IMPRECISE; - } - return BarrierType.NONE; - } - - private static BarrierType getArrayStoreBarrierType(StoreIndexedNode store) { - if (store.elementKind() == Kind.Object) { - return BarrierType.PRECISE; - } - return BarrierType.NONE; - } - - private static BarrierType getUnsafeStoreBarrierType(UnsafeStoreNode store) { - if (store.value().getKind() == Kind.Object) { - ResolvedJavaType type = StampTool.typeOrNull(store.object()); - if (type != null && !type.isArray()) { - return BarrierType.IMPRECISE; - } else { - return BarrierType.PRECISE; - } - } - return BarrierType.NONE; - } - - private static BarrierType getCompareAndSwapBarrierType(CompareAndSwapNode cas) { - if (cas.expected().getKind() == Kind.Object) { - ResolvedJavaType type = StampTool.typeOrNull(cas.object()); - if (type != null && !type.isArray()) { - return BarrierType.IMPRECISE; - } else { - return BarrierType.PRECISE; - } - } - return BarrierType.NONE; - } - - private static BarrierType getAtomicReadAndWriteBarrierType(AtomicReadAndWriteNode n) { - if (n.newValue().getKind() == Kind.Object) { - ResolvedJavaType type = StampTool.typeOrNull(n.object()); - if (type != null && !type.isArray()) { - return BarrierType.IMPRECISE; - } else { - return BarrierType.PRECISE; - } - } - return BarrierType.NONE; - } - - protected static ConstantLocationNode createFieldLocation(StructuredGraph graph, HotSpotResolvedJavaField field, boolean initialization) { - LocationIdentity loc = initialization ? INIT_LOCATION : field; - return ConstantLocationNode.create(loc, field.getKind(), field.offset(), graph); - } - - public int getScalingFactor(Kind kind) { - if (useCompressedOops() && kind == Kind.Object) { - return this.runtime.getTarget().getSizeInBytes(Kind.Int); - } else { - return this.runtime.getTarget().getSizeInBytes(kind); - } + @Override + protected int fieldOffset(ResolvedJavaField f) { + HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) f; + return field.offset(); } @Override - public IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index, boolean initialization) { - LocationIdentity loc = initialization ? INIT_LOCATION : NamedLocationIdentity.getArrayLocation(elementKind); - int scale = getScalingFactor(elementKind); - return IndexedLocationNode.create(loc, elementKind, getArrayBaseOffset(elementKind), index, graph, scale); + public int arrayScalingFactor(Kind kind) { + if (useCompressedOops() && kind == Kind.Object) { + return this.runtime.getTarget().getSizeInBytes(Kind.Int); + } + return super.arrayScalingFactor(kind); } @Override - public ValueNode reconstructArrayIndex(LocationNode location) { - Kind elementKind = location.getValueKind(); - assert location.getLocationIdentity().equals(NamedLocationIdentity.getArrayLocation(elementKind)); - - long base; - ValueNode index; - int scale = getScalingFactor(elementKind); - - if (location instanceof ConstantLocationNode) { - base = ((ConstantLocationNode) location).getDisplacement(); - index = null; - } else if (location instanceof IndexedLocationNode) { - IndexedLocationNode indexedLocation = (IndexedLocationNode) location; - assert indexedLocation.getIndexScaling() == scale; - base = indexedLocation.getDisplacement(); - index = indexedLocation.getIndex(); - } else { - throw GraalInternalError.shouldNotReachHere(); - } - - base -= getArrayBaseOffset(elementKind); - assert base >= 0 && base % scale == 0; - - base /= scale; - assert NumUtil.isInt(base); - - StructuredGraph graph = location.graph(); - if (index == null) { - return ConstantNode.forInt((int) base, graph); - } else { - if (base == 0) { - return index; - } else { - return IntegerArithmeticNode.add(graph, ConstantNode.forInt((int) base, graph), index); - } - } + protected int arrayBaseOffset(Kind kind) { + return HotSpotGraalRuntime.getArrayBaseOffset(kind); } - private GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) { - StructuredGraph g = n.graph(); - ValueNode array = n.array(); - ValueNode arrayLength = readArrayLength(n.graph(), array, tool.getConstantReflection()); - if (arrayLength == null) { - Stamp stamp = StampFactory.positiveInt(); - ReadNode readArrayLength = g.add(new ReadNode(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, runtime.getConfig().arrayLengthOffset, g), stamp, BarrierType.NONE, false)); - g.addBeforeFixed(n, readArrayLength); - readArrayLength.setGuard(createNullCheck(array, readArrayLength, tool)); - arrayLength = readArrayLength; - } - - if (arrayLength.isConstant() && n.index().isConstant()) { - int l = arrayLength.asConstant().asInt(); - int i = n.index().asConstant().asInt(); - if (i >= 0 && i < l) { - // unneeded range check - return null; - } - } - - return tool.createGuard(n, g.unique(new IntegerBelowThanNode(n.index(), arrayLength)), BoundsCheckException, InvalidateReprofile); + @Override + protected int arrayLengthOffset() { + return config().arrayLengthOffset; } - private static GuardingNode createNullCheck(ValueNode object, FixedNode before, LoweringTool tool) { - if (StampTool.isObjectNonNull(object)) { - return null; - } - return tool.createGuard(before, before.graph().unique(new IsNullNode(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true); + @Override + protected LocationIdentity initLocationIdentity() { + return INIT_LOCATION; } - } diff -r 1aaadf06db1b -r 8184c00fefd2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Sat May 24 01:41:56 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Fri May 23 17:33:18 2014 -0700 @@ -36,7 +36,7 @@ void initialize(HotSpotProviders providers, HotSpotVMConfig config); - int getScalingFactor(Kind kind); + int arrayScalingFactor(Kind kind); IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index, boolean initialization); diff -r 1aaadf06db1b -r 8184c00fefd2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Sat May 24 01:41:56 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Fri May 23 17:33:18 2014 -0700 @@ -416,7 +416,7 @@ ConstantNode hub = ConstantNode.forConstant(arrayType.klass(), providers.getMetaAccess(), graph); final int headerSize = HotSpotGraalRuntime.getArrayBaseOffset(elementKind); HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer(); - int log2ElementSize = CodeUtil.log2(lowerer.getScalingFactor(elementKind)); + int log2ElementSize = CodeUtil.log2(lowerer.arrayScalingFactor(elementKind)); Arguments args = new Arguments(allocateArray, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); diff -r 1aaadf06db1b -r 8184c00fefd2 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java Fri May 23 17:33:18 2014 -0700 @@ -0,0 +1,691 @@ +/* + * Copyright (c) 2011, 2014, 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.replacements; + +import static com.oracle.graal.api.code.MemoryBarriers.*; +import static com.oracle.graal.api.meta.DeoptimizationAction.*; +import static com.oracle.graal.api.meta.DeoptimizationReason.*; +import static com.oracle.graal.api.meta.LocationIdentity.*; +import static com.oracle.graal.nodes.java.ArrayLengthNode.*; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.HeapAccess.BarrierType; +import com.oracle.graal.nodes.calc.*; +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.nodes.virtual.*; +import com.oracle.graal.phases.util.*; + +/** + * VM-independent lowerings for standard Java nodes. VM-specific methods are abstract and must be + * implemented by VM-specific subclasses. + */ +public abstract class DefaultJavaLoweringProvider implements LoweringProvider { + + protected final MetaAccessProvider metaAccess; + protected final TargetDescription target; + + private BoxingSnippets.Templates boxingSnippets; + + public DefaultJavaLoweringProvider(MetaAccessProvider metaAccess, TargetDescription target) { + this.metaAccess = metaAccess; + this.target = target; + } + + public void initialize(Providers providers, SnippetReflectionProvider snippetReflection) { + boxingSnippets = new BoxingSnippets.Templates(providers, snippetReflection, target); + } + + @Override + public void lower(Node n, LoweringTool tool) { + if (n instanceof LoadFieldNode) { + lowerLoadFieldNode((LoadFieldNode) n, tool); + } else if (n instanceof StoreFieldNode) { + lowerStoreFieldNode((StoreFieldNode) n, tool); + } else if (n instanceof LoadIndexedNode) { + lowerLoadIndexedNode((LoadIndexedNode) n, tool); + } else if (n instanceof StoreIndexedNode) { + lowerStoreIndexedNode((StoreIndexedNode) n, tool); + } else if (n instanceof ArrayLengthNode) { + lowerArrayLengthNode((ArrayLengthNode) n, tool); + } else if (n instanceof LoadHubNode) { + lowerLoadHubNode((LoadHubNode) n); + } else if (n instanceof CompareAndSwapNode) { + lowerCompareAndSwapNode((CompareAndSwapNode) n); + } else if (n instanceof AtomicReadAndWriteNode) { + lowerAtomicReadAndWriteNode((AtomicReadAndWriteNode) n); + } else if (n instanceof UnsafeLoadNode) { + lowerUnsafeLoadNode((UnsafeLoadNode) n, tool); + } else if (n instanceof UnsafeStoreNode) { + lowerUnsafeStoreNode((UnsafeStoreNode) n); + } else if (n instanceof JavaReadNode) { + lowerJavaReadNode((JavaReadNode) n); + } else if (n instanceof JavaWriteNode) { + lowerJavaWriteNode((JavaWriteNode) n); + } else if (n instanceof CommitAllocationNode) { + lowerCommitAllocationNode((CommitAllocationNode) n, tool); + } else if (n instanceof BoxNode) { + boxingSnippets.lower((BoxNode) n, tool); + } else if (n instanceof UnboxNode) { + boxingSnippets.lower((UnboxNode) n, tool); + } else { + throw GraalInternalError.shouldNotReachHere("Node implementing Lowerable not handled: " + n); + } + } + + protected void lowerLoadFieldNode(LoadFieldNode loadField, LoweringTool tool) { + assert loadField.getKind() != Kind.Illegal; + StructuredGraph graph = loadField.graph(); + ResolvedJavaField field = loadField.field(); + ValueNode object = loadField.isStatic() ? staticFieldBase(graph, field) : loadField.object(); + Stamp loadStamp = loadStamp(loadField.stamp(), field.getKind(), true); + ConstantLocationNode location = createFieldLocation(graph, field, false); + assert location != null : "Field that is loaded must not be eliminated"; + + ReadNode memoryRead = graph.add(new ReadNode(object, location, loadStamp, fieldLoadBarrierType(field), false)); + ValueNode readValue = implicitLoadConvert(graph, field.getKind(), memoryRead); + loadField.replaceAtUsages(readValue); + graph.replaceFixed(loadField, memoryRead); + + memoryRead.setGuard(createNullCheck(object, memoryRead, tool)); + + if (loadField.isVolatile()) { + MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ)); + graph.addBeforeFixed(memoryRead, preMembar); + MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_READ)); + graph.addAfterFixed(memoryRead, postMembar); + } + } + + protected void lowerStoreFieldNode(StoreFieldNode storeField, LoweringTool tool) { + StructuredGraph graph = storeField.graph(); + ResolvedJavaField field = storeField.field(); + ValueNode object = storeField.isStatic() ? staticFieldBase(graph, field) : storeField.object(); + ValueNode value = implicitStoreConvert(graph, storeField.field().getKind(), storeField.value()); + ConstantLocationNode location = createFieldLocation(graph, field, false); + + if (location == null) { + /* Field has been eliminated, so no write necessary. */ + assert !storeField.isVolatile() : "missing memory barriers"; + graph.removeFixed(storeField); + return; + } + WriteNode memoryWrite = graph.add(new WriteNode(object, value, location, fieldStoreBarrierType(storeField.field()), false)); + memoryWrite.setStateAfter(storeField.stateAfter()); + graph.replaceFixedWithFixed(storeField, memoryWrite); + memoryWrite.setGuard(createNullCheck(object, memoryWrite, tool)); + + if (storeField.isVolatile()) { + MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE)); + graph.addBeforeFixed(memoryWrite, preMembar); + MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE)); + graph.addAfterFixed(memoryWrite, postMembar); + } + } + + protected void lowerLoadIndexedNode(LoadIndexedNode loadIndexed, LoweringTool tool) { + StructuredGraph graph = loadIndexed.graph(); + Kind elementKind = loadIndexed.elementKind(); + LocationNode location = createArrayLocation(graph, elementKind, loadIndexed.index(), false); + Stamp loadStamp = loadStamp(loadIndexed.stamp(), elementKind, true); + + ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), location, loadStamp, BarrierType.NONE, false)); + ValueNode readValue = implicitLoadConvert(graph, elementKind, memoryRead); + + memoryRead.setGuard(createBoundsCheck(loadIndexed, tool)); + + loadIndexed.replaceAtUsages(readValue); + graph.replaceFixed(loadIndexed, memoryRead); + } + + protected void lowerStoreIndexedNode(StoreIndexedNode storeIndexed, LoweringTool tool) { + StructuredGraph graph = storeIndexed.graph(); + GuardingNode boundsCheck = createBoundsCheck(storeIndexed, tool); + Kind elementKind = storeIndexed.elementKind(); + LocationNode location = createArrayLocation(graph, elementKind, storeIndexed.index(), false); + + ValueNode value = storeIndexed.value(); + ValueNode array = storeIndexed.array(); + FixedWithNextNode checkCastNode = null; + if (elementKind == Kind.Object && !StampTool.isObjectAlwaysNull(value)) { + /* Array store check. */ + ResolvedJavaType arrayType = StampTool.typeOrNull(array); + if (arrayType != null && StampTool.isExactType(array)) { + ResolvedJavaType elementType = arrayType.getComponentType(); + if (!MetaUtil.isJavaLangObject(elementType)) { + checkCastNode = graph.add(new CheckCastNode(elementType, value, null, true)); + graph.addBeforeFixed(storeIndexed, checkCastNode); + value = checkCastNode; + } + } else { + ValueNode arrayClass = createReadHub(graph, array, boundsCheck); + ValueNode componentHub = createReadArrayComponentHub(graph, arrayClass, storeIndexed); + checkCastNode = graph.add(new CheckCastDynamicNode(componentHub, value, true)); + graph.addBeforeFixed(storeIndexed, checkCastNode); + value = checkCastNode; + } + } + + WriteNode memoryWrite = graph.add(new WriteNode(array, implicitStoreConvert(graph, elementKind, value), location, arrayStoreBarrierType(storeIndexed.elementKind()), false)); + memoryWrite.setGuard(boundsCheck); + memoryWrite.setStateAfter(storeIndexed.stateAfter()); + graph.replaceFixedWithFixed(storeIndexed, memoryWrite); + + if (checkCastNode instanceof Lowerable) { + /* Recursive lowering of the store check node. */ + ((Lowerable) checkCastNode).lower(tool); + } + } + + protected void lowerArrayLengthNode(ArrayLengthNode arrayLengthNode, LoweringTool tool) { + StructuredGraph graph = arrayLengthNode.graph(); + ValueNode array = arrayLengthNode.array(); + ConstantLocationNode location = ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, arrayLengthOffset(), graph); + + ReadNode arrayLengthRead = graph.add(new ReadNode(array, location, StampFactory.positiveInt(), BarrierType.NONE, false)); + arrayLengthRead.setGuard(createNullCheck(array, arrayLengthNode, tool)); + graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead); + } + + protected void lowerLoadHubNode(LoadHubNode loadHub) { + StructuredGraph graph = loadHub.graph(); + if (graph.getGuardsStage().ordinal() < StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal()) { + return; + } + ValueNode hub = createReadHub(graph, loadHub.object(), loadHub.getGuard()); + graph.replaceFloating(loadHub, hub); + } + + protected void lowerCompareAndSwapNode(CompareAndSwapNode cas) { + StructuredGraph graph = cas.graph(); + Kind valueKind = cas.getValueKind(); + LocationNode location = IndexedLocationNode.create(cas.getLocationIdentity(), valueKind, cas.displacement(), cas.offset(), graph, 1); + + ValueNode expectedValue = implicitStoreConvert(graph, valueKind, cas.expected()); + ValueNode newValue = implicitStoreConvert(graph, valueKind, cas.newValue()); + + LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, expectedValue, newValue, compareAndSwapBarrierType(cas), false)); + atomicNode.setStateAfter(cas.stateAfter()); + graph.replaceFixedWithFixed(cas, atomicNode); + } + + protected void lowerAtomicReadAndWriteNode(AtomicReadAndWriteNode n) { + StructuredGraph graph = n.graph(); + Kind valueKind = n.getValueKind(); + LocationNode location = IndexedLocationNode.create(n.getLocationIdentity(), valueKind, 0, n.offset(), graph, 1); + + ValueNode newValue = implicitStoreConvert(graph, valueKind, n.newValue()); + + LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(n.object(), location, newValue, atomicReadAndWriteBarrierType(n), false)); + memoryRead.setStateAfter(n.stateAfter()); + + ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead); + n.replaceAtUsages(readValue); + graph.replaceFixedWithFixed(n, memoryRead); + } + + protected void lowerUnsafeLoadNode(UnsafeLoadNode load, @SuppressWarnings("unused") LoweringTool tool) { + StructuredGraph graph = load.graph(); + if (load.getGuardingCondition() != null) { + ConditionAnchorNode valueAnchorNode = graph.add(new ConditionAnchorNode(load.getGuardingCondition())); + ReadNode memoryRead = createUnsafeRead(graph, load, valueAnchorNode); + graph.replaceFixedWithFixed(load, valueAnchorNode); + graph.addAfterFixed(valueAnchorNode, memoryRead); + } else if (graph.getGuardsStage().ordinal() > StructuredGraph.GuardsStage.FLOATING_GUARDS.ordinal()) { + assert load.getKind() != Kind.Illegal; + ReadNode memoryRead = createUnsafeRead(graph, load, null); + // An unsafe read must not float outside its block otherwise + // it may float above an explicit null check on its object. + memoryRead.setGuard(BeginNode.prevBegin(load)); + graph.replaceFixedWithFixed(load, memoryRead); + } + } + + protected ReadNode createUnsafeRead(StructuredGraph graph, UnsafeLoadNode load, GuardingNode guard) { + boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object); + Kind readKind = load.accessKind(); + LocationNode location = createLocation(load); + Stamp loadStamp = loadStamp(load.stamp(), readKind, compressible); + ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, loadStamp, guard, BarrierType.NONE, false)); + ValueNode readValue = implicitLoadConvert(graph, readKind, memoryRead, compressible); + load.replaceAtUsages(readValue); + return memoryRead; + } + + protected void lowerUnsafeStoreNode(UnsafeStoreNode store) { + StructuredGraph graph = store.graph(); + LocationNode location = createLocation(store); + ValueNode object = store.object(); + boolean compressible = store.value().getKind() == Kind.Object; + Kind valueKind = store.accessKind(); + ValueNode value = implicitStoreConvert(graph, valueKind, store.value(), compressible); + WriteNode write = graph.add(new WriteNode(object, value, location, unsafeStoreBarrierType(store), false)); + write.setStateAfter(store.stateAfter()); + graph.replaceFixedWithFixed(store, write); + } + + protected void lowerJavaReadNode(JavaReadNode read) { + StructuredGraph graph = read.graph(); + Kind valueKind = read.location().getValueKind(); + Stamp loadStamp = loadStamp(read.stamp(), valueKind, read.isCompressible()); + + ReadNode memoryRead = graph.add(new ReadNode(read.object(), read.location(), loadStamp, read.getBarrierType(), false)); + ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead, read.isCompressible()); + memoryRead.setGuard(read.getGuard()); + read.replaceAtUsages(readValue); + graph.replaceFixed(read, memoryRead); + } + + protected void lowerJavaWriteNode(JavaWriteNode write) { + StructuredGraph graph = write.graph(); + Kind valueKind = write.location().getValueKind(); + ValueNode value = implicitStoreConvert(graph, valueKind, write.value(), write.isCompressible()); + + WriteNode memoryWrite = graph.add(new WriteNode(write.object(), value, write.location(), write.getBarrierType(), false, write.isInitialization())); + memoryWrite.setStateAfter(write.stateAfter()); + graph.replaceFixedWithFixed(write, memoryWrite); + memoryWrite.setGuard(write.getGuard()); + } + + protected void lowerCommitAllocationNode(CommitAllocationNode commit, LoweringTool tool) { + StructuredGraph graph = commit.graph(); + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { + List recursiveLowerings = new ArrayList<>(); + + ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()]; + BitSet omittedValues = new BitSet(); + int valuePos = 0; + for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { + VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); + int entryCount = virtual.entryCount(); + AbstractNewObjectNode newObject; + if (virtual instanceof VirtualInstanceNode) { + newObject = graph.add(new NewInstanceNode(virtual.type(), true)); + } else { + newObject = graph.add(new NewArrayNode(((VirtualArrayNode) virtual).componentType(), ConstantNode.forInt(entryCount, graph), true)); + } + recursiveLowerings.add(newObject); + graph.addBeforeFixed(commit, newObject); + allocations[objIndex] = newObject; + for (int i = 0; i < entryCount; i++) { + ValueNode value = commit.getValues().get(valuePos); + if (value instanceof VirtualObjectNode) { + value = allocations[commit.getVirtualObjects().indexOf(value)]; + } + if (value == null) { + omittedValues.set(valuePos); + } else if (!(value.isConstant() && value.asConstant().isDefaultForKind())) { + // Constant.illegal is always the defaultForKind, so it is skipped + Kind valueKind = value.getKind(); + Kind entryKind = virtual.entryKind(i); + + // Truffle requires some leniency in terms of what can be put where: + Kind accessKind = valueKind.getStackKind() == entryKind.getStackKind() ? entryKind : valueKind; + assert valueKind.getStackKind() == entryKind.getStackKind() || + (valueKind == Kind.Long || valueKind == Kind.Double || (valueKind == Kind.Int && virtual instanceof VirtualArrayNode)); + ConstantLocationNode location = null; + BarrierType barrierType = null; + if (virtual instanceof VirtualInstanceNode) { + ResolvedJavaField field = ((VirtualInstanceNode) virtual).field(i); + long offset = fieldOffset(field); + if (offset >= 0) { + location = ConstantLocationNode.create(initLocationIdentity(), accessKind, offset, graph); + barrierType = fieldInitializationBarrier(entryKind); + } + } else { + location = ConstantLocationNode.create(initLocationIdentity(), accessKind, arrayBaseOffset(entryKind) + i * arrayScalingFactor(entryKind), graph); + barrierType = arrayInitializationBarrier(entryKind); + } + if (location != null) { + WriteNode write = new WriteNode(newObject, implicitStoreConvert(graph, entryKind, value), location, barrierType, false); + graph.addAfterFixed(newObject, graph.add(write)); + } + } + valuePos++; + + } + } + valuePos = 0; + + for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { + VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); + int entryCount = virtual.entryCount(); + ValueNode newObject = allocations[objIndex]; + for (int i = 0; i < entryCount; i++) { + if (omittedValues.get(valuePos)) { + ValueNode value = commit.getValues().get(valuePos); + assert value instanceof VirtualObjectNode; + ValueNode allocValue = allocations[commit.getVirtualObjects().indexOf(value)]; + if (!(allocValue.isConstant() && allocValue.asConstant().isDefaultForKind())) { + assert virtual.entryKind(i) == Kind.Object && allocValue.getKind() == Kind.Object; + LocationNode location; + BarrierType barrierType; + if (virtual instanceof VirtualInstanceNode) { + VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual; + location = createFieldLocation(graph, virtualInstance.field(i), true); + barrierType = BarrierType.IMPRECISE; + } else { + location = createArrayLocation(graph, virtual.entryKind(i), ConstantNode.forInt(i, graph), true); + barrierType = BarrierType.PRECISE; + } + if (location != null) { + WriteNode write = new WriteNode(newObject, implicitStoreConvert(graph, Kind.Object, allocValue), location, barrierType, false); + graph.addBeforeFixed(commit, graph.add(write)); + } + } + } + valuePos++; + } + } + + finishAllocatedObjects(tool, commit, allocations); + graph.removeFixed(commit); + + for (AbstractNewObjectNode recursiveLowering : recursiveLowerings) { + recursiveLowering.lower(tool); + } + } + } + + public static void finishAllocatedObjects(LoweringTool tool, CommitAllocationNode commit, ValueNode[] allocations) { + StructuredGraph graph = commit.graph(); + for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { + FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations[objIndex])); + allocations[objIndex] = anchor; + graph.addBeforeFixed(commit, anchor); + } + for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { + for (MonitorIdNode monitorId : commit.getLocks(objIndex)) { + MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], monitorId)); + graph.addBeforeFixed(commit, enter); + enter.lower(tool); + } + } + for (Node usage : commit.usages().snapshot()) { + AllocatedObjectNode addObject = (AllocatedObjectNode) usage; + int index = commit.getVirtualObjects().indexOf(addObject.getVirtualObject()); + graph.replaceFloating(addObject, allocations[index]); + } + } + + protected BarrierType fieldLoadBarrierType(@SuppressWarnings("unused") ResolvedJavaField field) { + return BarrierType.NONE; + } + + protected BarrierType fieldStoreBarrierType(ResolvedJavaField field) { + if (field.getKind() == Kind.Object) { + return BarrierType.IMPRECISE; + } + return BarrierType.NONE; + } + + protected BarrierType arrayStoreBarrierType(Kind elementKind) { + if (elementKind == Kind.Object) { + return BarrierType.PRECISE; + } + return BarrierType.NONE; + } + + protected BarrierType fieldInitializationBarrier(Kind entryKind) { + return entryKind == Kind.Object ? BarrierType.IMPRECISE : BarrierType.NONE; + } + + protected BarrierType arrayInitializationBarrier(Kind entryKind) { + return entryKind == Kind.Object ? BarrierType.PRECISE : BarrierType.NONE; + } + + protected BarrierType unsafeStoreBarrierType(UnsafeStoreNode store) { + return storeBarrierType(store.object(), store.value()); + } + + protected BarrierType compareAndSwapBarrierType(CompareAndSwapNode cas) { + return storeBarrierType(cas.object(), cas.expected()); + } + + protected BarrierType atomicReadAndWriteBarrierType(AtomicReadAndWriteNode n) { + return storeBarrierType(n.object(), n.newValue()); + } + + protected BarrierType storeBarrierType(ValueNode object, ValueNode value) { + if (value.getKind() == Kind.Object) { + ResolvedJavaType type = StampTool.typeOrNull(object); + if (type != null && !type.isArray()) { + return BarrierType.IMPRECISE; + } else { + return BarrierType.PRECISE; + } + } + return BarrierType.NONE; + } + + protected abstract int fieldOffset(ResolvedJavaField field); + + protected abstract ValueNode staticFieldBase(StructuredGraph graph, ResolvedJavaField field); + + protected abstract int arrayLengthOffset(); + + protected abstract int arrayBaseOffset(Kind elementKind); + + public int arrayScalingFactor(Kind elementKind) { + return target.getSizeInBytes(elementKind); + } + + protected abstract LocationIdentity initLocationIdentity(); + + protected Stamp loadStamp(Stamp stamp, Kind kind, @SuppressWarnings("unused") boolean compressible) { + switch (kind) { + case Boolean: + case Byte: + return StampTool.narrowingConversion(stamp, 8); + case Char: + case Short: + return StampTool.narrowingConversion(stamp, 16); + } + return stamp; + } + + public ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value) { + return implicitLoadConvert(graph, kind, value, true); + + } + + protected ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value, @SuppressWarnings("unused") boolean compressible) { + switch (kind) { + case Byte: + case Short: + return graph.unique(new SignExtendNode(value, 32)); + case Boolean: + case Char: + return graph.unique(new ZeroExtendNode(value, 32)); + } + return value; + } + + public ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value) { + return implicitStoreConvert(graph, kind, value, true); + } + + protected ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value, @SuppressWarnings("unused") boolean compressible) { + switch (kind) { + case Boolean: + case Byte: + return graph.unique(new NarrowNode(value, 8)); + case Char: + case Short: + return graph.unique(new NarrowNode(value, 16)); + } + return value; + } + + protected abstract ValueNode createReadHub(StructuredGraph graph, ValueNode object, GuardingNode guard); + + protected abstract ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor); + + protected ConstantLocationNode createFieldLocation(StructuredGraph graph, ResolvedJavaField field, boolean initialization) { + int offset = fieldOffset(field); + if (offset >= 0) { + LocationIdentity loc = initialization ? initLocationIdentity() : field; + return ConstantLocationNode.create(loc, field.getKind(), offset, graph); + } else { + return null; + } + } + + protected LocationNode createLocation(UnsafeAccessNode access) { + return createLocation(access.offset(), access.getLocationIdentity(), access.accessKind()); + } + + protected LocationNode createLocation(ValueNode offsetNode, LocationIdentity locationIdentity, Kind accessKind) { + ValueNode offset = offsetNode; + if (offset.isConstant()) { + long offsetValue = offset.asConstant().asLong(); + return ConstantLocationNode.create(locationIdentity, accessKind, offsetValue, offset.graph()); + } + + long displacement = 0; + int indexScaling = 1; + boolean signExtend = false; + if (offset instanceof SignExtendNode) { + SignExtendNode extend = (SignExtendNode) offset; + if (extend.getResultBits() == 64) { + signExtend = true; + offset = extend.getInput(); + } + } + if (offset instanceof IntegerAddNode) { + IntegerAddNode integerAddNode = (IntegerAddNode) offset; + if (integerAddNode.y() instanceof ConstantNode) { + displacement = integerAddNode.y().asConstant().asLong(); + offset = integerAddNode.x(); + } + } + + if (offset instanceof LeftShiftNode) { + LeftShiftNode leftShiftNode = (LeftShiftNode) offset; + if (leftShiftNode.y() instanceof ConstantNode) { + long shift = leftShiftNode.y().asConstant().asLong(); + if (shift >= 1 && shift <= 3) { + if (shift == 1) { + indexScaling = 2; + } else if (shift == 2) { + indexScaling = 4; + } else { + indexScaling = 8; + } + offset = leftShiftNode.x(); + } + } + } + if (signExtend) { + // If we were using sign extended values before restore the sign extension. + offset = offset.graph().addOrUnique(new SignExtendNode(offset, 64)); + } + return IndexedLocationNode.create(locationIdentity, accessKind, displacement, offset, offset.graph(), indexScaling); + } + + public IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index, boolean initialization) { + LocationIdentity loc = initialization ? initLocationIdentity() : NamedLocationIdentity.getArrayLocation(elementKind); + return IndexedLocationNode.create(loc, elementKind, arrayBaseOffset(elementKind), index, graph, arrayScalingFactor(elementKind)); + } + + protected GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) { + StructuredGraph graph = n.graph(); + ValueNode array = n.array(); + ValueNode arrayLength = readArrayLength(n.graph(), array, tool.getConstantReflection()); + if (arrayLength == null) { + Stamp stamp = StampFactory.positiveInt(); + ReadNode readArrayLength = graph.add(new ReadNode(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, arrayLengthOffset(), graph), stamp, BarrierType.NONE, false)); + graph.addBeforeFixed(n, readArrayLength); + readArrayLength.setGuard(createNullCheck(array, readArrayLength, tool)); + arrayLength = readArrayLength; + } + + if (arrayLength.isConstant() && n.index().isConstant()) { + int l = arrayLength.asConstant().asInt(); + int i = n.index().asConstant().asInt(); + if (i >= 0 && i < l) { + // unneeded range check + return null; + } + } + + return tool.createGuard(n, graph.unique(new IntegerBelowThanNode(n.index(), arrayLength)), BoundsCheckException, InvalidateReprofile); + } + + protected GuardingNode createNullCheck(ValueNode object, FixedNode before, LoweringTool tool) { + if (StampTool.isObjectNonNull(object)) { + return null; + } + return tool.createGuard(before, before.graph().unique(new IsNullNode(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true); + } + + @Override + public ValueNode reconstructArrayIndex(LocationNode location) { + Kind elementKind = location.getValueKind(); + assert location.getLocationIdentity().equals(NamedLocationIdentity.getArrayLocation(elementKind)); + + long base; + ValueNode index; + int scale = arrayScalingFactor(elementKind); + + if (location instanceof ConstantLocationNode) { + base = ((ConstantLocationNode) location).getDisplacement(); + index = null; + } else if (location instanceof IndexedLocationNode) { + IndexedLocationNode indexedLocation = (IndexedLocationNode) location; + assert indexedLocation.getIndexScaling() == scale; + base = indexedLocation.getDisplacement(); + index = indexedLocation.getIndex(); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + + base -= arrayBaseOffset(elementKind); + assert base >= 0 && base % scale == 0; + + base /= scale; + assert NumUtil.isInt(base); + + StructuredGraph graph = location.graph(); + if (index == null) { + return ConstantNode.forInt((int) base, graph); + } else { + if (base == 0) { + return index; + } else { + return IntegerArithmeticNode.add(graph, ConstantNode.forInt((int) base, graph), index); + } + } + } +}