changeset 4181:319860ae697a

Simplify FrameMap: make offsets of spill slots and outgoing parameters independent so that they can be allocated at the same time, eliminating the separate phases. This makes the separate StackBlock unnecesary. Change CiStackSlot to use byte offsets instead of spill slot index. This makes CiTarget.spillSlotSize unnecessary.
author Christian Wimmer <Christian.Wimmer@Oracle.com>
date Mon, 02 Jan 2012 14:16:08 -0800
parents 383c1272cd1f
children de7b3e7ae528
files graal/com.oracle.max.cri/src/com/sun/cri/ci/CiRegisterConfig.java graal/com.oracle.max.cri/src/com/sun/cri/ci/CiStackSlot.java graal/com.oracle.max.cri/src/com/sun/cri/ci/CiTarget.java graal/com.oracle.max.cri/src/com/sun/cri/ri/RiRuntime.java graal/com.oracle.max.criutils/src/com/oracle/max/criutils/CompilationPrinter.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/MoveResolver.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/SpillSlots.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/MoveResolver.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/asm/TargetMethodAssembler.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/DebugInfoBuilder.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/FrameMap.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRDebugInfo.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/Backend.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Backend.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64CompilerStubEmitter.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64MoveOpcode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64StandardOpcode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64XirOpcode.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/CompilerImpl.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotRegisterConfig.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotRuntime.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotTarget.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/nodes/TailcallNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/spi/LIRGeneratorTool.java src/share/vm/graal/graalCodeInstaller.cpp src/share/vm/graal/graalJavaAccess.cpp src/share/vm/graal/graalJavaAccess.hpp
diffstat 34 files changed, 395 insertions(+), 680 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.cri/src/com/sun/cri/ci/CiRegisterConfig.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.cri/src/com/sun/cri/ci/CiRegisterConfig.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -193,8 +193,7 @@
 
         int currentGeneral = 0;
         int currentXMM = 0;
-        int firstStackIndex = (stackArg0Offsets[type.ordinal()]) / target.spillSlotSize;
-        int currentStackIndex = firstStackIndex;
+        int currentStackOffset = stackArg0Offsets[type.ordinal()];
 
         for (int i = 0; i < parameters.length; i++) {
             final CiKind kind = parameters[i];
@@ -226,12 +225,12 @@
             }
 
             if (locations[i] == null) {
-                locations[i] = CiStackSlot.get(kind.stackKind(), currentStackIndex, !type.out);
-                currentStackIndex += target.spillSlots(kind);
+                locations[i] = CiStackSlot.get(kind.stackKind(), currentStackOffset, !type.out);
+                currentStackOffset += Math.max(target.sizeInBytes(kind), target.wordSize);
             }
         }
 
-        return new CiCallingConvention(locations, (currentStackIndex - firstStackIndex) * target.spillSlotSize);
+        return new CiCallingConvention(locations, currentStackOffset);
     }
 
     public CiRegister[] getCallingConventionRegisters(Type type, RegisterFlag flag) {
--- a/graal/com.oracle.max.cri/src/com/sun/cri/ci/CiStackSlot.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.cri/src/com/sun/cri/ci/CiStackSlot.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,79 +22,88 @@
  */
 package com.sun.cri.ci;
 
+import static com.sun.cri.ci.CiKind.*;
+
 /**
  * Represents a compiler spill slot or an outgoing stack-based argument in a method's frame
  * or an incoming stack-based argument in a method's {@linkplain #inCallerFrame() caller's frame}.
  */
 public final class CiStackSlot extends CiValue {
 
-    /**
-     *
-     */
     private static final long serialVersionUID = -7725071921307318433L;
 
-    /**
-     * @see CiStackSlot#index()
-     */
-    private final int index;
-
-    /**
-     * Gets a {@link CiStackSlot} instance representing a stack slot in the current frame
-     * at a given index holding a value of a given kind.
-     *
-     * @param kind the kind of the value stored in the stack slot
-     * @param index the index of the stack slot
-     */
-    public static CiStackSlot get(CiKind kind, int index) {
-        return get(kind, index, false);
-    }
+    private final int offset;
+    private final boolean addFrameSize;
 
     /**
      * Gets a {@link CiStackSlot} instance representing a stack slot at a given index
      * holding a value of a given kind.
      *
-     * @param kind the kind of the value stored in the stack slot
-     * @param index the index of the stack slot
-     * @param inCallerFrame specifies if the slot is in the current frame or in the caller's frame
+     * @param kind The kind of the value stored in the stack slot.
+     * @param offset The offset of the stack slot (in bytes)
+     * @param inCallerFrame Specifies if the offset is relative to the stack pointer,
+     *        or the beginning of the frame (stack pointer + total frame size).
      */
-    public static CiStackSlot get(CiKind kind, int index, boolean inCallerFrame) {
+    public static CiStackSlot get(CiKind kind, int offset, boolean addFrameSize) {
         assert kind.stackKind() == kind;
-        CiStackSlot[][] cache = inCallerFrame ? CALLER_FRAME_CACHE : CACHE;
-        CiStackSlot[] slots = cache[kind.ordinal()];
-        CiStackSlot slot;
-        if (index < slots.length) {
-            slot = slots[index];
-        } else {
-            slot = new CiStackSlot(kind, inCallerFrame ? -(index + 1) : index);
+        assert addFrameSize || offset >= 0;
+
+        if (offset % CACHE_GRANULARITY == 0) {
+            CiStackSlot[][] cache;
+            int index = offset / CACHE_GRANULARITY;
+            if (!addFrameSize) {
+                cache = OUT_CACHE;
+            } else if (offset >= 0) {
+                cache = IN_CACHE;
+            } else {
+                cache = SPILL_CACHE;
+                index = -index;
+            }
+            CiStackSlot[] slots = cache[kind.ordinal()];
+            if (index < slots.length) {
+                CiStackSlot slot = slots[index];
+                assert slot.kind == kind && slot.offset == offset && slot.addFrameSize == addFrameSize;
+                return slot;
+            }
         }
-        assert slot.inCallerFrame() == inCallerFrame;
-        return slot;
+        return new CiStackSlot(kind, offset, addFrameSize);
     }
 
     /**
-     * Private constructor to enforce use of {@link #get(CiKind, int)} so that the
-     * shared instance {@linkplain #CACHE cache} is used.
+     * Private constructor to enforce use of {@link #get()} so that a cache can be used.
      */
-    private CiStackSlot(CiKind kind, int index) {
+    private CiStackSlot(CiKind kind, int offset, boolean addFrameSize) {
         super(kind);
-        this.index = index;
+        this.offset = offset;
+        this.addFrameSize = addFrameSize;
     }
 
     /**
-     * Gets the index of this stack slot. If this is a spill slot or outgoing stack argument to a call,
-     * then the index is relative to the current frame pointer. Otherwise this is an incoming stack
-     * argument and the index is relative to the caller frame pointer.
-     *
-     * @return the index of this slot
-     * @see #inCallerFrame()
+     * Gets the offset of this stack slot, relative to the stack pointer.
+     * @return The offset of this slot (in bytes).
      */
-    public int index() {
-        return index < 0 ? -(index + 1) : index;
+    public int offset(int totalFrameSize) {
+        assert totalFrameSize > 0 || !addFrameSize;
+        int result = offset + (addFrameSize ? totalFrameSize : 0);
+        assert result >= 0;
+        return result;
+    }
+
+    public boolean inCallerFrame() {
+        return addFrameSize && offset >= 0;
+    }
+
+    public int rawOffset() {
+        return offset;
+    }
+
+    public boolean rawAddFrameSize() {
+        return addFrameSize;
     }
 
     @Override
     public int hashCode() {
-        return kind.ordinal() + index;
+        return kind.ordinal() ^ (offset << 4) ^ (addFrameSize ? 15 : 0);
     }
 
     @Override
@@ -104,7 +113,7 @@
         }
         if (o instanceof CiStackSlot) {
             CiStackSlot l = (CiStackSlot) o;
-            return l.kind == kind && l.index == index;
+            return l.kind == kind && l.offset == offset && l.addFrameSize == addFrameSize;
         }
         return false;
     }
@@ -116,29 +125,31 @@
         }
         if (o instanceof CiStackSlot) {
             CiStackSlot l = (CiStackSlot) o;
-            return l.index == index;
+            return l.offset == offset && l.addFrameSize == addFrameSize;
         }
         return false;
     }
 
     @Override
     public String toString() {
-        return (inCallerFrame() ? "caller-stack" : "stack:") + index() + kindSuffix();
-    }
-
-    /**
-     * Determines if this is a stack slot in the caller's frame.
-     */
-    public boolean inCallerFrame() {
-        return index < 0;
+        String s;
+        if (!addFrameSize) {
+            s = "out:";
+        } else if (offset >= 0) {
+            s = "in:";
+        } else {
+            s = "spill:";
+        }
+        return s + offset + kindSuffix();
     }
 
     /**
      * Gets this stack slot used to pass an argument from the perspective of a caller.
      */
     public CiStackSlot asOutArg() {
-        if (inCallerFrame()) {
-            return get(kind, index(), false);
+        assert offset >= 0;
+        if (addFrameSize) {
+            return get(kind, offset, false);
         }
         return this;
     }
@@ -147,54 +158,31 @@
      * Gets this stack slot used to pass an argument from the perspective of a callee.
      */
     public CiStackSlot asInArg() {
-        if (!inCallerFrame()) {
-            return get(kind, index(), true);
+        assert offset >= 0;
+        if (!addFrameSize) {
+            return get(kind, offset, true);
         }
         return this;
     }
 
-    /**
-     * Default size of the cache to generate per kind.
-     */
-    private static final int CACHE_PER_KIND_SIZE = 100;
 
-    private static final int CALLER_FRAME_CACHE_PER_KIND_SIZE = 10;
+    private static final int CACHE_GRANULARITY = 8;
+    private static final int SPILL_CACHE_PER_KIND_SIZE = 100;
+    private static final int PARAM_CACHE_PER_KIND_SIZE = 10;
 
-    /**
-     * A cache of {@linkplain #inCallerFrame() non-caller-frame} stack slots.
-     */
-    private static final CiStackSlot[][] CACHE = makeCache(CACHE_PER_KIND_SIZE, false);
+    private static final CiStackSlot[][] SPILL_CACHE = makeCache(SPILL_CACHE_PER_KIND_SIZE, -1, true);
+    private static final CiStackSlot[][] IN_CACHE = makeCache(PARAM_CACHE_PER_KIND_SIZE, 1, true);
+    private static final CiStackSlot[][] OUT_CACHE = makeCache(PARAM_CACHE_PER_KIND_SIZE, 1, false);
 
-    /**
-     * A cache of {@linkplain #inCallerFrame() caller-frame} stack slots.
-     */
-    private static final CiStackSlot[][] CALLER_FRAME_CACHE = makeCache(CALLER_FRAME_CACHE_PER_KIND_SIZE, true);
-
-    private static CiStackSlot[][] makeCache(int cachePerKindSize, boolean inCallerFrame) {
+    private static CiStackSlot[][] makeCache(int cachePerKindSize, int sign, boolean addFrameSize) {
         CiStackSlot[][] cache = new CiStackSlot[CiKind.VALUES.length][];
-        cache[CiKind.Illegal.ordinal()] = makeCacheForKind(CiKind.Illegal, cachePerKindSize, inCallerFrame);
-        cache[CiKind.Int.ordinal()]     = makeCacheForKind(CiKind.Int, cachePerKindSize, inCallerFrame);
-        cache[CiKind.Long.ordinal()]    = makeCacheForKind(CiKind.Long, cachePerKindSize, inCallerFrame);
-        cache[CiKind.Float.ordinal()]   = makeCacheForKind(CiKind.Float, cachePerKindSize, inCallerFrame);
-        cache[CiKind.Double.ordinal()]  = makeCacheForKind(CiKind.Double, cachePerKindSize, inCallerFrame);
-        cache[CiKind.Object.ordinal()]  = makeCacheForKind(CiKind.Object, cachePerKindSize, inCallerFrame);
-        cache[CiKind.Jsr.ordinal()]     = makeCacheForKind(CiKind.Jsr, cachePerKindSize, inCallerFrame);
+        for (CiKind kind : new CiKind[] {Illegal, Int, Long, Float, Double, Object, Jsr}) {
+            CiStackSlot[] slots = new CiStackSlot[cachePerKindSize];
+            for (int i = 0; i < cachePerKindSize; i++) {
+                slots[i] = new CiStackSlot(kind, sign * i * CACHE_GRANULARITY, addFrameSize);
+            }
+            cache[kind.ordinal()] = slots;
+        }
         return cache;
     }
-
-    /**
-     * Creates an array of {@code CiStackSlot} objects for a given {@link CiKind}.
-     * The {@link #index} values range from {@code 0} to {@code count - 1}.
-     *
-     * @param kind the {@code CiKind} of the stack slot
-     * @param count the size of the array to create
-     * @return the generated {@code CiStackSlot} array
-     */
-    private static CiStackSlot[] makeCacheForKind(CiKind kind, int count, boolean inCallerFrame) {
-        CiStackSlot[] slots = new CiStackSlot[count];
-        for (int i = 0; i < count; ++i) {
-            slots[i] = new CiStackSlot(kind, inCallerFrame ? -(i + 1) : i);
-        }
-        return slots;
-    }
 }
--- a/graal/com.oracle.max.cri/src/com/sun/cri/ci/CiTarget.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.cri/src/com/sun/cri/ci/CiTarget.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,21 +41,11 @@
     public final boolean isMP;
 
     /**
-     * The number of {@link #spillSlotSize spill slots} required per kind.
-     */
-    private final int[] spillSlotsPerKindMap;
-
-    /**
      * Specifies if this target supports encoding objects inline in the machine code.
      */
     public final boolean inlineObjects;
 
     /**
-     * The spill slot size for values that occupy 1 {@linkplain CiKind#sizeInSlots() Java slot}.
-     */
-    public final int spillSlotSize;
-
-    /**
      * The machine word size on this target.
      */
     public final int wordSize;
@@ -107,7 +97,6 @@
 
     public CiTarget(CiArchitecture arch,
              boolean isMP,
-             int spillSlotSize,
              int stackAlignment,
              int pageSize,
              int cacheAlignment,
@@ -117,7 +106,6 @@
         this.arch = arch;
         this.pageSize = pageSize;
         this.isMP = isMP;
-        this.spillSlotSize = spillSlotSize;
         this.wordSize = arch.wordSize;
         if (wordSize == 8) {
             this.wordKind = CiKind.Long;
@@ -128,19 +116,8 @@
         this.stackBias = 0; // TODO: configure with param once SPARC port exists
         this.cacheAlignment = cacheAlignment;
         this.inlineObjects = inlineObjects;
-        this.spillSlotsPerKindMap = new int[CiKind.values().length];
         this.debugInfoDoubleWordsInSecondSlot = debugInfoDoubleWordsInSecondSlot;
         this.invokeSnippetAfterArguments = invokeSnippetAfterArguments;
-
-        for (CiKind k : CiKind.values()) {
-            // initialize the number of spill slots required for each kind
-            int size = sizeInBytes(k);
-            int slots = 0;
-            while (slots * spillSlotSize < size) {
-                slots++;
-            }
-            spillSlotsPerKindMap[k.ordinal()] = slots;
-        }
     }
 
     /**
@@ -168,15 +145,6 @@
     }
 
     /**
-     * Gets the number of spill slots for a specified kind in this target.
-     * @param kind the kind for which to get the spill slot count
-     * @return the number of spill slots for {@code kind}
-     */
-    public int spillSlots(CiKind kind) {
-        return spillSlotsPerKindMap[kind.ordinal()];
-    }
-
-    /**
      * Aligns the given frame size (without return instruction pointer) to the stack
      * alignment size and return the aligned size (without return instruction pointer).
      * @param frameSize the initial frame size to be aligned
--- a/graal/com.oracle.max.cri/src/com/sun/cri/ri/RiRuntime.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.cri/src/com/sun/cri/ri/RiRuntime.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -183,6 +183,13 @@
     int getCustomStackAreaSize();
 
     /**
+     * Minimum size of the stack area reserved for outgoing parameters. This area is reserved in all cases, even when
+     * the compiled method has no regular call instructions.
+     * @return the minimum size of the outgoing parameter area in bytes
+     */
+    int getMinimumOutgoingSize();
+
+    /**
      * Gets the length of the array that is wrapped in a CiConstant object.
      */
     int getArrayLength(CiConstant array);
--- a/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/CompilationPrinter.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/CompilationPrinter.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -109,7 +109,7 @@
         if (registerRefMap != null) {
             sb.append("reg-ref-map:");
             for (int reg = registerRefMap.nextSetBit(0); reg >= 0; reg = registerRefMap.nextSetBit(reg + 1)) {
-                sb.append(' ').append(arch == null ? "reg" + reg : arch.registers[reg]);
+                sb.append(' ').append(arch == null ? "r" + reg : arch.registers[reg]);
             }
             sb.append("\n");
         }
@@ -117,7 +117,7 @@
         if (frameRefMap != null) {
             sb.append("frame-ref-map:");
             for (int reg = frameRefMap.nextSetBit(0); reg >= 0; reg = frameRefMap.nextSetBit(reg + 1)) {
-                sb.append(' ').append(CiStackSlot.get(CiKind.Object, reg));
+                sb.append(' ').append("s").append(reg);
             }
             sb.append("\n");
         }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,22 +46,21 @@
     private final FrameMap frameMap;
     private final OperandPool operands;
     private final RiRegisterConfig registerConfig;
+    private final CiCallingConvention incomingArguments;
 
     private final DataFlowAnalysis dataFlow;
 
-    private final SpillSlots spillSlots;
-
-    public SpillAllAllocator(GraalContext context, LIR lir, GraalCompilation compilation, OperandPool pool, RiRegisterConfig registerConfig) {
+    public SpillAllAllocator(GraalContext context, LIR lir, GraalCompilation compilation, OperandPool pool, RiRegisterConfig registerConfig, CiCallingConvention incomingArguments) {
         this.context = context;
         this.lir = lir;
         this.operands = pool;
         this.registerConfig = registerConfig;
         this.frameMap = compilation.frameMap();
+        this.incomingArguments = incomingArguments;
 
-        this.spillSlots = new SpillSlots(compilation.compiler.context, frameMap);
-        this.dataFlow = new DataFlowAnalysis(context, lir, pool, registerConfig, frameMap.incomingArguments());
+        this.dataFlow = new DataFlowAnalysis(context, lir, pool, registerConfig, incomingArguments);
         this.blockLocations = new LocationMap[lir.linearScanOrder().size()];
-        this.moveResolver = new MoveResolver(frameMap.target, spillSlots);
+        this.moveResolver = new MoveResolver(frameMap);
     }
 
 
@@ -121,7 +120,7 @@
     private LIRInstruction curInstruction;
 
     public void execute() {
-        assert LIRVerifier.verify(true, lir, frameMap.incomingArguments(), frameMap, registerConfig, operands);
+        assert LIRVerifier.verify(true, lir, incomingArguments, frameMap, registerConfig, operands);
 
         dataFlow.execute();
 
@@ -129,21 +128,21 @@
 
         context.observable.fireCompilationEvent("After spill all allocation", lir);
 
-        spillSlots.finish();
+        frameMap.finish();
 
         ResolveDataFlow resolveDataFlow = new ResolveDataFlowImpl(lir, moveResolver);
         resolveDataFlow.execute();
 
         context.observable.fireCompilationEvent("After resolve data flow", lir);
 
-        assert RegisterVerifier.verify(lir, frameMap.incomingArguments(), frameMap, registerConfig);
+        assert RegisterVerifier.verify(lir, incomingArguments, frameMap, registerConfig);
 
         AssignRegisters assignRegisters = new AssignRegistersImpl(lir, frameMap);
         assignRegisters.execute();
 
         context.observable.fireCompilationEvent("After register asignment", lir);
 
-        assert LIRVerifier.verify(true, lir, frameMap.incomingArguments(), frameMap, registerConfig, operands);
+        assert LIRVerifier.verify(true, lir, incomingArguments, frameMap, registerConfig, operands);
     }
 
     private void allocate() {
@@ -171,7 +170,7 @@
                 curStackLocations = new LocationMap(operands.numVariables());
                 trace(1, "  arguments");
                 curInstruction = lir.startBlock().lir().get(0);
-                for (CiValue value : frameMap.incomingArguments().locations) {
+                for (CiValue value : incomingArguments.locations) {
                     block(value);
                 }
             } else {
@@ -336,7 +335,7 @@
             assert curStackLocations.get(asVariable(value)) == null;
             Location regLoc = allocateRegister(asVariable(value), null, curOutRegisterState);
             if (!isTemp) {
-                Location stackLoc = new Location(asVariable(value), spillSlots.allocateSpillSlot(value.kind));
+                Location stackLoc = new Location(asVariable(value), frameMap.allocateSpillSlot(value.kind));
                 curStackLocations.put(stackLoc);
                 moveResolver.add(regLoc, stackLoc);
             }
@@ -362,7 +361,7 @@
     private CiValue defSlot(CiValue value) {
         if (isVariable(value)) {
             trace(3, "    assignSlot %s", value);
-            Location stackLoc = new Location(asVariable(value), spillSlots.allocateSpillSlot(value.kind));
+            Location stackLoc = new Location(asVariable(value), frameMap.allocateSpillSlot(value.kind));
             assert curStackLocations.get(asVariable(value)) == null;
             curStackLocations.put(stackLoc);
             trace(3, "      slot %s", stackLoc);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/MoveResolver.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/MoveResolver.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
 import com.sun.cri.ci.*;
 
 public final class MoveResolver {
-    private final SpillSlots spillSlots;
+    private final FrameMap frameMap;
     private final int[] registersBlocked;
     private final Map<CiValue, Integer> valuesBlocked;
     private final List<CiValue> mappingFrom;
@@ -42,10 +42,10 @@
     private final LIRInsertionBuffer insertionBuffer;
     private int insertPos;
 
-    public MoveResolver(CiTarget target, SpillSlots spillSlots) {
-        this.spillSlots = spillSlots;
+    public MoveResolver(FrameMap frameMap) {
+        this.frameMap = frameMap;
 
-        registersBlocked = new int[target.arch.registers.length];
+        registersBlocked = new int[frameMap.target.arch.registers.length];
         valuesBlocked = new HashMap<>();
 
         mappingFrom = new ArrayList<>();
@@ -201,7 +201,7 @@
         } else {
             assert spillCandidate != null : "no location for spilling found";
 
-            Location spillLocation = new Location(spillCandidate.variable, spillSlots.allocateSpillSlot(spillCandidate.kind));
+            Location spillLocation = new Location(spillCandidate.variable, frameMap.allocateSpillSlot(spillCandidate.kind));
             insertMove(spillCandidate, spillLocation);
 
             for (int i = mappingFrom.size() - 1; i >= 0; i--) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/SpillSlots.java	Mon Jan 02 22:18:16 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2011, 2011, 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.max.graal.alloc.util;
-
-import static com.sun.cri.ci.CiUtil.*;
-
-import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.lir.*;
-import com.sun.cri.ci.*;
-
-
-public class SpillSlots {
-    public final GraalContext context;
-    public final FrameMap frameMap;
-
-    /**
-     * Number of stack slots used for intervals allocated to memory.
-     */
-    private int maxSpills;
-
-    /**
-     * Unused spill slot for a single-word value because of alignment of a double-word value.
-     */
-    private CiStackSlot unusedSpillSlot;
-
-    public SpillSlots(GraalContext context, FrameMap frameMap) {
-        this.context = context;
-        this.frameMap = frameMap;
-        this.maxSpills = frameMap.initialSpillSlot();
-        this.unusedSpillSlot = null;
-
-        assert maxSpills >= 0;
-    }
-
-    private int numberOfSpillSlots(CiKind kind) {
-        return frameMap.target.spillSlots(kind);
-    }
-
-    /**
-     * Allocates the next available spill slot for a value of a given kind.
-     */
-    public CiStackSlot allocateSpillSlot(CiKind kind) {
-        assert maxSpills >= 0 : "cannot allocate new spill slots after finish() has been called";
-        assert numberOfSpillSlots(kind) <= 2 : "larger values not supported yet";
-
-        CiStackSlot spillSlot;
-        if (numberOfSpillSlots(kind) == 2) {
-            if (isOdd(maxSpills)) {
-                // alignment of double-slot values
-                // the hole because of the alignment is filled with the next single-slot value
-                assert unusedSpillSlot == null : "wasting a spill slot";
-                unusedSpillSlot = CiStackSlot.get(kind, maxSpills);
-                maxSpills++;
-            }
-            spillSlot = CiStackSlot.get(kind, maxSpills);
-            maxSpills += 2;
-        } else if (unusedSpillSlot != null) {
-            // re-use hole that was the result of a previous double-word alignment
-            spillSlot = unusedSpillSlot;
-            unusedSpillSlot = null;
-        } else {
-            spillSlot = CiStackSlot.get(kind, maxSpills);
-            maxSpills++;
-        }
-
-        return spillSlot;
-    }
-
-    public void finish() {
-        if (GraalOptions.Meter) {
-            context.metrics.LSRASpills += (maxSpills - frameMap.initialSpillSlot());
-        }
-
-        // fill in number of spill slots into frameMap
-        frameMap.finalizeFrame(maxSpills);
-        // Mark this object as finished
-        maxSpills = -1;
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -139,7 +139,7 @@
         AbstractAssembler masm = compiler.backend.newAssembler(registerConfig);
         TargetMethodAssembler tasm = new TargetMethodAssembler(this, masm);
         tasm.setFrameSize(frameMap.frameSize());
-        tasm.targetMethod.setCustomStackAreaOffset(FrameMap.offsetToCustomArea());
+        tasm.targetMethod.setCustomStackAreaOffset(frameMap.offsetToCustomArea());
         return tasm;
     }
 
@@ -317,7 +317,7 @@
     }
 
     public void initFrameMap() {
-        frameMap = this.compiler.backend.newFrameMap(this, method);
+        frameMap = this.compiler.backend.newFrameMap(this);
     }
 
     private void emitLIR(RiXirGenerator xir) {
@@ -353,7 +353,7 @@
                 }
 
                 if (GraalOptions.AllocSSA) {
-                    new SpillAllAllocator(context(), lir, this, lirGenerator.operands, registerConfig).execute();
+                    new SpillAllAllocator(context(), lir, this, lirGenerator.operands, registerConfig, lirGenerator.incomingArguments).execute();
                 } else {
                     new LinearScan(this, lir, lirGenerator, frameMap()).allocate();
                 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,20 +23,18 @@
 package com.oracle.max.graal.compiler.alloc;
 
 import static com.sun.cri.ci.CiUtil.*;
-import static java.lang.reflect.Modifier.*;
 
 import java.util.*;
 
 import com.oracle.max.criutils.*;
-import com.oracle.max.graal.alloc.util.*;
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.alloc.Interval.RegisterBinding;
 import com.oracle.max.graal.compiler.alloc.Interval.RegisterPriority;
 import com.oracle.max.graal.compiler.alloc.Interval.SpillState;
 import com.oracle.max.graal.compiler.gen.*;
 import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
@@ -67,8 +65,6 @@
 
     final OperandPool operands;
 
-    final SpillSlots spillSlots;
-
     /**
      * Map from {@linkplain #operandNumber(CiValue) operand numbers} to intervals.
      */
@@ -114,7 +110,6 @@
         this.ir = ir;
         this.gen = gen;
         this.frameMap = frameMap;
-        this.spillSlots = new SpillSlots(context, frameMap);
         this.sortedBlocks = ir.linearScanOrder().toArray(new LIRBlock[ir.linearScanOrder().size()]);
         CiRegister[] allocatableRegisters = compilation.registerConfig.getAllocatableRegisters();
         this.registers = new CiRegister[CiRegister.maxRegisterNumber(allocatableRegisters) + 1];
@@ -168,7 +163,7 @@
         if (interval.spillSlot() != null) {
             interval.assignLocation(interval.spillSlot());
         } else {
-            CiStackSlot slot = spillSlots.allocateSpillSlot(interval.kind());
+            CiStackSlot slot = frameMap.allocateSpillSlot(interval.kind());
             interval.setSpillSlot(slot);
             interval.assignLocation(slot);
         }
@@ -461,8 +456,8 @@
 
                         if (GraalOptions.TraceLinearScanLevel >= 4) {
                             CiStackSlot slot = interval.spillSlot();
-                            TTY.println("inserting move after definition of interval %d to stack slot %d%s at opId %d",
-                                            interval.operandNumber, slot.index(), slot.inCallerFrame() ? " in caller frame" : "", opId);
+                            TTY.println("inserting move after definition of interval %d to stack slot %s at opId %d",
+                                            interval.operandNumber, slot, opId);
                         }
 
                         interval = interval.next;
@@ -1034,8 +1029,6 @@
             if (op.input(0).isStackSlot()) {
                 CiStackSlot slot = (CiStackSlot) op.input(0);
                 if (GraalOptions.DetailedAsserts) {
-                    int argSlots = compilation.method.signature().argumentSlots(!isStatic(compilation.method.accessFlags()));
-                    assert slot.index() >= 0 && slot.index() < argSlots;
                     assert op.id() > 0 : "invalid id";
                     assert blockForId(op.id()).numberOfPreds() == 0 : "move from stack must be in first block";
                     assert op.result().isVariable() : "result of move must be a variable";
@@ -1048,7 +1041,7 @@
                 Interval interval = intervalFor(op.result());
                 CiStackSlot copySlot = slot;
                 if (GraalOptions.CopyPointerStackArguments && slot.kind == CiKind.Object) {
-                    copySlot = spillSlots.allocateSpillSlot(slot.kind);
+                    copySlot = frameMap.allocateSpillSlot(slot.kind);
                 }
                 interval.setSpillSlot(copySlot);
                 interval.assignLocation(copySlot);
@@ -1832,7 +1825,7 @@
 
         context.timers.startScope("Create Debug Info");
         try {
-            spillSlots.finish();
+            frameMap.finish();
 
             printIntervals("After register allocation");
             printLir("After register allocation", true);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/MoveResolver.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/MoveResolver.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -277,7 +277,7 @@
                 // one stack slot to another can happen (not allowed by LIRAssembler
                 CiStackSlot spillSlot = fromInterval.spillSlot();
                 if (spillSlot == null) {
-                    spillSlot = allocator.spillSlots.allocateSpillSlot(spillInterval.kind());
+                    spillSlot = allocator.frameMap.allocateSpillSlot(spillInterval.kind());
                     fromInterval.setSpillSlot(spillSlot);
                 }
                 spillInterval.assignLocation(spillSlot);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -77,7 +77,7 @@
     void verify(LIRBlock start) {
         // setup input registers (method arguments) for first block
         Interval[] inputState = new Interval[stateSize()];
-        CiCallingConvention args = compilation().frameMap().incomingArguments();
+        CiCallingConvention args = allocator.gen.incomingArguments;
         for (int n = 0; n < args.locations.length; n++) {
             CiValue operand = args.locations[n];
             if (operand.isRegister()) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/asm/TargetMethodAssembler.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/asm/TargetMethodAssembler.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -255,7 +255,8 @@
 
     public CiAddress asAddress(CiValue value) {
         if (value.isStackSlot()) {
-            return compilation.frameMap().toStackAddress((CiStackSlot) value);
+            CiStackSlot slot = (CiStackSlot) value;
+            return new CiAddress(slot.kind, compilation.registerConfig.getFrameRegister().asValue(), compilation.frameMap().offsetForStackSlot(slot));
         }
         return (CiAddress) value;
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/DebugInfoBuilder.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/DebugInfoBuilder.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,6 @@
 
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.FrameMap.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.virtual.*;
@@ -36,29 +35,17 @@
 public class DebugInfoBuilder {
     public final GraalCompilation compilation;
 
-    private final NodeMap<StackBlock> lockDataMap;
+    private final NodeMap<CiStackSlot> lockDataMap;
 
     public DebugInfoBuilder(GraalCompilation compilation) {
         this.compilation = compilation;
-        if (needLockData()) {
-            lockDataMap = new NodeMap<>(compilation.graph);
-        } else {
-            lockDataMap = null;
-        }
+        this.lockDataMap = new NodeMap<>(compilation.graph);
     }
 
-    public boolean needLockData() {
-        return compilation.compiler.runtime.sizeOfLockData() > 0;
-    }
-
-    public StackBlock lockDataFor(MonitorObject object) {
-        if (!needLockData()) {
-            return null;
-        }
-
-        StackBlock result = lockDataMap.get(object);
+    public CiStackSlot lockDataFor(MonitorObject object) {
+        CiStackSlot result = lockDataMap.get(object);
         if (result == null) {
-            result = compilation.frameMap().reserveStackBlock(compilation.compiler.runtime.sizeOfLockData(), false);
+            result = compilation.frameMap().allocateStackBlock(compilation.compiler.runtime.sizeOfLockData(), false);
             lockDataMap.set(object, result);
         }
         return result;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,8 @@
  */
 package com.oracle.max.graal.compiler.gen;
 
+import static com.oracle.max.cri.intrinsics.MemoryBarriers.*;
 import static com.oracle.max.graal.alloc.util.ValueUtil.*;
-import static com.oracle.max.cri.intrinsics.MemoryBarriers.*;
 import static com.sun.cri.ci.CiCallingConvention.Type.*;
 import static com.sun.cri.ci.CiValue.*;
 
@@ -37,7 +37,6 @@
 import com.oracle.max.graal.compiler.alloc.OperandPool.VariableFlag;
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.graphbuilder.*;
-import com.oracle.max.graal.compiler.lir.FrameMap.StackBlock;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.compiler.stub.*;
@@ -73,6 +72,8 @@
     public final OperandPool operands;
     private final DebugInfoBuilder debugInfoBuilder;
 
+    public final CiCallingConvention incomingArguments;
+
     private LIRBlock currentBlock;
     private ValueNode currentInstruction;
     private ValueNode lastInstructionPrinted; // Debugging only
@@ -86,6 +87,8 @@
         this.xirSupport = new XirSupport();
         this.operands = new OperandPool(compilation.compiler.target);
         this.debugInfoBuilder = new DebugInfoBuilder(compilation);
+
+        this.incomingArguments = compilation.registerConfig.getCallingConvention(JavaCallee, CiUtil.signatureToKinds(compilation.method), compilation.compiler.target, false);
     }
 
     @Override
@@ -343,7 +346,7 @@
     }
 
     private void setOperandsForParameters() {
-        CiCallingConvention args = compilation.frameMap().incomingArguments();
+        CiCallingConvention args = incomingArguments;
         for (LocalNode local : compilation.graph.getNodes(LocalNode.class)) {
             int i = local.index();
             CiValue src = toStackKind(args.locations[i]);
@@ -404,8 +407,6 @@
         emitXir(snippet, x, state(), null, true);
     }
 
-    protected abstract CiVariable emitLea(StackBlock stackBlock);
-
     @Override
     public void visitLoadField(LoadFieldNode x) {
         RiField field = x.field();
@@ -748,7 +749,7 @@
 
         CiKind[] signature = CiUtil.signatureToKinds(callTarget.targetMethod().signature(), callTarget.isStatic() ? null : callTarget.targetMethod().holder().kind(true));
         CiCallingConvention cc = compilation.registerConfig.getCallingConvention(JavaCall, signature, target(), false);
-        compilation.frameMap().adjustOutgoingStackSize(cc, JavaCall);
+        compilation.frameMap().callsMethod(cc, JavaCall);
         List<CiStackSlot> pointerSlots = new ArrayList<>(2);
         List<CiValue> argList = visitInvokeArguments(cc, callTarget.arguments(), pointerSlots);
 
@@ -781,7 +782,7 @@
             if (isRegister(value)) {
                 return asRegister(value).asValue(value.kind.stackKind());
             } else if (isStackSlot(value)) {
-                return CiStackSlot.get(value.kind.stackKind(), asStackSlot(value).index(), asStackSlot(value).inCallerFrame());
+                return CiStackSlot.get(value.kind.stackKind(), asStackSlot(value).rawOffset(), asStackSlot(value).rawAddFrameSize());
             } else {
                 throw Util.shouldNotReachHere();
             }
@@ -828,7 +829,7 @@
         if (arguments.length > 0) {
             // move the arguments into the correct location
             CiCallingConvention cc = compilation.registerConfig.getCallingConvention(RuntimeCall, arguments, target(), false);
-            compilation.frameMap().adjustOutgoingStackSize(cc, RuntimeCall);
+            compilation.frameMap().callsMethod(cc, RuntimeCall);
             assert cc.locations.length == args.length : "argument count mismatch";
             for (int i = 0; i < args.length; i++) {
                 CiValue arg = args[i];
@@ -857,7 +858,7 @@
 
         CiValue resultOperand = resultOperandFor(x.kind());
         CiCallingConvention cc = compilation.registerConfig.getCallingConvention(RuntimeCall, x.call().arguments, target(), false);
-        compilation.frameMap().adjustOutgoingStackSize(cc, RuntimeCall);
+        compilation.frameMap().callsMethod(cc, RuntimeCall);
         List<CiStackSlot> pointerSlots = new ArrayList<>(2);
         List<CiValue> argList = visitInvokeArguments(cc, x.arguments(), pointerSlots);
 
@@ -1209,7 +1210,7 @@
         if (arguments.length > 0) {
             // move the arguments into the correct location
             CiCallingConvention cc = compilation.registerConfig.getCallingConvention(RuntimeCall, arguments, target(), false);
-            compilation.frameMap().adjustOutgoingStackSize(cc, RuntimeCall);
+            compilation.frameMap().callsMethod(cc, RuntimeCall);
             assert cc.locations.length == args.length : "argument count mismatch";
             for (int i = 0; i < args.length; i++) {
                 CiValue arg = args[i];
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/FrameMap.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/FrameMap.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,197 +23,151 @@
 package com.oracle.max.graal.compiler.lir;
 
 import static com.oracle.max.graal.alloc.util.ValueUtil.*;
-import static com.sun.cri.ci.CiCallingConvention.Type.*;
 
-import com.oracle.max.graal.compiler.*;
+import java.util.*;
+
 import com.oracle.max.graal.compiler.stub.*;
 import com.oracle.max.graal.compiler.util.*;
-import com.oracle.max.graal.cri.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ci.CiCallingConvention.Type;
 import com.sun.cri.ri.*;
 
 /**
  * This class is used to build the stack frame layout for a compiled method.
- *
- * This is the format of a stack frame on an x86 (i.e. IA32 or X64) platform:
+ * A {@link CiStackSlot} is used to index slots of the frame relative to the stack pointer.
+ * The frame size is only fixed after register allocation when all spill slots have
+ * been allocated. Both the outgoing argument area and the spill are can grow until then.
+ * Therefore, outgoing arguments are indexed from the stack pointer, while spill slots
+ * are indexed from the beginning of the frame (and the total frame size has to be added
+ * to get the actual offset from the stack pointer).
+ * <br>
+ * This is the format of a stack frame:
  * <pre>
  *   Base       Contents
  *
- *          :                                :
- *          | incoming overflow argument n   |
- *          |     ...                        |
- *          | incoming overflow argument 0   |
- *          +--------------------------------+ Caller frame
- *          |                                |
- *          : custom area*                   :
- *          |                                |
- *   -------+--------------------------------+---------------------
- *          | return address                 |
- *          +--------------------------------+                  ---
- *          |                                |                   ^
- *          : callee save area               :                   |
- *          |                                |                   |
- *          +--------------------------------+ Current frame     |
- *          | alignment padding              |                   |
- *          +--------------------------------+                   |
- *          | ALLOCA block n                 |                   |
- *          :     ...                        :                   |
- *          | ALLOCA block 0                 |                   |
- *          +--------------------------------+    ---            |
- *          | spill slot n                   |     ^           frame
- *          :     ...                        :     |           size
- *          | spill slot 0                   |  shared           |
- *          +- - - - - - - - - - - - - - - - +   slot            |
- *          | outgoing overflow argument n   |  indexes          |
- *          |     ...                        |     |             |
- *          | outgoing overflow argument 0   |     v             |
- *          +--------------------------------+    ---            |
- *          |                                |                   |
- *          : custom area                    :                   |
- *    %sp   |                                |                   v
- *   -------+--------------------------------+----------------  ---
+ *            :                                :  -----
+ *   caller   | incoming overflow argument n   |    ^
+ *   frame    :     ...                        :    | positive
+ *            | incoming overflow argument 0   |    | offsets
+ *   ---------+--------------------------------+---------------------
+ *            | return address                 |    |            ^
+ *   current  +--------------------------------+    |            |    -----
+ *   frame    |                                |    |            |      ^
+ *            : callee save area               :    |            |      |
+ *            |                                |    |            |      |
+ *            +--------------------------------+    |            |      |
+ *            | spill slot 0                   |    | negative   |      |
+ *            :     ...                        :    v offsets    |      |
+ *            | spill slot n                   |  -----        total  frame
+ *            +--------------------------------+               frame  size
+ *            | alignment padding              |               size     |
+ *            +--------------------------------+  -----          |      |
+ *            | outgoing overflow argument n   |    ^            |      |
+ *            :     ...                        :    | positive   |      |
+ *            | outgoing overflow argument 0   |    | offsets    v      v
+ *    %sp-->  +--------------------------------+---------------------------
  *
  * </pre>
- * Note that the size of stack allocated memory block (ALLOCA block) in
- * the frame may be greater than the size of a {@linkplain CiTarget#spillSlotSize spill slot}.
- * Note also that the layout of the caller frame shown only applies if the caller
- * was also compiled with Graal. In particular, native frames won't have
- * a custom area if the native ABI specifies that stack arguments are at
- * the bottom of the frame (e.g. System V ABI on AMD64).
+ * The spill slot area also includes stack allocated memory blocks (ALLOCA blocks). The size
+ * of such a block may be greater than the size of a normal spill slot or the word size.
+ * <br>
+ * A runtime has two ways to reserve space in the stack frame for its own use: <ul>
+ * <li>A memory block somewhere in the frame of size {@link RiRuntime#getCustomStackAreaSize()}. The offset
+ *     to this block is returned in {@link CiTargetMethod#customStackAreaOffset()}.
+ * <li>At the beginning of the overflow argument area: The calling convention can specify that the first
+ *     overflow stack argument is not at offset 0, but at a specified offset o. Use
+ *     {@link RiRuntime#getMinimumOutgoingSize()} to make sure that call-free methods also have this space
+ *     reserved. Then the VM can use memory the memory at offset 0 relative to the stack pointer.
+ * </ul>
  */
 public final class FrameMap {
-
-    public final GraalRuntime runtime;
+    public final RiRuntime runtime;
     public final CiTarget target;
-    private final RiRegisterConfig registerConfig;
-    private final CiCallingConvention incomingArguments;
+    public final RiRegisterConfig registerConfig;
 
     /**
-     * The final frame size.
-     * Value is only set after register allocation is complete.
+     * The final frame size, not including the size of the return address.
+     * The value is only set after register allocation is complete, i.e., after all spill slots have been allocated.
      */
     private int frameSize;
 
     /**
-     * The number of spill slots allocated by the register allocator.
-     * The value {@code -2} means that the size of outgoing argument stack slots
-     * is not yet fixed. The value {@code -1} means that the register
-     * allocator has started allocating spill slots and so the size of
-     * outgoing stack slots cannot change as outgoing stack slots and
-     * spill slots share the same slot index address space.
+     * Size of the area occupied by spill slots and other stack-allocated memory blocks.
      */
-    private int spillSlotCount;
+    private int spillSize;
 
     /**
-     * The amount of memory allocated within the frame for uses of stack allocated memory blocks.
-     */
-    private int stackBlocksSize;
-
-    /**
-     * The list of stack blocks allocated in this frame.
-     */
-    private StackBlock stackBlocks;
-
-    /**
-     * Area occupied by outgoing overflow arguments.
+     * Size of the area occupied by outgoing overflow arguments.
      * This value is adjusted as calling conventions for outgoing calls are retrieved.
      */
     private int outgoingSize;
 
     /**
+     * The list of stack areas allocated in this frame that are present in every reference map.
+     */
+    private final List<CiStackSlot> objectStackBlocks;
+
+    /**
+     * The stack area reserved for use by the VM, or {@code null} if the VM does not request stack space.
+     */
+    private final CiStackSlot customArea;
+
+    /**
      * Creates a new frame map for the specified method.
-     *
-     * @param compilation the compilation context
-     * @param method the outermost method being compiled
      */
-    public FrameMap(GraalCompilation compilation, RiResolvedMethod method) {
-        this.runtime = compilation.compiler.runtime;
-        this.target = compilation.compiler.target;
-        this.registerConfig = compilation.registerConfig;
+    public FrameMap(RiRuntime runtime, CiTarget target, RiRegisterConfig registerConfig) {
+        this.runtime = runtime;
+        this.target = target;
+        this.registerConfig = registerConfig;
         this.frameSize = -1;
-        this.spillSlotCount = -2;
+        this.spillSize = returnAddressSize() + calleeSaveAreaSize();
+        this.outgoingSize = runtime.getMinimumOutgoingSize();
+        this.objectStackBlocks = new ArrayList<>();
+        this.customArea = allocateStackBlock(runtime.getCustomStackAreaSize(), false);
+    }
+
 
-        if (method == null) {
-            incomingArguments = new CiCallingConvention(new CiValue[0], 0);
-        } else {
-            incomingArguments = registerConfig.getCallingConvention(JavaCallee, CiUtil.signatureToKinds(method), target, false);
-        }
+    private int returnAddressSize() {
+        return target.arch.returnAddressSize;
+    }
+
+    private int calleeSaveAreaSize() {
+        CiCalleeSaveLayout csl = registerConfig.getCalleeSaveLayout();
+        return csl != null ? csl.size : 0;
     }
 
     /**
-     * Adjusts the stack-size for stack-based outgoing arguments if required.
-     *
-     * @param cc the calling convention
-     * @param type the type of calling convention
-     */
-    public void adjustOutgoingStackSize(CiCallingConvention cc, Type type) {
-        assert type.out;
-        if (frameSize != -1 && cc.stackSize != 0) {
-            // TODO(tw): This is a special work around for Windows runtime calls that can happen and must be ignored.
-            assert type == RuntimeCall;
-        } else {
-            if (type != RuntimeCall) {
-                assert frameSize == -1 : "frame size must not yet be fixed!";
-                reserveOutgoing(cc.stackSize);
-            }
-        }
-    }
-
-    /**
-     * Gets the calling convention for the incoming arguments to the compiled method.
-     * @return the calling convention for incoming arguments
-     */
-    public CiCallingConvention incomingArguments() {
-        return incomingArguments;
-    }
-
-    /**
-     * Gets the frame size of the compiled frame.
-     * @return the size in bytes of the frame
+     * Gets the frame size of the compiled frame, not including the size of the return address.
+     * @return The size of the frame (in bytes).
      */
     public int frameSize() {
-        assert this.frameSize != -1 : "frame size not computed yet";
+        assert frameSize != -1 : "frame size not computed yet";
         return frameSize;
     }
 
     /**
+     * Gets the total frame size of the compiled frame, including the size of the return address.
+     * @return The total size of the frame (in bytes).
+     */
+    public int totalFrameSize() {
+        return frameSize() + returnAddressSize();
+    }
+
+    /**
      * Sets the frame size for this frame.
-     * @param frameSize the frame size in bytes
+     * @param frameSize The frame size (in bytes).
      */
     public void setFrameSize(int frameSize) {
-        assert this.frameSize == -1 : "should only be calculated once";
+        assert this.frameSize == -1 : "must only be set once";
         this.frameSize = frameSize;
     }
 
     /**
-     * Computes the frame size for this frame, given the number of spill slots.
-     * @param finalSpillSlotCount the number of spill slots
+     * Computes the frame size for this frame. After this method has been called, methods that change the
+     * frame size cannot be called anymore, e.g., no more spill slots or outgoing arguments can be requested.
      */
-    public void finalizeFrame(int finalSpillSlotCount) {
-        assert this.spillSlotCount == -1 : "can only be set once";
-        assert this.frameSize == -1 : "should only be calculated once";
-        assert finalSpillSlotCount >= 0 : "must be positive";
-
-        this.spillSlotCount = finalSpillSlotCount;
-        int newFrameSize = offsetToStackBlocksEnd();
-        CiCalleeSaveLayout csl = registerConfig.getCalleeSaveLayout();
-        if (csl != null) {
-            newFrameSize += csl.size;
-        }
-        this.frameSize = target.alignFrameSize(newFrameSize);
-    }
-
-    /**
-     * Informs the frame map that the compiled code uses a particular compiler stub, which
-     * may need stack space for outgoing arguments.
-     *
-     * @param stub the compiler stub
-     */
-    public void usesStub(CompilerStub stub) {
-        int argsSize = stub.inArgs.length * target.spillSlotSize;
-        int resultSize = stub.resultKind.isVoid() ? 0 : target.spillSlotSize;
-        reserveOutgoing(Math.max(argsSize, resultSize));
+    public void finish() {
+        setFrameSize(target.alignFrameSize(outgoingSize + spillSize - returnAddressSize()));
     }
 
     /**
@@ -224,199 +178,128 @@
      * @return the offset of the stack slot
      */
     public int offsetForStackSlot(CiStackSlot slot) {
-        assert frameSize >= 0 : "fame size not computed yet";
-        if (slot.inCallerFrame()) {
-            int callerFrame = frameSize() + target.arch.returnAddressSize;
-            int callerFrameOffset = slot.index() * target.spillSlotSize;
-            return callerFrame + callerFrameOffset;
-        } else {
-            int offset = slot.index() * target.spillSlotSize;
-            assert offset <= frameSize() - target.spillSlotSize : "slot outside of frame";
-            return offset;
-        }
+        assert (!slot.rawAddFrameSize() && slot.rawOffset() < outgoingSize) ||
+            (slot.rawAddFrameSize() && slot.rawOffset() < 0 && -slot.rawOffset() <= spillSize) ||
+            (slot.rawAddFrameSize() && slot.rawOffset() >= 0);
+        return slot.offset(totalFrameSize());
+    }
+
+    /**
+     * Gets the offset to the stack area where callee-saved registers are stored.
+     * @return The offset to the callee save area (in bytes).
+     */
+    public int offsetToCalleeSaveArea() {
+        return frameSize() - calleeSaveAreaSize();
     }
 
     /**
-     * Converts a stack slot into a stack address.
-     *
-     * @param slot a stack slot
-     * @return a stack address
+     * Gets the offset of the stack area stack block reserved for use by the VM, or -1 if the VM does not request stack space.
+     * @return The offset to the custom area (in bytes).
      */
-    public CiAddress toStackAddress(CiStackSlot slot) {
-        return new CiAddress(slot.kind, registerConfig.getFrameRegister().asValue(), offsetForStackSlot(slot));
+    public int offsetToCustomArea() {
+        return customArea == null ? -1 : offsetForStackSlot(customArea);
     }
 
     /**
-     * Gets the stack address within this frame for a given reserved stack block.
-     *
-     * @param stackBlock the value returned from {@link #reserveStackBlock(int, boolean)} identifying the stack block
-     * @return a representation of the stack location
+     * 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.
+     * @param type The type of calling convention.
      */
-    public CiAddress toStackAddress(StackBlock stackBlock) {
-        return new CiAddress(target.wordKind, registerConfig.getFrameRegister().asValue(target.wordKind), offsetForStackBlock(stackBlock));
+    public void callsMethod(CiCallingConvention cc, Type type) {
+        // TODO look at the actual stack offsets?
+        assert type.out;
+        reserveOutgoing(cc.stackSize);
     }
 
-    public CiStackSlot toStackSlot(StackBlock stackBlock) {
-        return CiStackSlot.get(stackBlock.kind, offsetForStackBlock(stackBlock) / target.spillSlotSize);
+    /**
+     * Informs the frame map that the compiled code uses a particular compiler stub, which
+     * may need stack space for outgoing arguments.
+     * @param stub The compiler stub.
+     */
+    public void usesStub(CompilerStub stub) {
+        // TODO look at the actual stack slot offsets?
+        int argsSize = stub.inArgs.length * target.wordSize;
+        int resultSize = stub.resultKind.isVoid() ? 0 : target.wordSize;
+        reserveOutgoing(Math.max(argsSize, resultSize));
     }
 
     /**
      * Reserves space for stack-based outgoing arguments.
-     *
-     * @param argsSize the amount of space to reserve for stack-based outgoing arguments
+     * @param argsSize The amount of space (in bytes) to reserve for stack-based outgoing arguments.
      */
     public void reserveOutgoing(int argsSize) {
-        assert spillSlotCount == -2 : "cannot reserve outgoing stack slot space once register allocation has started";
-        if (argsSize > outgoingSize) {
-            outgoingSize = Util.roundUp(argsSize, target.spillSlotSize);
-        }
+        assert frameSize == -1 : "frame size must not yet be fixed";
+        outgoingSize = Math.max(outgoingSize, argsSize);
+    }
+
+    private CiStackSlot getSlot(CiKind kind, int additionalOffset) {
+        return CiStackSlot.get(kind, -spillSize + additionalOffset, true);
     }
 
     /**
-     * Encapsulates the details of a stack block reserved by a call to {@link FrameMap#reserveStackBlock(int, boolean)}.
+     * 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.
+     * @param kind The kind of the spill slot to be reserved.
+     * @return A spill slot denoting the reserved memory area.
      */
-    public static final class StackBlock extends CiValue {
-        private static final long serialVersionUID = -5260976274149772987L;
-
-        /**
-         * The size of this stack block.
-         */
-        private final int size;
-
-        /**
-         * The offset of this stack block within the frame space reserved for stack blocks.
-         */
-        private final int offset;
-
-        private final StackBlock next;
-
-        public StackBlock(StackBlock next, int size, int offset, CiKind kind) {
-            super(kind);
-            this.next = next;
-            this.size = size;
-            this.offset = offset;
-        }
-
-        @Override
-        public String toString() {
-            return "StackBlock " + offset;
-        }
+    public CiStackSlot allocateSpillSlot(CiKind kind) {
+        int size = target.sizeInBytes(kind);
+        spillSize = Util.roundUp(spillSize + size, size);
+        return getSlot(kind, 0);
     }
 
     /**
-     * Reserves a block of memory in the frame of the method being compiled.
+     * Reserves a block of memory in the frame of the method being compiled. The returned block is aligned on a word boundary.
+     * If the requested size is 0, the method returns {@code null}.
      *
-     * @param size the number of bytes to reserve
-     * @param refs specifies if the block is all references
-     * @return a descriptor of the reserved block that can be used with {@link #toStackAddress(StackBlock)} once register
-     *         allocation is complete and the size of the frame has been {@linkplain #finalizeFrame(int) finalized}.
+     * @param size The size to reserve (in bytes).
+     * @param refs Specifies if the block is all references. If true, the block will be in all reference maps for this method.
+     *             The caller is responsible to initialize the memory block before the first instruction that uses a reference map.
+     * @return A stack slot describing the begin of the memory block.
      */
-    public StackBlock reserveStackBlock(int size, boolean refs) {
-        assert size % target.wordSize == 0;
-        StackBlock block = new StackBlock(stackBlocks, size, stackBlocksSize, refs ? CiKind.Object : target.wordKind);
-        stackBlocksSize += size;
-        stackBlocks = block;
-        return block;
-    }
-
-    private int offsetForStackBlock(StackBlock stackBlock) {
-        assert stackBlock.offset >= 0 && stackBlock.offset + stackBlock.size <= stackBlocksSize : "invalid stack block";
-        int offset = offsetToStackBlocks() + stackBlock.offset;
-        assert offset <= (frameSize() - stackBlock.size) : "stack block outside of frame";
-        return offset;
-    }
-
-    private int offsetToSpillArea() {
-        return outgoingSize + customAreaSize();
-    }
+    public CiStackSlot allocateStackBlock(int size, boolean refs) {
+        if (size == 0) {
+            return null;
+        }
+        spillSize = Util.roundUp(spillSize + size, target.wordSize);
 
-    private int offsetToSpillEnd() {
-        return offsetToSpillArea() + spillSlotCount * target.spillSlotSize;
-    }
-
-    public int customAreaSize() {
-        return runtime.getCustomStackAreaSize();
-    }
-
-    public static int offsetToCustomArea() {
-        return 0;
-    }
+        if (refs) {
+            assert size % target.wordSize == 0;
+            CiStackSlot result = getSlot(CiKind.Object, 0);
+            objectStackBlocks.add(result);
+            for (int i = target.wordSize; i < size; i += target.wordSize) {
+                objectStackBlocks.add(getSlot(CiKind.Object, i));
+            }
+            return result;
 
-    private int offsetToStackBlocks() {
-        return offsetToSpillEnd();
-    }
-
-    private int offsetToStackBlocksEnd() {
-        return offsetToStackBlocks() + stackBlocksSize;
-    }
-
-    public int offsetToCalleeSaveAreaStart() {
-        CiCalleeSaveLayout csl = registerConfig.getCalleeSaveLayout();
-        if (csl != null) {
-            return offsetToCalleeSaveAreaEnd() - csl.size;
         } else {
-            return offsetToCalleeSaveAreaEnd();
+            return getSlot(target.wordKind, 0);
         }
     }
 
-    public int offsetToCalleeSaveAreaEnd() {
-        return frameSize;
-    }
-
-    /**
-     * Gets the index of the first available spill slot relative to the base of the frame.
-     * After this call, no further outgoing stack slots can be {@linkplain #reserveOutgoing(int) reserved}.
-     *
-     * @return the index of the first available spill slot
-     */
-    public int initialSpillSlot() {
-        if (spillSlotCount == -2) {
-            spillSlotCount = -1;
-        }
-        return (outgoingSize + customAreaSize()) / target.spillSlotSize;
-    }
-
-
-
-
-    private int registerRefMapSize() {
-        return target.arch.registerReferenceMapBitCount;
-    }
-
-    private int frameRefMapSize() {
-        if (incomingArguments.stackSize > 0) {
-            return (frameSize() + target.arch.returnAddressSize + customAreaSize() + incomingArguments.stackSize) / target.wordSize;
-        } else {
-            return frameSize() / target.wordSize;
-        }
-    }
 
     private int frameRefMapIndex(CiStackSlot slot) {
-        int offset = offsetForStackSlot(slot);
-        assert offset % target.wordSize == 0 && offset / target.wordSize < frameRefMapSize();
-        return offset / target.wordSize;
+        assert offsetForStackSlot(slot) % target.wordSize == 0;
+        return offsetForStackSlot(slot) / target.wordSize;
     }
 
     /**
      * Initializes a reference map that covers all registers of the target architecture.
      */
     public CiBitMap initRegisterRefMap() {
-        return new CiBitMap(registerRefMapSize());
+        return new CiBitMap(target.arch.registerReferenceMapBitCount);
     }
 
     /**
-     * Initializes a reference map that covers all the slots in the frame.
+     * Initializes a reference map. Initially, the size is large enough to cover all the
+     * slots in the frame. If the method has incoming reference arguments on the stack,
+     * the reference map might grow later when such a reference is set.
      */
     public CiBitMap initFrameRefMap() {
-        CiBitMap frameRefMap = new CiBitMap(frameRefMapSize());
-        for (StackBlock sb = stackBlocks; sb != null; sb = sb.next) {
-            if (sb.kind == CiKind.Object) {
-                int firstSlot = offsetForStackBlock(sb) / target.wordSize;
-                int words = sb.size / target.wordSize;
-                for (int i = 0; i < words; i++) {
-                    frameRefMap.set(firstSlot + i);
-                }
-            }
+        CiBitMap frameRefMap = new CiBitMap(frameSize() / target.wordSize);
+        for (CiStackSlot slot : objectStackBlocks) {
+            setReference(slot, null, frameRefMap);
         }
         return frameRefMap;
     }
@@ -431,12 +314,14 @@
      * @param frameRefMap A frame reference map, as created by {@link #initFrameRefMap()}.
      */
     public void setReference(CiValue location, CiBitMap registerRefMap, CiBitMap frameRefMap) {
-//        assert registerRefMap.size() == registerRefMapSize() && frameRefMap.size() == frameRefMapSize();
         if (location.kind == CiKind.Object) {
             if (isRegister(location)) {
+                assert registerRefMap.size() == target.arch.registerReferenceMapBitCount;
                 registerRefMap.set(asRegister(location).number);
             } else if (isStackSlot(location)) {
-                frameRefMap.set(frameRefMapIndex(asStackSlot(location)));
+                int index = frameRefMapIndex(asStackSlot(location));
+                frameRefMap.grow(index + 1);
+                frameRefMap.set(index);
             } else {
                 assert isConstant(location);
             }
@@ -453,12 +338,15 @@
      * @param frameRefMap A frame reference map, as created by {@link #initFrameRefMap()}.
      */
     public void clearReference(CiValue location, CiBitMap registerRefMap, CiBitMap frameRefMap) {
-//        assert registerRefMap.size() == registerRefMapSize() && frameRefMap.size() == frameRefMapSize();
         if (location.kind == CiKind.Object) {
             if (location instanceof CiRegisterValue) {
+                assert registerRefMap.size() == target.arch.registerReferenceMapBitCount;
                 registerRefMap.clear(asRegister(location).number);
             } else if (isStackSlot(location)) {
-                frameRefMap.clear(frameRefMapIndex(asStackSlot(location)));
+                int index = frameRefMapIndex(asStackSlot(location));
+                if (index < frameRefMap.size()) {
+                    frameRefMap.clear(index);
+                }
             } else {
                 assert isConstant(location);
             }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRDebugInfo.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRDebugInfo.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
 
 import java.util.*;
 
-import com.oracle.max.graal.compiler.lir.FrameMap.StackBlock;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
 import com.sun.cri.ci.*;
 
@@ -106,16 +105,6 @@
     public void finish(CiBitMap registerRefMap, CiBitMap frameRefMap, FrameMap frameMap) {
         debugInfo = new CiDebugInfo(topFrame, registerRefMap, frameRefMap);
 
-        // Add locks that are in the designated frame area.
-        for (CiFrame cur = topFrame; cur != null; cur = cur.caller()) {
-            for (int i = 0; i < cur.numLocks; i++) {
-                CiMonitorValue lock = (CiMonitorValue) cur.getLockValue(i);
-                if (lock.lockData != null) {
-                    lock.lockData = frameMap.toStackSlot((StackBlock) lock.lockData);
-                }
-            }
-        }
-
         // Add additional stack slots for outgoing method parameters.
         if (pointerSlots != null) {
             for (CiStackSlot v : pointerSlots) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -348,7 +348,7 @@
                 if (buf.length() != 0) {
                     buf.append(", ");
                 }
-                buf.append(CiStackSlot.get(CiKind.Object, slot));
+                buf.append("s").append(slot);
             }
         }
         if (debugInfo.hasRegisterRefMap()) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/Backend.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/Backend.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,7 +54,7 @@
         }
     }
 
-    public abstract FrameMap newFrameMap(GraalCompilation compilation, RiResolvedMethod method);
+    public abstract FrameMap newFrameMap(GraalCompilation compilation);
     public abstract LIRGenerator newLIRGenerator(GraalCompilation compilation, RiXirGenerator xir);
     public abstract AbstractAssembler newAssembler(RiRegisterConfig registerConfig);
     public abstract CiXirAssembler newXirAssembler();
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Backend.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Backend.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,8 +54,8 @@
     }
 
     @Override
-    public FrameMap newFrameMap(GraalCompilation compilation, RiResolvedMethod method) {
-        return new FrameMap(compilation, method);
+    public FrameMap newFrameMap(GraalCompilation compilation) {
+        return new FrameMap(compilation.compiler.runtime, compilation.compiler.target, compilation.registerConfig);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64CompilerStubEmitter.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64CompilerStubEmitter.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -222,11 +222,11 @@
 
     private void convertPrologue() {
         prologue(new CiCalleeSaveLayout(0, -1, comp.compiler.target.wordSize, convertArgument, convertResult));
-        asm.movq(convertArgument, comp.frameMap().toStackAddress(inArgs[0]));
+        asm.movq(convertArgument, tasm.asAddress(inArgs[0]));
     }
 
     private void convertEpilogue() {
-        asm.movq(comp.frameMap().toStackAddress(outResult), convertResult);
+        asm.movq(tasm.asAddress(outResult), convertResult);
         epilogue();
     }
 
@@ -323,7 +323,7 @@
         CiCallingConvention cc = comp.registerConfig.getCallingConvention(RuntimeCall, call.arguments, comp.compiler.target, false);
         for (int i = 0; i < cc.locations.length; ++i) {
             CiValue location = cc.locations[i];
-            asm.movq(location.asRegister(), comp.frameMap().toStackAddress(inArgs[i]));
+            asm.movq(location.asRegister(), tasm.asAddress(inArgs[i]));
         }
 
         if (GraalOptions.AlignCallsForPatching) {
@@ -338,7 +338,7 @@
 
         if (call.resultKind != CiKind.Void) {
             CiRegister returnRegister = comp.registerConfig.getReturnRegister(call.resultKind);
-            asm.movq(comp.frameMap().toStackAddress(outResult), returnRegister);
+            asm.movq(tasm.asAddress(outResult), returnRegister);
         }
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,6 @@
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.gen.*;
 import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.FrameMap.StackBlock;
 import com.oracle.max.graal.compiler.stub.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.nodes.DeoptimizeNode.DeoptAction;
@@ -136,14 +135,14 @@
     @Override
     public CiVariable emitLea(CiAddress address) {
         CiVariable result = newVariable(target().wordKind);
-        append(LEA.create(result, address.base, address.index, address.scale, address.displacement));
+        append(LEA_MEMORY.create(result, address.base, address.index, address.scale, address.displacement));
         return result;
     }
 
     @Override
-    public CiVariable emitLea(StackBlock stackBlock) {
+    public CiVariable emitLea(CiStackSlot address) {
         CiVariable result = newVariable(target().wordKind);
-        append(LEA_STACK_BLOCK.create(result, stackBlock));
+        append(LEA_STACK.create(result, address));
         return result;
     }
 
@@ -490,7 +489,7 @@
 
         if (kind == CiKind.Object) {
             CiVariable loadedAddress = newVariable(compilation.compiler.target.wordKind);
-            append(LEA.create(loadedAddress, addrBase, addrIndex, CiAddress.Scale.Times1, 0));
+            append(LEA_MEMORY.create(loadedAddress, addrBase, addrIndex, CiAddress.Scale.Times1, 0));
             addrBase = loadedAddress;
             addrIndex = CiVariable.IllegalValue;
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64MoveOpcode.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64MoveOpcode.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,6 @@
 import com.oracle.max.asm.target.amd64.*;
 import com.oracle.max.graal.compiler.asm.*;
 import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.FrameMap.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.sun.cri.ci.*;
 
@@ -113,11 +112,11 @@
     public enum LeaStackBlockOpcode implements LIROpcode {
         LEA_STACK_BLOCK;
 
-        public LIRInstruction create(CiVariable result, final StackBlock stackBlock) {
+        public LIRInstruction create(CiVariable result, final CiStackSlot stackBlock) {
             return new AMD64LIRInstruction(this, result, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) {
                 @Override
                 public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-                    masm.leaq(tasm.asRegister(result()), tasm.compilation.frameMap().toStackAddress(stackBlock));
+                    masm.leaq(tasm.asRegister(result()), tasm.asAddress(stackBlock));
                 }
             };
         }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64StandardOpcode.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64StandardOpcode.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,8 +32,8 @@
     public static final AMD64MoveOpcode.MoveOpcode MOVE = AMD64MoveOpcode.MoveOpcode.MOVE;
     public static final AMD64MoveOpcode.LoadOpcode LOAD = AMD64MoveOpcode.LoadOpcode.LOAD;
     public static final AMD64MoveOpcode.StoreOpcode STORE = AMD64MoveOpcode.StoreOpcode.STORE;
-    public static final AMD64MoveOpcode.LeaOpcode LEA = AMD64MoveOpcode.LeaOpcode.LEA;
-    public static final AMD64MoveOpcode.LeaStackBlockOpcode LEA_STACK_BLOCK = AMD64MoveOpcode.LeaStackBlockOpcode.LEA_STACK_BLOCK;
+    public static final AMD64MoveOpcode.LeaOpcode LEA_MEMORY = AMD64MoveOpcode.LeaOpcode.LEA;
+    public static final AMD64MoveOpcode.LeaStackBlockOpcode LEA_STACK = AMD64MoveOpcode.LeaStackBlockOpcode.LEA_STACK_BLOCK;
     public static final AMD64MoveOpcode.MembarOpcode MEMBAR = AMD64MoveOpcode.MembarOpcode.MEMBAR;
     public static final AMD64MoveOpcode.NullCheckOpcode NULL_CHECK = AMD64MoveOpcode.NullCheckOpcode.NULL_CHECK;
     public static final AMD64MoveOpcode.CompareAndSwapOpcode CAS = AMD64MoveOpcode.CompareAndSwapOpcode.CAS;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64XirOpcode.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64XirOpcode.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -316,7 +316,6 @@
                     }
 
                     CiCallingConvention cc = tasm.compilation.registerConfig.getCallingConvention(RuntimeCall, signature, tasm.target, false);
-                    tasm.compilation.frameMap().adjustOutgoingStackSize(cc, RuntimeCall);
                     for (int i = 0; i < inst.arguments.length; i++) {
                         CiValue argumentLocation = cc.locations[i];
                         CiValue argumentSourceLocation = operands[inst.arguments[i].index];
@@ -454,7 +453,7 @@
                     }
                     CiCalleeSaveLayout csl = tasm.compilation.registerConfig.getCalleeSaveLayout();
                     if (csl != null && csl.size != 0) {
-                        int frameToCSA = tasm.compilation.frameMap().offsetToCalleeSaveAreaStart();
+                        int frameToCSA = tasm.compilation.frameMap().offsetToCalleeSaveArea();
                         assert frameToCSA >= 0;
                         masm.save(csl, frameToCSA);
                     }
@@ -467,7 +466,7 @@
                     if (csl != null && csl.size != 0) {
                         tasm.targetMethod.setRegisterRestoreEpilogueOffset(masm.codeBuffer.position());
                         // saved all registers, restore all registers
-                        int frameToCSA = tasm.compilation.frameMap().offsetToCalleeSaveAreaStart();
+                        int frameToCSA = tasm.compilation.frameMap().offsetToCalleeSaveArea();
                         masm.restore(csl, frameToCSA);
                     }
 
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/CompilerImpl.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/CompilerImpl.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -131,7 +131,7 @@
         if (target == null) {
             final int wordSize = 8;
             final int stackFrameAlignment = 16;
-            target = new HotSpotTarget(new AMD64(), true, wordSize, stackFrameAlignment, config.vmPageSize, wordSize, true);
+            target = new HotSpotTarget(new AMD64(), true, stackFrameAlignment, config.vmPageSize, wordSize, true);
         }
 
         return target;
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotRegisterConfig.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotRegisterConfig.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -74,11 +74,7 @@
 
     private final CiCalleeSaveLayout registerSaveArea;
 
-    private final HotSpotVMConfig config;
-
-
     public HotSpotRegisterConfig(HotSpotVMConfig config, boolean globalStubConfig) {
-        this.config = config;
         if (config.windowsOs) {
             generalParameterRegisters = new CiRegister[] {rdx, r8, r9, rdi, rsi, rcx};
         } else {
@@ -123,7 +119,7 @@
 
         int currentGeneral = 0;
         int currentXMM = 0;
-        int currentStackIndex = 0;
+        int currentStackOffset = 0;
 
         for (int i = 0; i < types.length; i++) {
             final CiKind kind = types[i];
@@ -153,16 +149,12 @@
             }
 
             if (locations[i] == null) {
-                locations[i] = CiStackSlot.get(kind.stackKind(), currentStackIndex, !type.out);
-                currentStackIndex += target.spillSlots(kind);
+                locations[i] = CiStackSlot.get(kind.stackKind(), currentStackOffset, !type.out);
+                currentStackOffset += Math.max(target.sizeInBytes(kind), target.wordSize);
             }
         }
 
-        int stackSize = currentStackIndex * target.spillSlotSize;
-        if (type == Type.RuntimeCall && config.windowsOs) {
-            stackSize = Math.max(stackSize, config.runtimeCallStackSize);
-        }
-        return new CiCallingConvention(locations, stackSize);
+        return new CiCallingConvention(locations, currentStackOffset);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotRuntime.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotRuntime.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -211,6 +211,11 @@
     }
 
     @Override
+    public int getMinimumOutgoingSize() {
+        return config.runtimeCallStackSize;
+    }
+
+    @Override
     public int getArrayLength(CiConstant array) {
         return compiler.getVMEntries().getArrayLength(array);
     }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotTarget.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotTarget.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
  */
 public class HotSpotTarget extends CiTarget {
 
-    public HotSpotTarget(CiArchitecture arch, boolean isMP, int spillSlotSize, int stackAlignment, int pageSize, int cacheAlignment, boolean inlineObjects) {
-        super(arch, isMP, spillSlotSize, stackAlignment, pageSize, cacheAlignment, inlineObjects, true, true);
+    public HotSpotTarget(CiArchitecture arch, boolean isMP, int stackAlignment, int pageSize, int cacheAlignment, boolean inlineObjects) {
+        super(arch, isMP, stackAlignment, pageSize, cacheAlignment, inlineObjects, true, true);
     }
 }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/nodes/TailcallNode.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/nodes/TailcallNode.java	Mon Jan 02 14:16:08 2012 -0800
@@ -65,7 +65,7 @@
 
         CiKind[] signature = CiUtil.signatureToKinds(method.signature(), isStatic ? null : method.holder().kind(true));
         CiCallingConvention cc = gen.compilation.registerConfig.getCallingConvention(JavaCall, signature, gen.compilation.compiler.target, false);
-        gen.compilation.frameMap().adjustOutgoingStackSize(cc, JavaCall);
+        gen.compilation.frameMap().callsMethod(cc, JavaCall);
         List<ValueNode> parameters = new ArrayList<>();
         for (int i = 0; i < cc.locations.length; i++) {
             parameters.add(frameState.localAt(i));
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/spi/LIRGeneratorTool.java	Mon Jan 02 22:18:16 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/spi/LIRGeneratorTool.java	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -57,6 +57,7 @@
     public abstract CiVariable emitLoad(CiAddress loadAddress, CiKind kind, boolean canTrap);
     public abstract void emitStore(CiAddress storeAddress, CiValue input, CiKind kind, boolean canTrap);
     public abstract CiVariable emitLea(CiAddress address);
+    public abstract CiVariable emitLea(CiStackSlot address);
 
     public abstract CiVariable emitNegate(CiValue input);
     public abstract CiVariable emitAdd(CiValue a, CiValue b);
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Mon Jan 02 22:18:16 2012 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Mon Jan 02 14:16:08 2012 -0800
@@ -147,13 +147,11 @@
     } else if (type == T_LONG) {
       locationType = Location::lng;
     }
-    jint index = CiStackSlot::index(value);
-    ScopeValue* value;
-    if (index >= 0) {
-      value = new LocationValue(Location::new_stk_loc(locationType, index * HeapWordSize));
-    } else {
-      value = new LocationValue(Location::new_stk_loc(locationType, -((index + 1) * HeapWordSize) + total_frame_size));
+    jint offset = CiStackSlot::offset(value);
+    if (CiStackSlot::addFrameSize(value)) {
+      offset += total_frame_size;
     }
+    ScopeValue* value = new LocationValue(Location::new_stk_loc(locationType, offset));
     if (type == T_DOUBLE || type == T_LONG) {
       second = value;
     }
--- a/src/share/vm/graal/graalJavaAccess.cpp	Mon Jan 02 22:18:16 2012 +0100
+++ b/src/share/vm/graal/graalJavaAccess.cpp	Mon Jan 02 14:16:08 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,13 +31,13 @@
 void compute_offset(int &dest_offset, klassOop klass_oop, const char* name, const char* signature, bool static_field) {
   Symbol* name_symbol = SymbolTable::probe(name, (int)strlen(name));
   Symbol* signature_symbol = SymbolTable::probe(signature, (int)strlen(signature));
-#ifdef DEBUG
+#ifndef PRODUCT
   if (name_symbol == NULL) {
     tty->print_cr("symbol with name %s was not found in symbol table (klass=%s)", name, klass_oop->klass_part()->name()->as_C_string());
   }
 #endif
-  assert(name_symbol != NULL, "symbol not found - class layout changed?");
-  assert(signature_symbol != NULL, "symbol not found - class layout changed?");
+  guarantee(name_symbol != NULL, "symbol not found - class layout changed?");
+  guarantee(signature_symbol != NULL, "symbol not found - class layout changed?");
 
   instanceKlass* ik = instanceKlass::cast(klass_oop);
   fieldDescriptor fd;
@@ -46,7 +46,7 @@
     tty->print_cr("Invalid layout of %s at %s", name_symbol->as_C_string(), ik->external_name());
     fatal("Invalid layout of preloaded class");
   }
-  assert(fd.is_static() == static_field, "static/instance mismatch");
+  guarantee(fd.is_static() == static_field, "static/instance mismatch");
   dest_offset = fd.offset();
 }
 
--- a/src/share/vm/graal/graalJavaAccess.hpp	Mon Jan 02 22:18:16 2012 +0100
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Mon Jan 02 14:16:08 2012 -0800
@@ -213,7 +213,8 @@
     int_field(CiRegister, number)                                                       \
   end_class                                                                             \
   start_class(CiStackSlot)                                                              \
-    int_field(CiStackSlot, index)                                                       \
+    int_field(CiStackSlot, offset)                                                      \
+    boolean_field(CiStackSlot, addFrameSize)                                            \
   end_class                                                                             \
   start_class(CiVirtualObject)                                                          \
     int_field(CiVirtualObject, id)                                                      \