changeset 15889:8184c00fefd2

Factor out VM-independent part of DefaultHotSpotLoweringProvider into DefaultJavaLoweringProvider
author Christian Wimmer <christian.wimmer@oracle.com>
date Fri, 23 May 2014 17:33:18 -0700
parents 1aaadf06db1b
children f4510fd9e8b3
files graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLoweringProvider.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLoweringProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java
diffstat 11 files changed, 785 insertions(+), 633 deletions(-) [+]
line wrap: on
line diff
--- 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) {
--- 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
--- 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);
--- 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);
     }
 
--- 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);
--- 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);
--- 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
--- 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;
     }
-
 }
--- 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);
 
--- 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);
--- /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<AbstractNewObjectNode> 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);
+            }
+        }
+    }
+}