Access stack slots in the order they were allocated (bug 673550 part 1, r=adrake).
authorDavid Anderson <danderson@mozilla.com>
Mon, 25 Jul 2011 20:43:34 -0700
changeset 73489 7bac5dfc151a6bdb9cfdfbca6469cc1ed951ff6c
parent 73488 7605afbb47bbd1518c42927184de854329daadc8
child 73490 584ea5bae16e0d79d416a884ebbb17d03b50e580
push id23
push userdanderson@mozilla.com
push dateTue, 26 Jul 2011 03:57:11 +0000
reviewersadrake
bugs673550
milestone8.0a1
Access stack slots in the order they were allocated (bug 673550 part 1, r=adrake).
js/src/ion/GreedyAllocator.cpp
js/src/ion/IonLIR.cpp
js/src/ion/IonLIR.h
js/src/ion/LinearScan.cpp
js/src/ion/MIR.h
js/src/ion/shared/CodeGenerator-shared.cpp
js/src/ion/shared/CodeGenerator-shared.h
js/src/ion/shared/CodeGenerator-x86-shared.cpp
js/src/ion/shared/CodeGenerator-x86-shared.h
js/src/ion/x64/StackAssignment-x64.h
js/src/ion/x86/Architecture-x86.h
js/src/ion/x86/StackAssignment-x86.h
--- a/js/src/ion/GreedyAllocator.cpp
+++ b/js/src/ion/GreedyAllocator.cpp
@@ -907,13 +907,13 @@ GreedyAllocator::allocate()
 
     blocks = gen->allocate<BlockInfo>(graph.numBlocks());
     for (size_t i = 0; i < graph.numBlocks(); i++)
         new (&blocks[i]) BlockInfo();
 
     findDefinitions();
     if (!allocateRegisters())
         return false;
-    graph.setStackHeight(stackSlots.stackHeight());
+    graph.setLocalSlotCount(stackSlots.stackHeight());
 
     return true;
 }
 
--- a/js/src/ion/IonLIR.cpp
+++ b/js/src/ion/IonLIR.cpp
@@ -44,17 +44,17 @@
 #include "IonLIR.h"
 #include "IonLIR-inl.h"
 
 using namespace js;
 using namespace js::ion;
 
 LIRGraph::LIRGraph()
   : numVirtualRegisters_(0),
-    stackHeight_(0)
+    localSlotCount_(0)
 {
 }
 
 uint32
 LBlock::firstId()
 {
     if (phis_.length()) {
         return phis_[0]->id();
--- a/js/src/ion/IonLIR.h
+++ b/js/src/ion/IonLIR.h
@@ -605,17 +605,17 @@ class LInstruction : public TempObject,
 #   undef LIROP
 
     virtual bool accept(LInstructionVisitor *visitor) = 0;
 };
 
 class LInstructionVisitor
 {
   public:
-#define VISIT_INS(op) virtual bool visit##op(L##op *) { JS_NOT_REACHED("implement " #op); return false; }
+#define VISIT_INS(op) virtual bool visit##op(L##op *) { return true; JS_NOT_REACHED("implement " #op); return false; }
     LIR_OPCODE_LIST(VISIT_INS)
 #undef VISIT_INS
 };
 
 typedef InlineList<LInstruction>::iterator LInstructionIterator;
 typedef InlineList<LInstruction>::reverse_iterator LInstructionReverseIterator;
 
 class LPhi;
@@ -801,17 +801,19 @@ public:
         return **this;
     }
 };
 
 class LIRGraph
 {
     Vector<LBlock *, 16, IonAllocPolicy> blocks_;
     uint32 numVirtualRegisters_;
-    uint32 stackHeight_;
+
+    // Number of stack slots needed for local spills.
+    uint32 localSlotCount_;
 
   public:
     LIRGraph();
 
     size_t numBlocks() const {
         return blocks_.length();
     }
     LBlock *getBlock(size_t i) const {
@@ -824,22 +826,21 @@ class LIRGraph
         numVirtualRegisters_ += VREG_INCREMENT;
         return numVirtualRegisters_;
     }
     uint32 numVirtualRegisters() const {
         // Virtual registers are 1-based, not 0-based, so add one as a
         // convenience for 0-based arrays.
         return numVirtualRegisters_ + 1;
     } 
-    void setStackHeight(uint32 stackHeight) {
-        // Note that the stack height is counted in slots.
-        stackHeight_ = stackHeight;
+    void setLocalSlotCount(uint32 localSlotCount) {
+        localSlotCount_ = localSlotCount;
     }
-    uint32 stackHeight() const {
-        return stackHeight_;
+    uint32 localSlotCount() const {
+        return localSlotCount_;
     }
 };
 
 LAllocation::LAllocation(const AnyRegister &reg)
 {
     if (reg.isFloat())
         *this = LFloatReg(reg.fpu());
     else
--- a/js/src/ion/LinearScan.cpp
+++ b/js/src/ion/LinearScan.cpp
@@ -822,17 +822,17 @@ LinearScanAllocator::reifyAllocations()
         }
     }
 
     // Strip phis out
     for (size_t i = 0; i < graph.numBlocks(); i++)
         graph.getBlock(i)->clearPhis();
 
     // Set the graph overall stack height
-    graph.setStackHeight(stackAssignment.stackHeight());
+    graph.setLocalSlotCount(stackAssignment.stackHeight());
 
     return true;
 }
 
 /*
  * Split the given interval at the given position, and add the created
  * interval to the unhandled queue.
  */
--- a/js/src/ion/MIR.h
+++ b/js/src/ion/MIR.h
@@ -216,16 +216,17 @@ class MDefinition : public MNode
     uint32 flags_;          // Bit flags.
 
   private:
     enum Flag {
         None = 0,
 #   define DEFINE_FLAG(flag) flag,
         MIR_FLAG_LIST(DEFINE_FLAG)
 #   undef DEFINE_FLAG
+        Total
     };
 
     void setBlock(MBasicBlock *block) {
         block_ = block;
     }
 
     bool hasFlags(uint32 flags) const {
         return (flags_ & flags) == flags;
--- a/js/src/ion/shared/CodeGenerator-shared.cpp
+++ b/js/src/ion/shared/CodeGenerator-shared.cpp
@@ -41,17 +41,19 @@
 #include "CodeGenerator-shared.h"
 #include "ion/MIRGenerator.h"
 
 using namespace js;
 using namespace js::ion;
 
 CodeGeneratorShared::CodeGeneratorShared(MIRGenerator *gen, LIRGraph &graph)
   : gen(gen),
-    graph(graph)
+    graph(graph),
+    frameDepth_(graph.localSlotCount() * sizeof(STACK_SLOT_SIZE)),
+    framePushed_(0)
 {
 }
 
 bool
 CodeGeneratorShared::generateBody()
 {
     for (size_t i = 0; i < graph.numBlocks(); i++) {
         current = graph.getBlock(i);
--- a/js/src/ion/shared/CodeGenerator-shared.h
+++ b/js/src/ion/shared/CodeGenerator-shared.h
@@ -57,16 +57,39 @@ class CodeGeneratorShared : public LInst
     LIRGraph &graph;
     LBlock *current;
     MoveGroupResolver moveGroupResolver;
 
     static inline int32 ToInt32(const LAllocation *a) {
         return a->toConstant()->toInt32();
     }
 
+  protected:
+    // The initial size of the frame in bytes. These are bytes beyond the
+    // constant header present for every Ion frame, used for pre-determined
+    // spills.
+    int32 frameDepth_;
+
+    // Extra bytes currently pushed onto the frame beyond frameDepth_. This is
+    // needed to compute offsets to stack slots while temporary space has been
+    // reserved for unexpected spills or C++ function calls.
+    int32 framePushed_;
+
+    inline int32 ArgToStackOffset(int32 slot) {
+        JS_ASSERT(slot >= 0);
+        return framePushed_ + frameDepth_ + ION_FRAME_PREFIX_SIZE + slot;
+    }
+
+    inline int32 SlotToStackOffset(int32 slot) {
+        JS_ASSERT(slot >= 0 && slot <= int32(graph.localSlotCount()));
+        int32 offset = framePushed_ + frameDepth_ - slot * STACK_SLOT_SIZE;
+        JS_ASSERT(offset >= 0);
+        return offset;
+    }
+
   private:
     virtual bool generatePrologue() = 0;
     bool generateBody();
 
   public:
     CodeGeneratorShared(MIRGenerator *gen, LIRGraph &graph);
 
     bool generate();
--- a/js/src/ion/shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/ion/shared/CodeGenerator-x86-shared.cpp
@@ -42,19 +42,17 @@
 #include "ion/MIR.h"
 #include "ion/MIRGraph.h"
 #include "CodeGenerator-shared-inl.h"
 
 using namespace js;
 using namespace js::ion;
 
 CodeGeneratorX86Shared::CodeGeneratorX86Shared(MIRGenerator *gen, LIRGraph &graph)
-  : CodeGeneratorShared(gen, graph),
-    frameDepth_(graph.stackHeight() * sizeof(STACK_SLOT_SIZE)),
-    framePushed_(0)
+  : CodeGeneratorShared(gen, graph)
 {
 
 }
 
 bool
 CodeGeneratorX86Shared::generatePrologue()
 {
     masm.reserveStack(frameDepth_);
--- a/js/src/ion/shared/CodeGenerator-x86-shared.h
+++ b/js/src/ion/shared/CodeGenerator-x86-shared.h
@@ -51,27 +51,16 @@ class CodeGeneratorX86Shared : public Co
 {
     friend class MoveResolverX86;
 
     CodeGeneratorX86Shared *thisFromCtor() {
         return this;
     }
 
   protected:
-    // The initial size of the frame in bytes. These are bytes beyond the
-    // constant header present for every Ion frame, used for pre-determined
-    // spills.
-    int32 frameDepth_;
-
-    // Extra bytes currently pushed onto the frame beyond frameDepth_. This is
-    // needed to compute offsets to stack slots while temporary space has been
-    // reserved for unexpected spills or C++ function calls.
-    int32 framePushed_;
-
-  protected:
     inline Operand ToOperand(const LAllocation &a) {
         if (a.isGeneralReg())
             return Operand(a.toGeneralReg()->reg());
         if (a.isFloatReg())
             return Operand(a.toFloatReg()->reg());
         int32 disp;
         if (a.isStackSlot())
             disp = SlotToStackOffset(a.toStackSlot()->slot());
@@ -81,26 +70,16 @@ class CodeGeneratorX86Shared : public Co
     }
     inline Operand ToOperand(const LAllocation *a) {
         return ToOperand(*a);
     }
     inline Operand ToOperand(const LDefinition *def) {
         return ToOperand(def->output());
     }
 
-    inline int32 ArgToStackOffset(int32 slot) {
-        JS_ASSERT(slot >= 0);
-        return framePushed_ + frameDepth_ + ION_FRAME_PREFIX_SIZE + slot;
-    }
-
-    inline int32 SlotToStackOffset(int32 slot) {
-        JS_ASSERT(slot >= 0 && slot < int32(graph.stackHeight()));
-        return framePushed_ + slot * STACK_SLOT_SIZE;
-    }
-
   public:
     CodeGeneratorX86Shared(MIRGenerator *gen, LIRGraph &graph);
 
     bool generatePrologue();
 
   public:
     virtual bool visitLabel(LLabel *label);
     virtual bool visitGoto(LGoto *jump);
--- a/js/src/ion/x64/StackAssignment-x64.h
+++ b/js/src/ion/x64/StackAssignment-x64.h
@@ -66,18 +66,18 @@ class StackAssignment
         return allocateSlot(index);
     }
 
     bool allocateSlot(uint32 *index) {
         if (!slots.empty()) {
             *index = slots.popCopy();
             return true;
         }
-        *index = height_++;
-        return height_ < MAX_STACK_SLOTS;
+        *index = ++height_;
+        return true;
     }
 
     uint32 stackHeight() const {
         return height_;
     }
 };
 
 } // namespace ion
--- a/js/src/ion/x86/Architecture-x86.h
+++ b/js/src/ion/x86/Architecture-x86.h
@@ -43,17 +43,16 @@
 #define jsion_cpu_x86_regs_h__
 
 #include "assembler/assembler/X86Assembler.h"
 
 namespace js {
 namespace ion {
 
 static const ptrdiff_t STACK_SLOT_SIZE       = 4;
-static const uint32 MAX_STACK_SLOTS          = 256;
 static const uint32 DOUBLE_STACK_ALIGNMENT   = 2;
 
 // In bytes: slots in between arguments and the locals.
 //   +4 for number of arguments.
 //   +4 for return address.
 static const uint32 ION_FRAME_PREFIX_SIZE    = 8;
 
 // In bytes: slots needed for potential memory->memory move spills.
--- a/js/src/ion/x86/StackAssignment-x86.h
+++ b/js/src/ion/x86/StackAssignment-x86.h
@@ -60,38 +60,38 @@ class StackAssignment
     }
     void freeDoubleSlot(uint32 index) {
         doubleSlots.append(index);
     }
 
     bool allocateDoubleSlot(uint32 *index) {
         if (!doubleSlots.empty()) {
             *index = doubleSlots.popCopy();
-            return false;
+            return true;
         }
         if (ComputeByteAlignment(height_, DOUBLE_STACK_ALIGNMENT)) {
             normalSlots.append(height_++);
             JS_ASSERT(!ComputeByteAlignment(height_, DOUBLE_STACK_ALIGNMENT));
         }
+        height_ += 2;
         *index = height_;
-        height_ += 2;
-        return height_ < MAX_STACK_SLOTS;
+        return true;
     }
 
     bool allocateSlot(uint32 *index) {
         if (!normalSlots.empty()) {
             *index = normalSlots.popCopy();
             return true;
         }
         if (!doubleSlots.empty()) {
             *index = doubleSlots.popCopy();
             return normalSlots.append(*index + 1);
         }
-        *index = height_++;
-        return height_ < MAX_STACK_SLOTS;
+        *index = ++height_;
+        return true;
     }
 
     uint32 stackHeight() const {
         return height_;
     }
 };
 
 } // namespace ion