changeset 18159:2d6646ca59be

Merge.
author Doug Simon <doug.simon@oracle.com>
date Wed, 22 Oct 2014 20:33:19 +0200
parents 31ad929e1afd (current diff) 95f8dd398214 (diff)
children 30e03a7f9110
files
diffstat 34 files changed, 313 insertions(+), 95 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Wed Oct 22 20:33:19 2014 +0200
@@ -133,10 +133,11 @@
             List<? extends AbstractBlock<?>> codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blockMap.blocks.size(), blockMap.startBlock);
             LIR lir = new LIR(cfg, linearScanOrder, codeEmittingOrder);
 
-            FrameMap frameMap = backend.newFrameMap(null);
+            RegisterConfig registerConfig = null;
+            FrameMapBuilder frameMapBuilder = backend.newFrameMapBuilder(registerConfig);
             TargetDescription target = backend.getTarget();
             CallingConvention cc = CodeUtil.getCallingConvention(backend.getProviders().getCodeCache(), CallingConvention.Type.JavaCallee, method, false);
-            this.lirGenRes = backend.newLIRGenerationResult(lir, frameMap, method, null);
+            this.lirGenRes = backend.newLIRGenerationResult(lir, frameMapBuilder, method, null);
             this.gen = backend.newLIRGenerator(cc, lirGenRes);
             this.lirBuilder = backend.newBytecodeLIRBuilder(gen, this);
 
@@ -158,7 +159,7 @@
                 try (Scope s = Debug.scope("Allocator")) {
 
                     if (backend.shouldAllocateRegisters()) {
-                        LinearScan.allocate(target, lir, frameMap);
+                        LinearScan.allocate(target, lirGenRes);
                     }
                 } catch (Throwable e) {
                     throw Debug.handle(e);
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java	Wed Oct 22 20:33:19 2014 +0200
@@ -453,7 +453,7 @@
             sig[i] = node.arguments().get(i).stamp().javaType(gen.getMetaAccess());
         }
 
-        Value[] parameters = visitInvokeArguments(gen.getResult().getFrameMap().getRegisterConfig().getCallingConvention(CallingConvention.Type.JavaCall, null, sig, gen.target(), false),
+        Value[] parameters = visitInvokeArguments(gen.getResult().getFrameMapBuilder().getRegisterConfig().getCallingConvention(CallingConvention.Type.JavaCall, null, sig, gen.target(), false),
                         node.arguments());
         append(new AMD64BreakpointOp(parameters));
     }
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Wed Oct 22 20:33:19 2014 +0200
@@ -919,7 +919,7 @@
 
     private StackSlot getTempSlot(LIRKind kind) {
         if (tmpStackSlot == null) {
-            tmpStackSlot = getResult().getFrameMap().allocateSpillSlot(kind);
+            tmpStackSlot = getResult().getFrameMapBuilder().allocateSpillSlot(kind);
         }
         return tmpStackSlot;
     }
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java	Wed Oct 22 20:33:19 2014 +0200
@@ -58,7 +58,7 @@
             sig[i] = node.arguments().get(i).stamp().javaType(gen.getMetaAccess());
         }
 
-        Value[] parameters = visitInvokeArguments(gen.getResult().getFrameMap().getRegisterConfig().getCallingConvention(CallingConvention.Type.JavaCall, null, sig, gen.target(), false),
+        Value[] parameters = visitInvokeArguments(gen.getResult().getFrameMapBuilder().getRegisterConfig().getCallingConvention(CallingConvention.Type.JavaCall, null, sig, gen.target(), false),
                         node.arguments());
         append(new SPARCBreakpointOp(parameters));
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Oct 22 20:33:19 2014 +0200
@@ -242,8 +242,8 @@
             throw Debug.handle(e);
         }
         try (Scope ds = Debug.scope("BackEnd", lir)) {
-            FrameMap frameMap = backend.newFrameMap(registerConfig);
-            LIRGenerationResult lirGenRes = backend.newLIRGenerationResult(lir, frameMap, graph.method(), stub);
+            FrameMapBuilder frameMapBuilder = backend.newFrameMapBuilder(registerConfig);
+            LIRGenerationResult lirGenRes = backend.newLIRGenerationResult(lir, frameMapBuilder, graph.method(), stub);
             LIRGeneratorTool lirGen = backend.newLIRGenerator(cc, lirGenRes);
             NodeLIRBuilderTool nodeLirGen = backend.newNodeLIRBuilder(graph, lirGen);
 
@@ -269,7 +269,10 @@
 
             try (Scope s = Debug.scope("Allocator", nodeLirGen)) {
                 if (backend.shouldAllocateRegisters()) {
-                    LinearScan.allocate(target, lir, frameMap);
+                    LinearScan.allocate(target, lirGenRes);
+                } else {
+                    // build frame map for targets that do not allocate registers
+                    lirGenRes.buildFrameMap();
                 }
             } catch (Throwable e) {
                 throw Debug.handle(e);
@@ -279,7 +282,7 @@
                 EdgeMoveOptimizer.optimize(lir);
                 ControlFlowOptimizer.optimize(lir, codeEmittingOrder);
                 if (lirGen.canEliminateRedundantMoves()) {
-                    RedundantMoveElimination.optimize(lir, frameMap);
+                    RedundantMoveElimination.optimize(lir, frameMapBuilder);
                 }
                 NullCheckOptimizer.optimize(lir, target.implicitNullCheckLimit);
 
@@ -295,7 +298,8 @@
 
     public static void emitCode(Backend backend, Assumptions assumptions, LIRGenerationResult lirGenRes, CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner,
                     CompilationResultBuilderFactory factory) {
-        CompilationResultBuilder crb = backend.newCompilationResultBuilder(lirGenRes, compilationResult, factory);
+        FrameMap frameMap = lirGenRes.getFrameMap();
+        CompilationResultBuilder crb = backend.newCompilationResultBuilder(lirGenRes, frameMap, compilationResult, factory);
         backend.emitCode(crb, lirGenRes.getLIR(), installedCodeOwner);
         crb.finish();
         if (!assumptions.isEmpty()) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Wed Oct 22 20:33:19 2014 +0200
@@ -45,6 +45,7 @@
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.StandardOp.MoveOp;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.util.*;
@@ -58,8 +59,9 @@
 public final class LinearScan {
 
     final TargetDescription target;
+    final LIRGenerationResult res;
     final LIR ir;
-    final FrameMap frameMap;
+    final FrameMapBuilder frameMapBuilder;
     final RegisterAttributes[] registerAttributes;
     final Register[] registers;
 
@@ -159,12 +161,13 @@
      */
     private final int firstVariableNumber;
 
-    public LinearScan(TargetDescription target, LIR ir, FrameMap frameMap) {
+    public LinearScan(TargetDescription target, LIRGenerationResult res) {
         this.target = target;
-        this.ir = ir;
-        this.frameMap = frameMap;
+        this.res = res;
+        this.ir = res.getLIR();
+        this.frameMapBuilder = res.getFrameMapBuilder();
         this.sortedBlocks = ir.linearScanOrder();
-        this.registerAttributes = frameMap.getRegisterConfig().getAttributesMap();
+        this.registerAttributes = frameMapBuilder.getRegisterConfig().getAttributesMap();
 
         this.registers = target.arch.getRegisters();
         this.firstVariableNumber = registers.length;
@@ -257,7 +260,7 @@
         } else if (interval.spillSlot() != null) {
             interval.assignLocation(interval.spillSlot());
         } else {
-            StackSlot slot = frameMap.allocateSpillSlot(interval.kind());
+            StackSlot slot = frameMapBuilder.allocateSpillSlot(interval.kind());
             interval.setSpillSlot(slot);
             interval.assignLocation(slot);
         }
@@ -1168,7 +1171,7 @@
             };
 
             // create a list with all caller-save registers (cpu, fpu, xmm)
-            Register[] callerSaveRegs = frameMap.getRegisterConfig().getCallerSaveRegisters();
+            Register[] callerSaveRegs = frameMapBuilder.getRegisterConfig().getCallerSaveRegisters();
 
             // iterate all blocks in reverse order
             for (int i = blockCount() - 1; i >= 0; i--) {
@@ -1632,7 +1635,7 @@
      * Visits all intervals for a frame state. The frame state use this information to build the OOP
      * maps.
      */
-    private void markFrameLocations(IntervalWalker iw, LIRInstruction op, LIRFrameState info) {
+    private void markFrameLocations(IntervalWalker iw, LIRInstruction op, LIRFrameState info, FrameMap frameMap) {
         Debug.log("creating oop map at opId %d", op.id());
 
         // walk before the current operation . intervals that start at
@@ -1730,8 +1733,9 @@
     }
 
     private void computeDebugInfo(IntervalWalker iw, final LIRInstruction op, LIRFrameState info) {
+        FrameMap frameMap = res.getFrameMap();
         info.initDebugInfo(frameMap, !op.destroysCallerSavedRegisters() || !callKillsRegisters);
-        markFrameLocations(iw, op, info);
+        markFrameLocations(iw, op, info, frameMap);
 
         info.forEachState(op, this::debugInfoProcedure);
         info.finish(op, frameMap);
@@ -1800,8 +1804,8 @@
         }
     }
 
-    public static void allocate(TargetDescription target, LIR lir, FrameMap frameMap) {
-        new LinearScan(target, lir, frameMap).allocate();
+    public static void allocate(TargetDescription target, LIRGenerationResult res) {
+        new LinearScan(target, res).allocate();
     }
 
     private void allocate() {
@@ -1844,7 +1848,8 @@
             }
 
             try (Scope s = Debug.scope("DebugInfo")) {
-                frameMap.finish();
+                // build frame map
+                res.buildFrameMap();
 
                 printIntervals("After register allocation");
                 printLir("After register allocation", true);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Wed Oct 22 20:33:19 2014 +0200
@@ -79,7 +79,7 @@
 
         // If all allocatable registers are caller saved, then no registers are live across a call
         // site. The register allocator can save time not trying to find a register at a call site.
-        allocator.callKillsRegisters = allocator.frameMap.getRegisterConfig().areAllAllocatableRegistersCallerSaved();
+        allocator.callKillsRegisters = allocator.frameMapBuilder.getRegisterConfig().areAllAllocatableRegistersCallerSaved();
 
         moveResolver = new MoveResolver(allocator);
         spillIntervals = Util.uncheckedCast(new List[allocator.registers.length]);
@@ -773,7 +773,7 @@
     }
 
     void initVarsForAlloc(Interval interval) {
-        availableRegs = allocator.frameMap.getRegisterConfig().getAllocatableRegisters(interval.kind().getPlatformKind());
+        availableRegs = allocator.frameMapBuilder.getRegisterConfig().getAllocatableRegisters(interval.kind().getPlatformKind());
     }
 
     static boolean isMove(LIRInstruction op, Interval from, Interval to) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/MoveResolver.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/MoveResolver.java	Wed Oct 22 20:33:19 2014 +0200
@@ -280,7 +280,7 @@
                 // one stack slot to another can happen (not allowed by LIRAssembler
                 StackSlot spillSlot = fromInterval.spillSlot();
                 if (spillSlot == null) {
-                    spillSlot = allocator.frameMap.allocateSpillSlot(spillInterval.kind());
+                    spillSlot = allocator.frameMapBuilder.allocateSpillSlot(spillInterval.kind());
                     fromInterval.setSpillSlot(spillSlot);
                 }
                 spillInterval.assignLocation(spillSlot);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java	Wed Oct 22 20:33:19 2014 +0200
@@ -225,7 +225,7 @@
             op.visitEachInput(useConsumer);
             // invalidate all caller save registers at calls
             if (op.destroysCallerSavedRegisters()) {
-                for (Register r : allocator.frameMap.getRegisterConfig().getCallerSaveRegisters()) {
+                for (Register r : allocator.frameMapBuilder.getRegisterConfig().getCallerSaveRegisters()) {
                     statePut(inputState, r.asValue(), null);
                 }
             }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Wed Oct 22 20:33:19 2014 +0200
@@ -456,9 +456,9 @@
     @Override
     public void emitInvoke(Invoke x) {
         LoweredCallTargetNode callTarget = (LoweredCallTargetNode) x.callTarget();
-        CallingConvention invokeCc = gen.getResult().getFrameMap().getRegisterConfig().getCallingConvention(callTarget.callType(), x.asNode().stamp().javaType(gen.getMetaAccess()),
+        CallingConvention invokeCc = gen.getResult().getFrameMapBuilder().getRegisterConfig().getCallingConvention(callTarget.callType(), x.asNode().stamp().javaType(gen.getMetaAccess()),
                         callTarget.signature(), gen.target(), false);
-        gen.getResult().getFrameMap().callsMethod(invokeCc);
+        gen.getResult().getFrameMapBuilder().callsMethod(invokeCc);
 
         Value[] parameters = visitInvokeArguments(invokeCc, callTarget.arguments());
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Wed Oct 22 20:33:19 2014 +0200
@@ -71,11 +71,13 @@
      * The given registerConfig is optional, in case null is passed the default RegisterConfig from
      * the CodeCacheProvider will be used.
      */
-    public abstract FrameMap newFrameMap(RegisterConfig registerConfig);
+    public abstract FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig);
+
+    public abstract FrameMap newFrameMap(FrameMapBuilder frameMapBuilder);
 
     public abstract LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes);
 
-    public abstract LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, ResolvedJavaMethod method, Object stub);
+    public abstract LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMapBuilder frameMapBuilder, ResolvedJavaMethod method, Object stub);
 
     public abstract NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen);
 
@@ -95,7 +97,8 @@
     /**
      * Creates the object used to fill in the details of a given compilation result.
      */
-    public abstract CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenResult, CompilationResult compilationResult, CompilationResultBuilderFactory factory);
+    public abstract CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenResult, FrameMap frameMap, CompilationResult compilationResult,
+                    CompilationResultBuilderFactory factory);
 
     public abstract boolean shouldAllocateRegisters();
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Wed Oct 22 20:33:19 2014 +0200
@@ -66,8 +66,13 @@
     }
 
     @Override
-    public FrameMap newFrameMap(RegisterConfig registerConfig) {
-        return new AMD64FrameMap(getCodeCache(), registerConfig);
+    public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
+        return new FrameMapBuilderImpl(this::newFrameMap, getCodeCache(), registerConfig);
+    }
+
+    @Override
+    public FrameMap newFrameMap(FrameMapBuilder frameMapBuilder) {
+        return new AMD64FrameMap(getCodeCache(), frameMapBuilder.getRegisterConfig());
     }
 
     @Override
@@ -76,8 +81,8 @@
     }
 
     @Override
-    public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, ResolvedJavaMethod method, Object stub) {
-        return new AMD64HotSpotLIRGenerationResult(lir, frameMap, stub);
+    public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMapBuilder frameMapBuilder, ResolvedJavaMethod method, Object stub) {
+        return new AMD64HotSpotLIRGenerationResult(lir, frameMapBuilder, stub);
     }
 
     @Override
@@ -206,7 +211,7 @@
     }
 
     @Override
-    public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRen, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
+    public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRen, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
         // Omit the frame if the method:
         // - has no spill slots or other slots allocated during register allocation
         // - has no callee-saved registers
@@ -214,7 +219,6 @@
         // - has no deoptimization points
         // - makes no foreign calls (which require an aligned stack)
         AMD64HotSpotLIRGenerationResult gen = (AMD64HotSpotLIRGenerationResult) lirGenRen;
-        FrameMap frameMap = gen.getFrameMap();
         LIR lir = gen.getLIR();
         assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame";
         boolean omitFrame = CanOmitFrame.getValue() && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame() && !gen.hasForeignCall();
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java	Wed Oct 22 20:33:19 2014 +0200
@@ -46,8 +46,8 @@
      */
     private Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = new HashMap<>();
 
-    public AMD64HotSpotLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) {
-        super(lir, frameMap);
+    public AMD64HotSpotLIRGenerationResult(LIR lir, FrameMapBuilder frameMapBuilder, Object stub) {
+        super(lir, frameMapBuilder);
         this.stub = stub;
     }
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Oct 22 20:33:19 2014 +0200
@@ -86,7 +86,7 @@
 
         public SaveRbp(NoOp placeholder) {
             this.placeholder = placeholder;
-            this.reservedSlot = getResult().getFrameMap().allocateSpillSlot(LIRKind.value(Kind.Long));
+            this.reservedSlot = getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(Kind.Long));
             assert reservedSlot.getRawOffset() == -16 : reservedSlot.getRawOffset();
         }
 
@@ -100,7 +100,7 @@
             if (useStack) {
                 dst = reservedSlot;
             } else {
-                getResult().getFrameMap().freeSpillSlot(reservedSlot);
+                getResult().getFrameMapBuilder().freeSpillSlot(reservedSlot);
                 dst = newVariable(LIRKind.value(Kind.Long));
             }
 
@@ -229,7 +229,7 @@
         for (int i = 0; i < savedRegisters.length; i++) {
             PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory());
             assert kind != Kind.Illegal;
-            StackSlot spillSlot = getResult().getFrameMap().allocateSpillSlot(LIRKind.value(kind));
+            StackSlot spillSlot = getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(kind));
             savedRegisterLocations[i] = spillSlot;
         }
         return emitSaveRegisters(savedRegisters, savedRegisterLocations, supportsRemove);
@@ -259,7 +259,7 @@
         if (destroysRegisters) {
             if (getStub() != null) {
                 if (getStub().preservesRegisters()) {
-                    Register[] savedRegisters = getResult().getFrameMap().getRegisterConfig().getAllocatableRegisters();
+                    Register[] savedRegisters = getResult().getFrameMapBuilder().getRegisterConfig().getAllocatableRegisters();
                     save = emitSaveAllRegisters(savedRegisters, true);
                 }
             }
@@ -337,7 +337,7 @@
     }
 
     protected boolean zapRegisters() {
-        Register[] zappedRegisters = getResult().getFrameMap().getRegisterConfig().getAllocatableRegisters();
+        Register[] zappedRegisters = getResult().getFrameMapBuilder().getRegisterConfig().getAllocatableRegisters();
         Constant[] zapValues = new Constant[zappedRegisters.length];
         for (int i = 0; i < zappedRegisters.length; i++) {
             PlatformKind kind = target().arch.getLargestStorableKind(zappedRegisters[i].getRegisterCategory());
@@ -356,7 +356,7 @@
     @Override
     public void emitCCall(long address, CallingConvention nativeCallingConvention, Value[] args, int numberOfFloatingPointArguments) {
         Value[] argLocations = new Value[args.length];
-        getResult().getFrameMap().callsMethod(nativeCallingConvention);
+        getResult().getFrameMapBuilder().callsMethod(nativeCallingConvention);
         // TODO(mg): in case a native function uses floating point varargs, the ABI requires that
         // RAX contains the length of the varargs
         AllocatableValue numberOfFloatingPointArgumentsRegister = AMD64.rax.asValue();
@@ -411,7 +411,7 @@
         boolean hasDebugInfo = getResult().getLIR().hasDebugInfo();
         AllocatableValue savedRbp = saveRbp.finalize(hasDebugInfo);
         if (hasDebugInfo) {
-            ((AMD64HotSpotLIRGenerationResult) getResult()).setDeoptimizationRescueSlot(getResult().getFrameMap().allocateSpillSlot(LIRKind.value(Kind.Long)));
+            ((AMD64HotSpotLIRGenerationResult) getResult()).setDeoptimizationRescueSlot(getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(Kind.Long)));
         }
 
         for (AMD64HotSpotEpilogueOp op : epilogueOps) {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java	Wed Oct 22 20:33:19 2014 +0200
@@ -105,7 +105,7 @@
 
     @Override
     protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeMap<Value> nodeOperands) {
-        HotSpotLockStack lockStack = new HotSpotLockStack(gen.getResult().getFrameMap(), LIRKind.value(Kind.Long));
+        HotSpotLockStack lockStack = new HotSpotLockStack(gen.getResult().getFrameMapBuilder(), LIRKind.value(Kind.Long));
         return new HotSpotDebugInfoBuilder(nodeOperands, lockStack);
     }
 
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Wed Oct 22 20:33:19 2014 +0200
@@ -383,12 +383,17 @@
     private static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args, int numTlabs, int allocBytesPerWorkitem, int[] oopMapArray)
                     throws InvalidInstalledCodeException;
 
+    @Override
+    public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
+        return new FrameMapBuilderImpl(this::newFrameMap, getCodeCache(), registerConfig);
+    }
+
     /**
      * Use the HSAIL register set when the compilation target is HSAIL.
      */
     @Override
-    public FrameMap newFrameMap(RegisterConfig registerConfig) {
-        return new HSAILFrameMap(getCodeCache(), registerConfig);
+    public FrameMap newFrameMap(FrameMapBuilder frameMapBuilder) {
+        return new HSAILFrameMap(getCodeCache(), frameMapBuilder.getRegisterConfig());
     }
 
     @Override
@@ -397,8 +402,8 @@
     }
 
     @Override
-    public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, ResolvedJavaMethod method, Object stub) {
-        return new HSAILHotSpotLIRGenerationResult(lir, frameMap);
+    public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMapBuilder frameMapBuilder, ResolvedJavaMethod method, Object stub) {
+        return new HSAILHotSpotLIRGenerationResult(lir, frameMapBuilder);
     }
 
     @Override
@@ -467,8 +472,7 @@
     }
 
     @Override
-    public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
-        FrameMap frameMap = lirGenRes.getFrameMap();
+    public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
         Assembler masm = createAssembler(frameMap);
         HotSpotFrameContext frameContext = new HotSpotFrameContext();
         // save lirGen for later use by setHostGraph
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerationResult.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerationResult.java	Wed Oct 22 20:33:19 2014 +0200
@@ -32,8 +32,8 @@
 
     private List<DeoptimizingOp> deopts = new ArrayList<>();
 
-    public HSAILHotSpotLIRGenerationResult(LIR lir, FrameMap frameMap) {
-        super(lir, frameMap);
+    public HSAILHotSpotLIRGenerationResult(LIR lir, FrameMapBuilder frameMapBuilder) {
+        super(lir, frameMapBuilder);
     }
 
     public List<DeoptimizingOp> getDeopts() {
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Wed Oct 22 20:33:19 2014 +0200
@@ -49,8 +49,8 @@
 import com.oracle.graal.lir.StandardOp.LabelOp;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.lir.ptx.PTXControlFlow.PTXPredicatedLIRInstruction;
 import com.oracle.graal.lir.ptx.*;
-import com.oracle.graal.lir.ptx.PTXControlFlow.PTXPredicatedLIRInstruction;
 import com.oracle.graal.lir.ptx.PTXMemOp.LoadReturnAddrOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -156,8 +156,13 @@
     private static native long getLaunchKernelAddress();
 
     @Override
-    public FrameMap newFrameMap(RegisterConfig registerConfig) {
-        return new PTXFrameMap(getCodeCache(), registerConfig);
+    public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
+        return new FrameMapBuilderImpl(this::newFrameMap, getCodeCache(), registerConfig);
+    }
+
+    @Override
+    public FrameMap newFrameMap(FrameMapBuilder frameMapBuilder) {
+        return new PTXFrameMap(getCodeCache(), frameMapBuilder.getRegisterConfig());
     }
 
     /**
@@ -329,13 +334,12 @@
     }
 
     @Override
-    public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
+    public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
         // Omit the frame of the method:
         // - has no spill slots or other slots allocated during register allocation
         // - has no callee-saved registers
         // - has no incoming arguments passed on the stack
         // - has no instructions with debug info
-        FrameMap frameMap = lirGenRes.getFrameMap();
         Assembler masm = createAssembler(frameMap);
         PTXFrameContext frameContext = new PTXFrameContext();
         CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult);
@@ -344,8 +348,8 @@
     }
 
     @Override
-    public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, ResolvedJavaMethod method, Object stub) {
-        return new LIRGenerationResultBase(lir, frameMap);
+    public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMapBuilder frameMapBuilder, ResolvedJavaMethod method, Object stub) {
+        return new LIRGenerationResultBase(lir, frameMapBuilder);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Wed Oct 22 20:33:19 2014 +0200
@@ -72,8 +72,13 @@
     }
 
     @Override
-    public FrameMap newFrameMap(RegisterConfig registerConfig) {
-        return new SPARCFrameMap(getProviders().getCodeCache(), registerConfig);
+    public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
+        return new FrameMapBuilderImpl(this::newFrameMap, getCodeCache(), registerConfig);
+    }
+
+    @Override
+    public FrameMap newFrameMap(FrameMapBuilder frameMapBuilder) {
+        return new SPARCFrameMap(getCodeCache(), frameMapBuilder.getRegisterConfig());
     }
 
     @Override
@@ -82,8 +87,8 @@
     }
 
     @Override
-    public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, ResolvedJavaMethod method, Object stub) {
-        return new SPARCHotSpotLIRGenerationResult(lir, frameMap, stub);
+    public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMapBuilder frameMapBuilder, ResolvedJavaMethod method, Object stub) {
+        return new SPARCHotSpotLIRGenerationResult(lir, frameMapBuilder, stub);
     }
 
     @Override
@@ -179,9 +184,8 @@
     }
 
     @Override
-    public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
+    public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
         SPARCHotSpotLIRGenerationResult gen = (SPARCHotSpotLIRGenerationResult) lirGenRes;
-        FrameMap frameMap = gen.getFrameMap();
         LIR lir = gen.getLIR();
         assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame";
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java	Wed Oct 22 20:33:19 2014 +0200
@@ -46,8 +46,8 @@
      */
     private Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = new HashMap<>();
 
-    public SPARCHotSpotLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) {
-        super(lir, frameMap);
+    public SPARCHotSpotLIRGenerationResult(LIR lir, FrameMapBuilder frameMapBuilder, Object stub) {
+        super(lir, frameMapBuilder);
         this.stub = stub;
     }
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Wed Oct 22 20:33:19 2014 +0200
@@ -97,7 +97,7 @@
         super.beforeRegisterAllocation();
         boolean hasDebugInfo = getResult().getLIR().hasDebugInfo();
         if (hasDebugInfo) {
-            ((SPARCHotSpotLIRGenerationResult) getResult()).setDeoptimizationRescueSlot(getResult().getFrameMap().allocateSpillSlot(LIRKind.value(Kind.Long)));
+            ((SPARCHotSpotLIRGenerationResult) getResult()).setDeoptimizationRescueSlot(getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(Kind.Long)));
         }
     }
 
@@ -276,7 +276,7 @@
         for (int i = 0; i < savedRegisters.length; i++) {
             PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory());
             assert kind != Kind.Illegal;
-            StackSlot spillSlot = getResult().getFrameMap().allocateSpillSlot(LIRKind.value(kind));
+            StackSlot spillSlot = getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(kind));
             savedRegisterLocations[i] = spillSlot;
         }
         return emitSaveRegisters(savedRegisters, savedRegisterLocations, false);
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java	Wed Oct 22 20:33:19 2014 +0200
@@ -53,7 +53,7 @@
 
     @Override
     protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeMap<Value> nodeOperands) {
-        HotSpotLockStack lockStack = new HotSpotLockStack(gen.getResult().getFrameMap(), LIRKind.value(Kind.Long));
+        HotSpotLockStack lockStack = new HotSpotLockStack(gen.getResult().getFrameMapBuilder(), LIRKind.value(Kind.Long));
         return new HotSpotDebugInfoBuilder(nodeOperands, lockStack);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLockStack.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLockStack.java	Wed Oct 22 20:33:19 2014 +0200
@@ -35,11 +35,11 @@
 public class HotSpotLockStack {
 
     private StackSlot[] locks;
-    private final FrameMap frameMap;
+    private final FrameMapBuilder frameMapBuilder;
     private final LIRKind slotKind;
 
-    public HotSpotLockStack(FrameMap frameMap, LIRKind slotKind) {
-        this.frameMap = frameMap;
+    public HotSpotLockStack(FrameMapBuilder frameMapBuilder, LIRKind slotKind) {
+        this.frameMapBuilder = frameMapBuilder;
         this.slotKind = slotKind;
     }
 
@@ -53,7 +53,7 @@
             locks = Arrays.copyOf(locks, lockDepth + 1);
         }
         if (locks[lockDepth] == null) {
-            locks[lockDepth] = frameMap.allocateSpillSlot(slotKind);
+            locks[lockDepth] = frameMapBuilder.allocateSpillSlot(slotKind);
         }
         return locks[lockDepth];
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java	Wed Oct 22 20:33:19 2014 +0200
@@ -63,7 +63,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        StackSlot array = gen.getLIRGeneratorTool().getResult().getFrameMap().allocateStackSlots(slots, objects, null);
+        StackSlot array = gen.getLIRGeneratorTool().getResult().getFrameMapBuilder().allocateStackSlots(slots, objects, null);
         Value result = gen.getLIRGeneratorTool().emitAddress(array);
         gen.setResult(this, result);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java	Wed Oct 22 20:33:19 2014 +0200
@@ -58,7 +58,7 @@
         int size = rank * 4;
         int wordSize = lirGen.target().wordSize;
         int slots = roundUp(size, wordSize) / wordSize;
-        StackSlot array = lirGen.getResult().getFrameMap().allocateStackSlots(slots, new BitSet(0), null);
+        StackSlot array = lirGen.getResult().getFrameMapBuilder().allocateStackSlots(slots, new BitSet(0), null);
         Value result = lirGen.emitAddress(array);
         gen.setResult(this, result);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java	Wed Oct 22 20:33:19 2014 +0200
@@ -48,7 +48,7 @@
     @Override
     public void generate(NodeLIRBuilderTool gen) {
         assert graph().getNodes().filter(MonitorCounterNode.class).count() == 1 : "monitor counters not canonicalized to single instance";
-        StackSlot counter = gen.getLIRGeneratorTool().getResult().getFrameMap().allocateStackSlots(1, new BitSet(0), null);
+        StackSlot counter = gen.getLIRGeneratorTool().getResult().getFrameMapBuilder().allocateStackSlots(1, new BitSet(0), null);
         Value result = gen.getLIRGeneratorTool().emitAddress(counter);
         gen.setResult(this, result);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Wed Oct 22 20:33:19 2014 +0200
@@ -69,7 +69,7 @@
         boolean isStatic = method.isStatic();
 
         JavaType[] signature = method.getSignature().toParameterTypes(isStatic ? null : method.getDeclaringClass());
-        CallingConvention cc = lirGen.getResult().getFrameMap().getRegisterConfig().getCallingConvention(CallingConvention.Type.JavaCall, null, signature, lirGen.target(), false);
+        CallingConvention cc = lirGen.getResult().getFrameMapBuilder().getRegisterConfig().getCallingConvention(CallingConvention.Type.JavaCall, null, signature, lirGen.target(), false);
         List<ValueNode> parameters = new ArrayList<>();
         for (int i = 0, slot = 0; i < cc.getArgumentCount(); i++, slot += HIRFrameStateBuilder.stackSlots(frameState.localAt(slot).getKind())) {
             parameters.add(frameState.localAt(slot));
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java	Wed Oct 22 20:33:19 2014 +0200
@@ -45,7 +45,7 @@
     public SPARCByteSwapOp(LIRGeneratorTool tool, Value result, Value input) {
         this.result = result;
         this.input = input;
-        this.tmpSlot = tool.getResult().getFrameMap().allocateSpillSlot(LIRKind.value(Kind.Long));
+        this.tmpSlot = tool.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(Kind.Long));
         this.tempIndex = tool.newVariable(LIRKind.value(Kind.Long));
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMapBuilder.java	Wed Oct 22 20:33:19 2014 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2014, 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.lir;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+
+/**
+ * A {@link FrameMapBuilder} is used to collect all information necessary to
+ * {@linkplain #buildFrameMap() create} a {@link FrameMap}.
+ */
+public interface FrameMapBuilder {
+
+    /**
+     * Reserves a spill slot in the frame of the method being compiled. The returned slot is aligned
+     * on its natural alignment, i.e., an 8-byte spill slot is aligned at an 8-byte boundary, unless
+     * overridden by a subclass.
+     *
+     * @param kind The kind of the spill slot to be reserved.
+     * @return A spill slot denoting the reserved memory area.
+     */
+    StackSlot allocateSpillSlot(LIRKind kind);
+
+    /**
+     * Reserves a number of contiguous slots in the frame of the method being compiled. If the
+     * requested number of slots is 0, this method returns {@code null}.
+     *
+     * @param slots the number of slots to reserve
+     * @param objects specifies the indexes of the object pointer slots. The caller is responsible
+     *            for guaranteeing that each such object pointer slot is initialized before any
+     *            instruction that uses a reference map. Without this guarantee, the garbage
+     *            collector could see garbage object values.
+     * @param outObjectStackSlots if non-null, the object pointer slots allocated are added to this
+     *            list
+     * @return the first reserved stack slot (i.e., at the lowest address)
+     */
+    StackSlot allocateStackSlots(int slots, BitSet objects, List<StackSlot> outObjectStackSlots);
+
+    RegisterConfig getRegisterConfig();
+
+    /**
+     * Frees a spill slot that was obtained via {@link #allocateSpillSlot(LIRKind)} such that it can
+     * be reused for the next allocation request for the same kind of slot.
+     */
+    void freeSpillSlot(StackSlot slot);
+
+    /**
+     * Informs the frame map that the compiled code calls a particular method, which may need stack
+     * space for outgoing arguments.
+     *
+     * @param cc The calling convention for the called method.
+     */
+    void callsMethod(CallingConvention cc);
+
+    /**
+     * Creates a {@linkplain FrameMap} based on the information collected by this
+     * {@linkplain FrameMapBuilder}.
+     */
+    FrameMap buildFrameMap();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMapBuilderImpl.java	Wed Oct 22 20:33:19 2014 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, 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.lir;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+
+/**
+ * A simple forwarder to {@link FrameMap}.
+ */
+public class FrameMapBuilderImpl implements FrameMapBuilder {
+
+    @FunctionalInterface
+    public interface FrameMapFactory {
+        FrameMap newFrameMap(FrameMapBuilder frameMapBuilder);
+    }
+
+    private final FrameMap frameMap;
+    private final RegisterConfig registerConfig;
+
+    public FrameMapBuilderImpl(FrameMapFactory factory, CodeCacheProvider codeCache, RegisterConfig registerConfig) {
+        this.registerConfig = registerConfig == null ? codeCache.getRegisterConfig() : registerConfig;
+        this.frameMap = factory.newFrameMap(this);
+    }
+
+    public StackSlot allocateSpillSlot(LIRKind kind) {
+        return frameMap.allocateSpillSlot(kind);
+    }
+
+    public StackSlot allocateStackSlots(int slots, BitSet objects, List<StackSlot> outObjectStackSlots) {
+        return frameMap.allocateStackSlots(slots, objects, outObjectStackSlots);
+    }
+
+    public RegisterConfig getRegisterConfig() {
+        return registerConfig;
+    }
+
+    public void freeSpillSlot(StackSlot slot) {
+        frameMap.freeSpillSlot(slot);
+    }
+
+    public void callsMethod(CallingConvention cc) {
+        frameMap.callsMethod(cc);
+    }
+
+    public FrameMap buildFrameMap() {
+        frameMap.finish();
+        return frameMap;
+    }
+
+}
\ No newline at end of file
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java	Wed Oct 22 20:33:19 2014 +0200
@@ -39,9 +39,9 @@
  */
 public final class RedundantMoveElimination {
 
-    public static void optimize(LIR lir, FrameMap frameMap) {
+    public static void optimize(LIR lir, FrameMapBuilder frameMapBuilder) {
         RedundantMoveElimination redundantMoveElimination = new RedundantMoveElimination();
-        redundantMoveElimination.doOptimize(lir, frameMap);
+        redundantMoveElimination.doOptimize(lir, frameMapBuilder);
     }
 
     /**
@@ -101,11 +101,11 @@
     /**
      * The main method doing the elimination of redundant moves.
      */
-    private void doOptimize(LIR lir, FrameMap frameMap) {
+    private void doOptimize(LIR lir, FrameMapBuilder frameMapBuilder) {
 
         try (Indent indent = Debug.logAndIndent("eliminate redundant moves")) {
 
-            callerSaveRegs = frameMap.getRegisterConfig().getCallerSaveRegisters();
+            callerSaveRegs = frameMapBuilder.getRegisterConfig().getCallerSaveRegisters();
 
             initBlockData(lir);
 
@@ -113,7 +113,7 @@
             // Unallocatable registers should never be optimized.
             eligibleRegs = new int[numRegs];
             Arrays.fill(eligibleRegs, -1);
-            for (Register reg : frameMap.getRegisterConfig().getAllocatableRegisters()) {
+            for (Register reg : frameMapBuilder.getRegisterConfig().getAllocatableRegisters()) {
                 if (reg.number < numRegs) {
                     eligibleRegs[reg.number] = reg.number;
                 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResult.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResult.java	Wed Oct 22 20:33:19 2014 +0200
@@ -25,6 +25,28 @@
 import com.oracle.graal.lir.*;
 
 public interface LIRGenerationResult {
+
+    /**
+     * Returns the {@link FrameMapBuilder} for collecting the information to build a
+     * {@link FrameMap}.
+     *
+     * This method can only be used prior calling {@link #buildFrameMap()}.
+     */
+    FrameMapBuilder getFrameMapBuilder();
+
+    /**
+     * Creates a {@link FrameMap} out of the {@link FrameMapBuilder}. This method should only be
+     * called once. After calling it, {@link #getFrameMapBuilder()} can no longer be used.
+     *
+     * @see FrameMapBuilder#buildFrameMap()
+     */
+    void buildFrameMap();
+
+    /**
+     * Returns the {@link FrameMap} associated with this {@link LIRGenerationResult}.
+     *
+     * This method can only be called after {@link #buildFrameMap()}.
+     */
     FrameMap getFrameMap();
 
     LIR getLIR();
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResultBase.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResultBase.java	Wed Oct 22 20:33:19 2014 +0200
@@ -26,15 +26,16 @@
 
 public class LIRGenerationResultBase implements LIRGenerationResult {
     private final LIR lir;
-    private final FrameMap frameMap;
+    private final FrameMapBuilder frameMapBuilder;
+    private FrameMap frameMap;
     /**
      * Records whether the code being generated makes at least one foreign call.
      */
     private boolean hasForeignCall;
 
-    public LIRGenerationResultBase(LIR lir, FrameMap frameMap) {
+    public LIRGenerationResultBase(LIR lir, FrameMapBuilder frameMapBuilder) {
         this.lir = lir;
-        this.frameMap = frameMap;
+        this.frameMapBuilder = frameMapBuilder;
     }
 
     public LIR getLIR() {
@@ -52,7 +53,18 @@
         this.hasForeignCall = hasForeignCall;
     }
 
-    public final FrameMap getFrameMap() {
+    public final FrameMapBuilder getFrameMapBuilder() {
+        assert frameMap == null : "getFrameMapBuilder() can only be used before calling buildFrameMap()!";
+        return frameMapBuilder;
+    }
+
+    public void buildFrameMap() {
+        assert frameMap == null : "buildFrameMap() can only be called once!";
+        frameMap = frameMapBuilder.buildFrameMap();
+    }
+
+    public FrameMap getFrameMap() {
+        assert frameMap != null : "getFrameMap() can only be used after calling buildFrameMap()!";
         return frameMap;
     }
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java	Wed Oct 22 20:20:42 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java	Wed Oct 22 20:33:19 2014 +0200
@@ -107,7 +107,7 @@
 
     @Override
     public RegisterAttributes attributes(Register register) {
-        return res.getFrameMap().getRegisterConfig().getAttributesMap()[register.number];
+        return res.getFrameMapBuilder().getRegisterConfig().getAttributesMap()[register.number];
     }
 
     @Override
@@ -173,7 +173,7 @@
      *         {@code kind}
      */
     public AllocatableValue resultOperandFor(LIRKind kind) {
-        return res.getFrameMap().getRegisterConfig().getReturnRegister((Kind) kind.getPlatformKind()).asValue(kind);
+        return res.getFrameMapBuilder().getRegisterConfig().getReturnRegister((Kind) kind.getPlatformKind()).asValue(kind);
     }
 
     public void append(LIRInstruction op) {
@@ -273,7 +273,7 @@
 
         // move the arguments into the correct location
         CallingConvention linkageCc = linkage.getOutgoingCallingConvention();
-        res.getFrameMap().callsMethod(linkageCc);
+        res.getFrameMapBuilder().callsMethod(linkageCc);
         assert linkageCc.getArgumentCount() == args.length : "argument count mismatch";
         Value[] argLocations = new Value[args.length];
         for (int i = 0; i < args.length; i++) {