changeset 13594:fcabc0da42b0

enhanced support for reserving a block of memory on the stack such that the block can be a mix of primitive data and object pointers
author Doug Simon <doug.simon@oracle.com>
date Sun, 12 Jan 2014 14:53:00 +0100
parents 24353c21ef34
children 7acbe6efed0d
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java
diffstat 3 files changed, 47 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java	Fri Jan 10 19:30:45 2014 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java	Sun Jan 12 14:53:00 2014 +0100
@@ -22,6 +22,10 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import static com.oracle.graal.asm.NumUtil.*;
+
+import java.util.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
@@ -45,7 +49,9 @@
     @Override
     public void generate(LIRGenerator gen) {
         int size = rank * 4;
-        StackSlot array = gen.frameMap().allocateStackBlock(size, false);
+        int wordSize = gen.target().wordSize;
+        int slots = roundUp(size, wordSize) / wordSize;
+        StackSlot array = gen.frameMap().allocateStackSlots(slots, new BitSet(0), null);
         Value result = gen.emitAddress(array);
         gen.setResult(this, result);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java	Fri Jan 10 19:30:45 2014 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java	Sun Jan 12 14:53:00 2014 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import java.util.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
@@ -41,7 +43,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         assert graph().getNodes().filter(MonitorCounterNode.class).count() == 1 : "monitor counters not canonicalized to single instance";
-        StackSlot counter = gen.frameMap().allocateStackBlock(gen.target().wordSize, false);
+        StackSlot counter = gen.frameMap().allocateStackSlots(1, new BitSet(0), null);
         Value result = gen.emitAddress(counter);
         gen.setResult(this, result);
     }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Fri Jan 10 19:30:45 2014 -0800
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Sun Jan 12 14:53:00 2014 +0100
@@ -73,9 +73,9 @@
     private boolean hasOutgoingStackArguments;
 
     /**
-     * The list of stack areas allocated in this frame that are present in every reference map.
+     * The list of stack slots allocated in this frame that are present in every reference map.
      */
-    private final List<StackSlot> objectStackBlocks;
+    private final List<StackSlot> objectStackSlots;
 
     /**
      * Records whether an offset to an incoming stack argument was ever returned by
@@ -91,7 +91,7 @@
         this.registerConfig = codeCache.getRegisterConfig();
         this.frameSize = -1;
         this.outgoingSize = codeCache.getMinimumOutgoingSize();
-        this.objectStackBlocks = new ArrayList<>();
+        this.objectStackSlots = new ArrayList<>();
     }
 
     protected int returnAddressSize() {
@@ -296,29 +296,46 @@
     }
 
     /**
-     * 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}.
+     * Reserves a number of contiguous slots in the frame of the method being compiled. If the
+     * requested number of slots is 0, this method returns {@code null}.
      * 
-     * @param 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.
+     * @param slots the number of slots to reserve
+     * @param objects specifies the indexes of the object pointer slots. The caller is responsible
+     *            for guaranteeing that each such object pointer slot is initialized before any
+     *            instruction that uses a reference map. Without this guarantee, the garbage
+     *            collector could see garbage object values.
+     * @param outObjectStackSlots if non-null, the object pointer slots allocated are added to this
+     *            list
+     * @return the first reserved stack slot (i.e., at the lowest address)
      */
-    public StackSlot allocateStackBlock(int size, boolean refs) {
+    public StackSlot allocateStackSlots(int slots, BitSet objects, List<StackSlot> outObjectStackSlots) {
         assert frameSize == -1 : "frame size must not yet be fixed";
-        if (size == 0) {
+        if (slots == 0) {
             return null;
         }
-        spillSize = NumUtil.roundUp(spillSize + size, target.wordSize);
+        spillSize += (slots * target.wordSize);
 
-        if (refs) {
-            assert size % target.wordSize == 0;
-            StackSlot result = allocateNewSpillSlot(Kind.Object, 0);
-            objectStackBlocks.add(result);
-            for (int i = target.wordSize; i < size; i += target.wordSize) {
-                objectStackBlocks.add(allocateNewSpillSlot(Kind.Object, i));
+        if (!objects.isEmpty()) {
+            assert objects.length() < slots;
+            StackSlot result = null;
+            for (int slotIndex = 0; slotIndex < slots; slotIndex++) {
+                StackSlot objectSlot = null;
+                if (objects.get(slotIndex)) {
+                    objectSlot = allocateNewSpillSlot(Kind.Object, slotIndex * target.wordSize);
+                    objectStackSlots.add(objectSlot);
+                    if (outObjectStackSlots != null) {
+                        outObjectStackSlots.add(objectSlot);
+                    }
+                }
+                if (slotIndex == 0) {
+                    if (objectSlot != null) {
+                        result = objectSlot;
+                    } else {
+                        result = allocateNewSpillSlot(target.wordKind, 0);
+                    }
+                }
             }
+            assert result != null;
             return result;
 
         } else {
@@ -340,7 +357,7 @@
      */
     public BitSet initFrameRefMap() {
         BitSet frameRefMap = new BitSet(frameSize() / target.wordSize);
-        for (StackSlot slot : objectStackBlocks) {
+        for (StackSlot slot : objectStackSlots) {
             setReference(slot, null, frameRefMap);
         }
         return frameRefMap;