Bug 950703 - SpiderMonkey: Use 32-bit slots on 64-bit platforms. r=jandem

This commit is contained in:
Dan Gohman 2013-12-17 08:46:37 -08:00
parent 968a156b5b
commit a5a98431b0
22 changed files with 187 additions and 148 deletions

View File

@ -5838,7 +5838,7 @@ StackDecrementForCall(MacroAssembler &masm, const VectorT &argTypes, unsigned ex
return AlignBytes(alreadyPushed + extraBytes + argBytes, StackAlignment) - alreadyPushed; return AlignBytes(alreadyPushed + extraBytes + argBytes, StackAlignment) - alreadyPushed;
} }
static const unsigned FramePushedAfterSave = NonVolatileRegs.gprs().size() * STACK_SLOT_SIZE + static const unsigned FramePushedAfterSave = NonVolatileRegs.gprs().size() * sizeof(intptr_t) +
NonVolatileRegs.fpus().size() * sizeof(double); NonVolatileRegs.fpus().size() * sizeof(double);
static bool static bool

View File

@ -32,6 +32,29 @@
namespace js { namespace js {
namespace jit { namespace jit {
// Given a slot index, returns the offset, in bytes, of that slot from an
// IonJSFrameLayout. Slot distances are uniform across architectures, however,
// the distance does depend on the size of the frame header.
static inline int32_t
OffsetOfFrameSlot(int32_t slot)
{
if (slot <= 0)
return -slot;
return -(slot * STACK_SLOT_SIZE);
}
static inline uintptr_t
ReadFrameSlot(IonJSFrameLayout *fp, int32_t slot)
{
return *(uintptr_t *)((char *)fp + OffsetOfFrameSlot(slot));
}
static inline double
ReadFrameDoubleSlot(IonJSFrameLayout *fp, int32_t slot)
{
return *(double *)((char *)fp + OffsetOfFrameSlot(slot));
}
IonFrameIterator::IonFrameIterator(JSContext *cx) IonFrameIterator::IonFrameIterator(JSContext *cx)
: current_(cx->mainThread().ionTop), : current_(cx->mainThread().ionTop),
type_(IonFrame_Exit), type_(IonFrame_Exit),

View File

@ -17,6 +17,13 @@
namespace js { namespace js {
namespace jit { namespace jit {
// The size of a stack "slot". Multiple adjacent slots are allocated together
// when larger stack allocations are needed.
static const uint32_t STACK_SLOT_SIZE = 4;
// The number of stack slots needed for a double value.
static const uint32_t DOUBLE_STACK_ALIGNMENT = 2;
typedef void * CalleeToken; typedef void * CalleeToken;
enum CalleeTokenTag enum CalleeTokenTag
@ -310,29 +317,6 @@ namespace jit {
void void
GetPcScript(JSContext *cx, JSScript **scriptRes, jsbytecode **pcRes); GetPcScript(JSContext *cx, JSScript **scriptRes, jsbytecode **pcRes);
// Given a slot index, returns the offset, in bytes, of that slot from an
// IonJSFrameLayout. Slot distances are uniform across architectures, however,
// the distance does depend on the size of the frame header.
static inline int32_t
OffsetOfFrameSlot(int32_t slot)
{
if (slot <= 0)
return -slot;
return -(slot * STACK_SLOT_SIZE);
}
static inline uintptr_t
ReadFrameSlot(IonJSFrameLayout *fp, int32_t slot)
{
return *(uintptr_t *)((char *)fp + OffsetOfFrameSlot(slot));
}
static inline double
ReadFrameDoubleSlot(IonJSFrameLayout *fp, int32_t slot)
{
return *(double *)((char *)fp + OffsetOfFrameSlot(slot));
}
CalleeToken CalleeToken
MarkCalleeToken(JSTracer *trc, CalleeToken token); MarkCalleeToken(JSTracer *trc, CalleeToken token);

View File

@ -243,13 +243,13 @@ void
MacroAssembler::PushRegsInMask(RegisterSet set) MacroAssembler::PushRegsInMask(RegisterSet set)
{ {
int32_t diffF = set.fpus().size() * sizeof(double); int32_t diffF = set.fpus().size() * sizeof(double);
int32_t diffG = set.gprs().size() * STACK_SLOT_SIZE; int32_t diffG = set.gprs().size() * sizeof(intptr_t);
#if defined(JS_CPU_X86) || defined(JS_CPU_X64) #if defined(JS_CPU_X86) || defined(JS_CPU_X64)
// On x86, always use push to push the integer registers, as it's fast // On x86, always use push to push the integer registers, as it's fast
// on modern hardware and it's a small instruction. // on modern hardware and it's a small instruction.
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) { for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
diffG -= STACK_SLOT_SIZE; diffG -= sizeof(intptr_t);
Push(*iter); Push(*iter);
} }
#elif defined(JS_CPU_ARM) #elif defined(JS_CPU_ARM)
@ -257,21 +257,21 @@ MacroAssembler::PushRegsInMask(RegisterSet set)
adjustFrame(diffG); adjustFrame(diffG);
startDataTransferM(IsStore, StackPointer, DB, WriteBack); startDataTransferM(IsStore, StackPointer, DB, WriteBack);
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) { for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
diffG -= STACK_SLOT_SIZE; diffG -= sizeof(intptr_t);
transferReg(*iter); transferReg(*iter);
} }
finishDataTransfer(); finishDataTransfer();
} else { } else {
reserveStack(diffG); reserveStack(diffG);
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) { for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
diffG -= STACK_SLOT_SIZE; diffG -= sizeof(intptr_t);
storePtr(*iter, Address(StackPointer, diffG)); storePtr(*iter, Address(StackPointer, diffG));
} }
} }
#else #else
reserveStack(diffG); reserveStack(diffG);
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) { for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
diffG -= STACK_SLOT_SIZE; diffG -= sizeof(intptr_t);
storePtr(*iter, Address(StackPointer, diffG)); storePtr(*iter, Address(StackPointer, diffG));
} }
#endif #endif
@ -293,7 +293,7 @@ MacroAssembler::PushRegsInMask(RegisterSet set)
void void
MacroAssembler::PopRegsInMaskIgnore(RegisterSet set, RegisterSet ignore) MacroAssembler::PopRegsInMaskIgnore(RegisterSet set, RegisterSet ignore)
{ {
int32_t diffG = set.gprs().size() * STACK_SLOT_SIZE; int32_t diffG = set.gprs().size() * sizeof(intptr_t);
int32_t diffF = set.fpus().size() * sizeof(double); int32_t diffF = set.fpus().size() * sizeof(double);
const int32_t reservedG = diffG; const int32_t reservedG = diffG;
const int32_t reservedF = diffF; const int32_t reservedF = diffF;
@ -322,7 +322,7 @@ MacroAssembler::PopRegsInMaskIgnore(RegisterSet set, RegisterSet ignore)
// instruction. // instruction.
if (ignore.empty(false)) { if (ignore.empty(false)) {
for (GeneralRegisterForwardIterator iter(set.gprs()); iter.more(); iter++) { for (GeneralRegisterForwardIterator iter(set.gprs()); iter.more(); iter++) {
diffG -= STACK_SLOT_SIZE; diffG -= sizeof(intptr_t);
Pop(*iter); Pop(*iter);
} }
} else } else
@ -331,7 +331,7 @@ MacroAssembler::PopRegsInMaskIgnore(RegisterSet set, RegisterSet ignore)
if (set.gprs().size() > 1 && ignore.empty(false)) { if (set.gprs().size() > 1 && ignore.empty(false)) {
startDataTransferM(IsLoad, StackPointer, IA, WriteBack); startDataTransferM(IsLoad, StackPointer, IA, WriteBack);
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) { for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
diffG -= STACK_SLOT_SIZE; diffG -= sizeof(intptr_t);
transferReg(*iter); transferReg(*iter);
} }
finishDataTransfer(); finishDataTransfer();
@ -340,7 +340,7 @@ MacroAssembler::PopRegsInMaskIgnore(RegisterSet set, RegisterSet ignore)
#endif #endif
{ {
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) { for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
diffG -= STACK_SLOT_SIZE; diffG -= sizeof(intptr_t);
if (!ignore.has(*iter)) if (!ignore.has(*iter))
loadPtr(Address(StackPointer, diffG), *iter); loadPtr(Address(StackPointer, diffG), *iter);
} }

View File

@ -37,7 +37,7 @@ class MSnapshot;
static const uint32_t VREG_INCREMENT = 1; static const uint32_t VREG_INCREMENT = 1;
static const uint32_t THIS_FRAME_SLOT = 0; static const uint32_t THIS_FRAME_ARGSLOT = 0;
#if defined(JS_NUNBOX32) #if defined(JS_NUNBOX32)
# define BOX_PIECES 2 # define BOX_PIECES 2
@ -349,8 +349,7 @@ class LConstantIndex : public LAllocation
} }
}; };
// Stack slots are indexes into the stack, given that each slot is size // Stack slots are indices into the stack. The indices are byte indices.
// STACK_SLOT_SIZE.
class LStackSlot : public LAllocation class LStackSlot : public LAllocation
{ {
public: public:
@ -363,9 +362,7 @@ class LStackSlot : public LAllocation
} }
}; };
// Arguments are reverse indexes into the stack, and as opposed to LStackSlot, // Arguments are reverse indices into the stack. The indices are byte indices.
// each index is measured in bytes because we have to index the middle of a
// Value on 32 bits architectures.
class LArgument : public LAllocation class LArgument : public LAllocation
{ {
public: public:

View File

@ -799,6 +799,16 @@ LinearScanAllocator::allocateSlotFor(const LiveInterval *interval)
SlotList *freed; SlotList *freed;
if (reg->type() == LDefinition::DOUBLE) if (reg->type() == LDefinition::DOUBLE)
freed = &finishedDoubleSlots_; freed = &finishedDoubleSlots_;
#if JS_BITS_PER_WORD == 64
else if (reg->type() == LDefinition::GENERAL ||
reg->type() == LDefinition::OBJECT ||
reg->type() == LDefinition::SLOTS)
freed = &finishedDoubleSlots_;
#endif
#ifdef JS_PUNBOX64
else if (reg->type() == LDefinition::BOX)
freed = &finishedDoubleSlots_;
#endif
#ifdef JS_NUNBOX32 #ifdef JS_NUNBOX32
else if (IsNunbox(reg)) else if (IsNunbox(reg))
freed = &finishedNunboxSlots_; freed = &finishedNunboxSlots_;
@ -882,6 +892,16 @@ LinearScanAllocator::freeAllocation(LiveInterval *interval, LAllocation *alloc)
if (alloc->isStackSlot()) { if (alloc->isStackSlot()) {
if (mine->type() == LDefinition::DOUBLE) if (mine->type() == LDefinition::DOUBLE)
finishedDoubleSlots_.append(interval); finishedDoubleSlots_.append(interval);
#if JS_BITS_PER_WORD == 64
else if (mine->type() == LDefinition::GENERAL ||
mine->type() == LDefinition::OBJECT ||
mine->type() == LDefinition::SLOTS)
finishedDoubleSlots_.append(interval);
#endif
#ifdef JS_PUNBOX64
else if (mine->type() == LDefinition::BOX)
finishedDoubleSlots_.append(interval);
#endif
else else
finishedSlots_.append(interval); finishedSlots_.append(interval);
} }

View File

@ -31,7 +31,7 @@ LIRGenerator::visitParameter(MParameter *param)
{ {
ptrdiff_t offset; ptrdiff_t offset;
if (param->index() == MParameter::THIS_SLOT) if (param->index() == MParameter::THIS_SLOT)
offset = THIS_FRAME_SLOT; offset = THIS_FRAME_ARGSLOT;
else else
offset = 1 + param->index(); offset = 1 + param->index();

View File

@ -69,16 +69,20 @@ class SnapshotReader
{ {
friend class SnapshotReader; friend class SnapshotReader;
// An offset that is illegal for a local variable's stack allocation.
static const int32_t InvalidStackSlot = -1;
Register::Code reg_; Register::Code reg_;
int32_t stackSlot_; int32_t stackSlot_;
static Location From(const Register &reg) { static Location From(const Register &reg) {
Location loc; Location loc;
loc.reg_ = reg.code(); loc.reg_ = reg.code();
loc.stackSlot_ = INVALID_STACK_SLOT; loc.stackSlot_ = InvalidStackSlot;
return loc; return loc;
} }
static Location From(int32_t stackSlot) { static Location From(int32_t stackSlot) {
JS_ASSERT(stackSlot != InvalidStackSlot);
Location loc; Location loc;
loc.reg_ = Register::Code(0); // Quell compiler warnings. loc.reg_ = Register::Code(0); // Quell compiler warnings.
loc.stackSlot_ = stackSlot; loc.stackSlot_ = stackSlot;
@ -95,7 +99,7 @@ class SnapshotReader
return stackSlot_; return stackSlot_;
} }
bool isStackSlot() const { bool isStackSlot() const {
return stackSlot_ != INVALID_STACK_SLOT; return stackSlot_ != InvalidStackSlot;
} }
}; };

View File

@ -28,10 +28,9 @@ class StackSlotAllocator
uint32_t allocateDoubleSlot() { uint32_t allocateDoubleSlot() {
if (!doubleSlots.empty()) if (!doubleSlots.empty())
return doubleSlots.popCopy(); return doubleSlots.popCopy();
if (ComputeByteAlignment(height_, DOUBLE_STACK_ALIGNMENT)) if (height_ % 2 != 0)
normalSlots.append(++height_); normalSlots.append(++height_);
height_ += (sizeof(double) / STACK_SLOT_SIZE); return height_ += 2;
return height_;
} }
uint32_t allocateSlot() { uint32_t allocateSlot() {
if (!normalSlots.empty()) if (!normalSlots.empty())
@ -50,13 +49,20 @@ class StackSlotAllocator
void freeSlot(LDefinition::Type type, uint32_t index) { void freeSlot(LDefinition::Type type, uint32_t index) {
switch (type) { switch (type) {
case LDefinition::FLOAT32: #if JS_BITS_PER_WORD == 32
case LDefinition::GENERAL:
case LDefinition::OBJECT: case LDefinition::OBJECT:
case LDefinition::SLOTS: case LDefinition::SLOTS:
#endif
case LDefinition::FLOAT32: return freeSlot(index);
#if JS_BITS_PER_WORD == 64
case LDefinition::GENERAL:
case LDefinition::OBJECT:
case LDefinition::SLOTS:
#endif
#ifdef JS_PUNBOX64 #ifdef JS_PUNBOX64
case LDefinition::BOX: case LDefinition::BOX:
#endif #endif
case LDefinition::GENERAL: return freeSlot(index);
#ifdef JS_NUNBOX32 #ifdef JS_NUNBOX32
case LDefinition::TYPE: case LDefinition::TYPE:
case LDefinition::PAYLOAD: case LDefinition::PAYLOAD:
@ -68,13 +74,20 @@ class StackSlotAllocator
uint32_t allocateSlot(LDefinition::Type type) { uint32_t allocateSlot(LDefinition::Type type) {
switch (type) { switch (type) {
case LDefinition::FLOAT32: #if JS_BITS_PER_WORD == 32
case LDefinition::GENERAL:
case LDefinition::OBJECT: case LDefinition::OBJECT:
case LDefinition::SLOTS: case LDefinition::SLOTS:
#endif
case LDefinition::FLOAT32: return allocateSlot();
#if JS_BITS_PER_WORD == 64
case LDefinition::GENERAL:
case LDefinition::OBJECT:
case LDefinition::SLOTS:
#endif
#ifdef JS_PUNBOX64 #ifdef JS_PUNBOX64
case LDefinition::BOX: case LDefinition::BOX:
#endif #endif
case LDefinition::GENERAL: return allocateSlot();
#ifdef JS_NUNBOX32 #ifdef JS_NUNBOX32
case LDefinition::TYPE: case LDefinition::TYPE:
case LDefinition::PAYLOAD: case LDefinition::PAYLOAD:

View File

@ -17,18 +17,12 @@
namespace js { namespace js {
namespace jit { namespace jit {
static const uint32_t STACK_SLOT_SIZE = 4;
static const uint32_t DOUBLE_STACK_ALIGNMENT = 2;
// In bytes: slots needed for potential memory->memory move spills. // In bytes: slots needed for potential memory->memory move spills.
// +8 for cycles // +8 for cycles
// +4 for gpr spills // +4 for gpr spills
// +8 for double spills // +8 for double spills
static const uint32_t ION_FRAME_SLACK_SIZE = 20; static const uint32_t ION_FRAME_SLACK_SIZE = 20;
// An offset that is illegal for a local variable's stack allocation.
static const int32_t INVALID_STACK_SLOT = -1;
// These offsets are specific to nunboxing, and capture offsets into the // These offsets are specific to nunboxing, and capture offsets into the
// components of a js::Value. // components of a js::Value.
static const int32_t NUNBOX32_TYPE_OFFSET = 4; static const int32_t NUNBOX32_TYPE_OFFSET = 4;

View File

@ -2211,7 +2211,7 @@ static inline uint32_t
GetArgStackDisp(uint32_t arg) GetArgStackDisp(uint32_t arg)
{ {
JS_ASSERT(arg >= NumIntArgRegs); JS_ASSERT(arg >= NumIntArgRegs);
return (arg - NumIntArgRegs) * STACK_SLOT_SIZE; return (arg - NumIntArgRegs) * sizeof(intptr_t);
} }
#endif #endif

View File

@ -34,7 +34,7 @@ BailoutEnvironment::BailoutEnvironment(JitCompartment *ion, void **sp)
if (bailout_->frameClass() != FrameSizeClass::None()) { if (bailout_->frameClass() != FrameSizeClass::None()) {
frameSize_ = bailout_->frameSize(); frameSize_ = bailout_->frameSize();
frame_ = &sp_[sizeof(BailoutStack) / STACK_SLOT_SIZE]; frame_ = &sp_[sizeof(BailoutStack) / sizeof(void *)];
// Compute the bailout ID. // Compute the bailout ID.
IonCode *code = ion->getBailoutTable(bailout_->frameClass()); IonCode *code = ion->getBailoutTable(bailout_->frameClass());
@ -49,14 +49,14 @@ BailoutEnvironment::BailoutEnvironment(JitCompartment *ion, void **sp)
JS_ASSERT(bailoutId_ < BAILOUT_TABLE_SIZE); JS_ASSERT(bailoutId_ < BAILOUT_TABLE_SIZE);
} else { } else {
frameSize_ = bailout_->frameSize(); frameSize_ = bailout_->frameSize();
frame_ = &sp_[sizeof(ExtendedBailoutStack) / STACK_SLOT_SIZE]; frame_ = &sp_[sizeof(ExtendedBailoutStack) / sizeof(void *)];
} }
} }
IonFramePrefix * IonFramePrefix *
BailoutEnvironment::top() const BailoutEnvironment::top() const
{ {
return (IonFramePrefix *)&frame_[frameSize_ / STACK_SLOT_SIZE]; return (IonFramePrefix *)&frame_[frameSize_ / sizeof(void *)];
} }
#endif #endif

View File

@ -7,12 +7,13 @@
#ifndef jit_arm_IonFrames_arm_h #ifndef jit_arm_IonFrames_arm_h
#define jit_arm_IonFrames_arm_h #define jit_arm_IonFrames_arm_h
#include <stdint.h>
#include "jit/shared/IonFrames-shared.h" #include "jit/shared/IonFrames-shared.h"
namespace js { namespace js {
namespace jit { namespace jit {
class IonFramePrefix;
// Layout of the frame prefix. This assumes the stack architecture grows down. // Layout of the frame prefix. This assumes the stack architecture grows down.
// If this is ever not the case, we'll have to refactor. // If this is ever not the case, we'll have to refactor.
class IonCommonFrameLayout class IonCommonFrameLayout
@ -50,26 +51,16 @@ class IonCommonFrameLayout
} }
}; };
// this is the layout of the frame that is used when we enter Ion code from EABI code class IonJSFrameLayout : public IonCommonFrameLayout
class IonEntryFrameLayout : public IonCommonFrameLayout
{ {
public: CalleeToken calleeToken_;
static inline size_t Size() {
return sizeof(IonEntryFrameLayout);
}
};
class IonJSFrameLayout : public IonEntryFrameLayout
{
protected:
void *calleeToken_;
uintptr_t numActualArgs_; uintptr_t numActualArgs_;
public: public:
void *calleeToken() const { CalleeToken calleeToken() const {
return calleeToken_; return calleeToken_;
} }
void replaceCalleeToken(void *calleeToken) { void replaceCalleeToken(CalleeToken calleeToken) {
calleeToken_ = calleeToken; calleeToken_ = calleeToken;
} }
@ -113,6 +104,15 @@ class IonJSFrameLayout : public IonEntryFrameLayout
} }
}; };
// this is the layout of the frame that is used when we enter Ion code from platform ABI code
class IonEntryFrameLayout : public IonJSFrameLayout
{
public:
static inline size_t Size() {
return sizeof(IonEntryFrameLayout);
}
};
class IonRectifierFrameLayout : public IonJSFrameLayout class IonRectifierFrameLayout : public IonJSFrameLayout
{ {
public: public:
@ -121,13 +121,14 @@ class IonRectifierFrameLayout : public IonJSFrameLayout
} }
}; };
class IonUnwoundRectifierFrameLayout : public IonJSFrameLayout // The callee token is now dead.
class IonUnwoundRectifierFrameLayout : public IonRectifierFrameLayout
{ {
public: public:
static inline size_t Size() { static inline size_t Size() {
// On X86, there is a +sizeof(uintptr_t) to account for an extra callee token. // It is not necessary to accout for an extra callee token here because
// This is not needed here because sizeof(IonExitFrame) == sizeof(IonRectifierFrame) // sizeof(IonExitFrameLayout) == sizeof(IonRectifierFrameLayout) due to
// due to extra padding. // extra padding.
return sizeof(IonUnwoundRectifierFrameLayout); return sizeof(IonUnwoundRectifierFrameLayout);
} }
}; };
@ -159,43 +160,13 @@ class IonExitFooterFrame
} }
}; };
class IonOsrFrameLayout : public IonJSFrameLayout
{
public:
static inline size_t Size() {
return sizeof(IonOsrFrameLayout);
}
};
class ICStub;
class IonBaselineStubFrameLayout : public IonCommonFrameLayout
{
public:
static inline size_t Size() {
return sizeof(IonBaselineStubFrameLayout);
}
static inline int reverseOffsetOfStubPtr() {
return -int(sizeof(void *));
}
static inline int reverseOffsetOfSavedFramePtr() {
return -int(2 * sizeof(void *));
}
inline ICStub *maybeStubPtr() {
uint8_t *fp = reinterpret_cast<uint8_t *>(this);
return *reinterpret_cast<ICStub **>(fp + reverseOffsetOfStubPtr());
}
};
class IonNativeExitFrameLayout; class IonNativeExitFrameLayout;
class IonOOLNativeExitFrameLayout; class IonOOLNativeExitFrameLayout;
class IonOOLPropertyOpExitFrameLayout; class IonOOLPropertyOpExitFrameLayout;
class IonOOLProxyExitFrameLayout; class IonOOLProxyExitFrameLayout;
class IonDOMExitFrameLayout; class IonDOMExitFrameLayout;
// this is the frame layout when we are exiting ion code, and about to enter EABI code // this is the frame layout when we are exiting ion code, and about to enter platform ABI code
class IonExitFrameLayout : public IonCommonFrameLayout class IonExitFrameLayout : public IonCommonFrameLayout
{ {
inline uint8_t *top() { inline uint8_t *top() {
@ -273,6 +244,7 @@ class IonExitFrameLayout : public IonCommonFrameLayout
// IonExitFrameLayout. // IonExitFrameLayout.
class IonNativeExitFrameLayout class IonNativeExitFrameLayout
{ {
protected: // only to silence a clang warning about unused private fields
IonExitFooterFrame footer_; IonExitFooterFrame footer_;
IonExitFrameLayout exit_; IonExitFrameLayout exit_;
uintptr_t argc_; uintptr_t argc_;
@ -300,6 +272,7 @@ class IonNativeExitFrameLayout
class IonOOLNativeExitFrameLayout class IonOOLNativeExitFrameLayout
{ {
protected: // only to silence a clang warning about unused private fields
IonExitFooterFrame footer_; IonExitFooterFrame footer_;
IonExitFrameLayout exit_; IonExitFrameLayout exit_;
@ -343,6 +316,7 @@ class IonOOLNativeExitFrameLayout
class IonOOLPropertyOpExitFrameLayout class IonOOLPropertyOpExitFrameLayout
{ {
protected: // only to silence a clang warning about unused private fields
IonExitFooterFrame footer_; IonExitFooterFrame footer_;
IonExitFrameLayout exit_; IonExitFrameLayout exit_;
@ -438,11 +412,12 @@ class IonOOLProxyExitFrameLayout
class IonDOMExitFrameLayout class IonDOMExitFrameLayout
{ {
protected: // only to silence a clang warning about unused private fields
IonExitFooterFrame footer_; IonExitFooterFrame footer_;
IonExitFrameLayout exit_; IonExitFrameLayout exit_;
JSObject *thisObj; JSObject *thisObj;
// We need to split the Value in 2 fields of 32 bits, otherwise the C++ // We need to split the Value into 2 fields of 32 bits, otherwise the C++
// compiler may add some padding between the fields. // compiler may add some padding between the fields.
uint32_t loCalleeResult_; uint32_t loCalleeResult_;
uint32_t hiCalleeResult_; uint32_t hiCalleeResult_;
@ -470,6 +445,7 @@ struct IonDOMMethodExitFrameLayoutTraits;
class IonDOMMethodExitFrameLayout class IonDOMMethodExitFrameLayout
{ {
protected: // only to silence a clang warning about unused private fields
IonExitFooterFrame footer_; IonExitFooterFrame footer_;
IonExitFrameLayout exit_; IonExitFrameLayout exit_;
// This must be the last thing pushed, so as to stay common with // This must be the last thing pushed, so as to stay common with
@ -478,7 +454,7 @@ class IonDOMMethodExitFrameLayout
Value *argv_; Value *argv_;
uintptr_t argc_; uintptr_t argc_;
// We need to split the Value in 2 fields of 32 bits, otherwise the C++ // We need to split the Value into 2 fields of 32 bits, otherwise the C++
// compiler may add some padding between the fields. // compiler may add some padding between the fields.
uint32_t loCalleeResult_; uint32_t loCalleeResult_;
uint32_t hiCalleeResult_; uint32_t hiCalleeResult_;
@ -514,6 +490,36 @@ struct IonDOMMethodExitFrameLayoutTraits {
offsetof(IonDOMMethodExitFrameLayout, argv_); offsetof(IonDOMMethodExitFrameLayout, argv_);
}; };
class IonOsrFrameLayout : public IonJSFrameLayout
{
public:
static inline size_t Size() {
return sizeof(IonOsrFrameLayout);
}
};
class ICStub;
class IonBaselineStubFrameLayout : public IonCommonFrameLayout
{
public:
static inline size_t Size() {
return sizeof(IonBaselineStubFrameLayout);
}
static inline int reverseOffsetOfStubPtr() {
return -int(sizeof(void *));
}
static inline int reverseOffsetOfSavedFramePtr() {
return -int(2 * sizeof(void *));
}
inline ICStub *maybeStubPtr() {
uint8_t *fp = reinterpret_cast<uint8_t *>(this);
return *reinterpret_cast<ICStub **>(fp + reverseOffsetOfStubPtr());
}
};
// An invalidation bailout stack is at the stack pointer for the callee frame. // An invalidation bailout stack is at the stack pointer for the callee frame.
class InvalidationBailoutStack class InvalidationBailoutStack
{ {

View File

@ -2423,7 +2423,7 @@ MacroAssemblerARMCompat::cmpPtr(const Address &lhs, const ImmPtr &rhs)
void void
MacroAssemblerARMCompat::setStackArg(const Register &reg, uint32_t arg) MacroAssemblerARMCompat::setStackArg(const Register &reg, uint32_t arg)
{ {
ma_dataTransferN(IsStore, 32, true, sp, Imm32(arg * STACK_SLOT_SIZE), reg); ma_dataTransferN(IsStore, 32, true, sp, Imm32(arg * sizeof(intptr_t)), reg);
} }
@ -3640,8 +3640,8 @@ MacroAssemblerARMCompat::callWithABIPre(uint32_t *stackAdjust)
if (!dynamicAlignment_) { if (!dynamicAlignment_) {
*stackAdjust += ComputeByteAlignment(framePushed_ + *stackAdjust, StackAlignment); *stackAdjust += ComputeByteAlignment(framePushed_ + *stackAdjust, StackAlignment);
} else { } else {
// STACK_SLOT_SIZE account for the saved stack pointer pushed by setupUnalignedABICall // sizeof(intptr_t) account for the saved stack pointer pushed by setupUnalignedABICall
*stackAdjust += ComputeByteAlignment(*stackAdjust + STACK_SLOT_SIZE, StackAlignment); *stackAdjust += ComputeByteAlignment(*stackAdjust + sizeof(intptr_t), StackAlignment);
} }
reserveStack(*stackAdjust); reserveStack(*stackAdjust);

View File

@ -1143,22 +1143,22 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
// The following functions are exposed for use in platform-shared code. // The following functions are exposed for use in platform-shared code.
void Push(const Register &reg) { void Push(const Register &reg) {
ma_push(reg); ma_push(reg);
adjustFrame(STACK_SLOT_SIZE); adjustFrame(sizeof(intptr_t));
} }
void Push(const Imm32 imm) { void Push(const Imm32 imm) {
push(imm); push(imm);
adjustFrame(STACK_SLOT_SIZE); adjustFrame(sizeof(intptr_t));
} }
void Push(const ImmWord imm) { void Push(const ImmWord imm) {
push(imm); push(imm);
adjustFrame(STACK_SLOT_SIZE); adjustFrame(sizeof(intptr_t));
} }
void Push(const ImmPtr imm) { void Push(const ImmPtr imm) {
Push(ImmWord(uintptr_t(imm.value))); Push(ImmWord(uintptr_t(imm.value)));
} }
void Push(const ImmGCPtr ptr) { void Push(const ImmGCPtr ptr) {
push(ptr); push(ptr);
adjustFrame(STACK_SLOT_SIZE); adjustFrame(sizeof(intptr_t));
} }
void Push(const FloatRegister &t) { void Push(const FloatRegister &t) {
VFPRegister r = VFPRegister(t); VFPRegister r = VFPRegister(t);
@ -1176,19 +1176,19 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
void PushWithPadding(const Register &reg, const Imm32 extraSpace) { void PushWithPadding(const Register &reg, const Imm32 extraSpace) {
pushWithPadding(reg, extraSpace); pushWithPadding(reg, extraSpace);
adjustFrame(STACK_SLOT_SIZE + extraSpace.value); adjustFrame(sizeof(intptr_t) + extraSpace.value);
} }
void PushWithPadding(const Imm32 imm, const Imm32 extraSpace) { void PushWithPadding(const Imm32 imm, const Imm32 extraSpace) {
pushWithPadding(imm, extraSpace); pushWithPadding(imm, extraSpace);
adjustFrame(STACK_SLOT_SIZE + extraSpace.value); adjustFrame(sizeof(intptr_t) + extraSpace.value);
} }
void Pop(const Register &reg) { void Pop(const Register &reg) {
ma_pop(reg); ma_pop(reg);
adjustFrame(-STACK_SLOT_SIZE); adjustFrame(-sizeof(intptr_t));
} }
void implicitPop(uint32_t args) { void implicitPop(uint32_t args) {
JS_ASSERT(args % STACK_SLOT_SIZE == 0); JS_ASSERT(args % sizeof(intptr_t) == 0);
adjustFrame(-args); adjustFrame(-args);
} }
uint32_t framePushed() const { uint32_t framePushed() const {

View File

@ -14,9 +14,10 @@
namespace js { namespace js {
namespace jit { namespace jit {
// Layout of the frame prefix. This assumes the stack architecture grows down.
// If this is ever not the case, we'll have to refactor.
class IonCommonFrameLayout class IonCommonFrameLayout
{ {
private:
uint8_t *returnAddress_; uint8_t *returnAddress_;
uintptr_t descriptor_; uintptr_t descriptor_;
@ -52,15 +53,15 @@ class IonCommonFrameLayout
class IonJSFrameLayout : public IonCommonFrameLayout class IonJSFrameLayout : public IonCommonFrameLayout
{ {
void *calleeToken_; CalleeToken calleeToken_;
uintptr_t numActualArgs_; uintptr_t numActualArgs_;
public: public:
CalleeToken calleeToken() const { CalleeToken calleeToken() const {
return calleeToken_; return calleeToken_;
} }
void replaceCalleeToken(void *value) { void replaceCalleeToken(CalleeToken calleeToken) {
calleeToken_ = value; calleeToken_ = calleeToken;
} }
static size_t offsetOfCalleeToken() { static size_t offsetOfCalleeToken() {
@ -103,6 +104,7 @@ class IonJSFrameLayout : public IonCommonFrameLayout
} }
}; };
// this is the layout of the frame that is used when we enter Ion code from platform ABI code
class IonEntryFrameLayout : public IonJSFrameLayout class IonEntryFrameLayout : public IonJSFrameLayout
{ {
public: public:
@ -124,6 +126,9 @@ class IonUnwoundRectifierFrameLayout : public IonRectifierFrameLayout
{ {
public: public:
static inline size_t Size() { static inline size_t Size() {
// It is not necessary to accout for an extra callee token here because
// sizeof(IonExitFrameLayout) == sizeof(IonRectifierFrameLayout) due to
// extra padding.
return sizeof(IonUnwoundRectifierFrameLayout); return sizeof(IonUnwoundRectifierFrameLayout);
} }
}; };
@ -161,6 +166,7 @@ class IonOOLPropertyOpExitFrameLayout;
class IonOOLProxyExitFrameLayout; class IonOOLProxyExitFrameLayout;
class IonDOMExitFrameLayout; class IonDOMExitFrameLayout;
// this is the frame layout when we are exiting ion code, and about to enter platform ABI code
class IonExitFrameLayout : public IonCommonFrameLayout class IonExitFrameLayout : public IonCommonFrameLayout
{ {
inline uint8_t *top() { inline uint8_t *top() {
@ -234,6 +240,8 @@ class IonExitFrameLayout : public IonCommonFrameLayout
} }
}; };
// Cannot inherit implementa<tion since we need to extend the top of
// IonExitFrameLayout.
class IonNativeExitFrameLayout class IonNativeExitFrameLayout
{ {
protected: // only to silence a clang warning about unused private fields protected: // only to silence a clang warning about unused private fields
@ -241,7 +249,7 @@ class IonNativeExitFrameLayout
IonExitFrameLayout exit_; IonExitFrameLayout exit_;
uintptr_t argc_; uintptr_t argc_;
// We need to split the Value in 2 field of 32 bits, otherwise the C++ // We need to split the Value into 2 fields of 32 bits, otherwise the C++
// compiler may add some padding between the fields. // compiler may add some padding between the fields.
uint32_t loCalleeResult_; uint32_t loCalleeResult_;
uint32_t hiCalleeResult_; uint32_t hiCalleeResult_;
@ -284,7 +292,7 @@ class IonOOLNativeExitFrameLayout
public: public:
static inline size_t Size(size_t argc) { static inline size_t Size(size_t argc) {
// The Frame accounts for the callee/result and |this|, so we only needs args. // The frame accounts for the callee/result and |this|, so we only need args.
return sizeof(IonOOLNativeExitFrameLayout) + (argc * sizeof(Value)); return sizeof(IonOOLNativeExitFrameLayout) + (argc * sizeof(Value));
} }
@ -409,7 +417,7 @@ class IonDOMExitFrameLayout
IonExitFrameLayout exit_; IonExitFrameLayout exit_;
JSObject *thisObj; JSObject *thisObj;
// We need to split the Value in 2 fields of 32 bits, otherwise the C++ // We need to split the Value into 2 fields of 32 bits, otherwise the C++
// compiler may add some padding between the fields. // compiler may add some padding between the fields.
uint32_t loCalleeResult_; uint32_t loCalleeResult_;
uint32_t hiCalleeResult_; uint32_t hiCalleeResult_;
@ -463,6 +471,7 @@ class IonDOMMethodExitFrameLayout
} }
inline Value *vp() { inline Value *vp() {
// The code in visitCallDOMNative depends on this static assert holding
JS_STATIC_ASSERT(offsetof(IonDOMMethodExitFrameLayout, loCalleeResult_) == JS_STATIC_ASSERT(offsetof(IonDOMMethodExitFrameLayout, loCalleeResult_) ==
(offsetof(IonDOMMethodExitFrameLayout, argc_) + sizeof(uintptr_t))); (offsetof(IonDOMMethodExitFrameLayout, argc_) + sizeof(uintptr_t)));
return reinterpret_cast<Value*>(&loCalleeResult_); return reinterpret_cast<Value*>(&loCalleeResult_);
@ -538,7 +547,7 @@ class InvalidationBailoutStack
void checkInvariants() const; void checkInvariants() const;
}; };
} } // namespace jit
} } // namespace js
#endif /* jit_shared_IonFrames_x86_shared_h */ #endif /* jit_shared_IonFrames_x86_shared_h */

View File

@ -198,7 +198,7 @@ class MacroAssemblerX86Shared : public Assembler
template <typename T> template <typename T>
void Push(const T &t) { void Push(const T &t) {
push(t); push(t);
framePushed_ += STACK_SLOT_SIZE; framePushed_ += sizeof(intptr_t);
} }
void Push(const FloatRegister &t) { void Push(const FloatRegister &t) {
push(t); push(t);
@ -215,14 +215,14 @@ class MacroAssemblerX86Shared : public Assembler
template <typename T> template <typename T>
void Pop(const T &t) { void Pop(const T &t) {
pop(t); pop(t);
framePushed_ -= STACK_SLOT_SIZE; framePushed_ -= sizeof(intptr_t);
} }
void Pop(const FloatRegister &t) { void Pop(const FloatRegister &t) {
pop(t); pop(t);
framePushed_ -= sizeof(double); framePushed_ -= sizeof(double);
} }
void implicitPop(uint32_t args) { void implicitPop(uint32_t args) {
JS_ASSERT(args % STACK_SLOT_SIZE == 0); JS_ASSERT(args % sizeof(intptr_t) == 0);
framePushed_ -= args; framePushed_ -= args;
} }
uint32_t framePushed() const { uint32_t framePushed() const {

View File

@ -12,9 +12,6 @@
namespace js { namespace js {
namespace jit { namespace jit {
static const ptrdiff_t STACK_SLOT_SIZE = 8;
static const uint32_t DOUBLE_STACK_ALIGNMENT = 1;
// In bytes: slots needed for potential memory->memory move spills. // In bytes: slots needed for potential memory->memory move spills.
// +8 for cycles // +8 for cycles
// +8 for gpr spills // +8 for gpr spills
@ -27,9 +24,6 @@ static const uint32_t ShadowStackSpace = 32;
static const uint32_t ShadowStackSpace = 0; static const uint32_t ShadowStackSpace = 0;
#endif #endif
// An offset that is illegal for a local variable's stack allocation.
static const int32_t INVALID_STACK_SLOT = -1;
class Registers { class Registers {
public: public:
typedef JSC::X86Registers::RegisterID Code; typedef JSC::X86Registers::RegisterID Code;

View File

@ -198,7 +198,7 @@ MacroAssemblerX64::callWithABIPre(uint32_t *stackAdjust)
if (dynamicAlignment_) { if (dynamicAlignment_) {
*stackAdjust = stackForCall_ *stackAdjust = stackForCall_
+ ComputeByteAlignment(stackForCall_ + STACK_SLOT_SIZE, + ComputeByteAlignment(stackForCall_ + sizeof(intptr_t),
StackAlignment); StackAlignment);
} else { } else {
*stackAdjust = stackForCall_ *stackAdjust = stackForCall_

View File

@ -11,8 +11,6 @@
namespace js { namespace js {
namespace jit { namespace jit {
static const ptrdiff_t STACK_SLOT_SIZE = 4;
static const uint32_t DOUBLE_STACK_ALIGNMENT = 2;
// In bytes: slots needed for potential memory->memory move spills. // In bytes: slots needed for potential memory->memory move spills.
// +8 for cycles // +8 for cycles
@ -23,9 +21,6 @@ static const uint32_t ION_FRAME_SLACK_SIZE = 20;
// Only Win64 requires shadow stack space. // Only Win64 requires shadow stack space.
static const uint32_t ShadowStackSpace = 0; static const uint32_t ShadowStackSpace = 0;
// An offset that is illegal for a local variable's stack allocation.
static const int32_t INVALID_STACK_SLOT = -1;
// These offsets are specific to nunboxing, and capture offsets into the // These offsets are specific to nunboxing, and capture offsets into the
// components of a js::Value. // components of a js::Value.
static const int32_t NUNBOX32_TYPE_OFFSET = 4; static const int32_t NUNBOX32_TYPE_OFFSET = 4;

View File

@ -196,7 +196,7 @@ MacroAssemblerX86::callWithABIPre(uint32_t *stackAdjust)
if (dynamicAlignment_) { if (dynamicAlignment_) {
*stackAdjust = stackForCall_ *stackAdjust = stackForCall_
+ ComputeByteAlignment(stackForCall_ + STACK_SLOT_SIZE, + ComputeByteAlignment(stackForCall_ + sizeof(intptr_t),
StackAlignment); StackAlignment);
} else { } else {
*stackAdjust = stackForCall_ *stackAdjust = stackForCall_

View File

@ -676,7 +676,7 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
} }
void setStackArg(const Register &reg, uint32_t arg) { void setStackArg(const Register &reg, uint32_t arg) {
movl(reg, Operand(esp, arg * STACK_SLOT_SIZE)); movl(reg, Operand(esp, arg * sizeof(intptr_t)));
} }
// Type testing instructions can take a tag in a register or a // Type testing instructions can take a tag in a register or a