Access stack slots in the order they were allocated (
bug 673550 part 1, r=adrake).
--- 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 ®)
{
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