mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
[JAEGER] Added JSOP_GLOBALINC, JSOP_GLOBALDEC, JSOP_INCGLOBAL, JSOP_DECGLOBAL.
This commit is contained in:
parent
aad4b0b970
commit
bf470f73e5
@ -349,6 +349,15 @@ mjit::Compiler::generateMethod()
|
|||||||
jsop_setglobal(GET_SLOTNO(PC));
|
jsop_setglobal(GET_SLOTNO(PC));
|
||||||
END_CASE(JSOP_SETGLOBAL)
|
END_CASE(JSOP_SETGLOBAL)
|
||||||
|
|
||||||
|
BEGIN_CASE(JSOP_INCGLOBAL)
|
||||||
|
BEGIN_CASE(JSOP_DECGLOBAL)
|
||||||
|
BEGIN_CASE(JSOP_GLOBALINC)
|
||||||
|
BEGIN_CASE(JSOP_GLOBALDEC)
|
||||||
|
/* Advances PC automatically. */
|
||||||
|
jsop_globalinc(op, GET_SLOTNO(PC));
|
||||||
|
break;
|
||||||
|
END_CASE(JSOP_GLOBALINC)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Sorry, this opcode isn't implemented yet. */
|
/* Sorry, this opcode isn't implemented yet. */
|
||||||
#ifdef JS_METHODJIT_SPEW
|
#ifdef JS_METHODJIT_SPEW
|
||||||
|
@ -129,6 +129,7 @@ class Compiler
|
|||||||
|
|
||||||
/* Fast opcodes. */
|
/* Fast opcodes. */
|
||||||
void jsop_bitop(JSOp op);
|
void jsop_bitop(JSOp op);
|
||||||
|
void jsop_globalinc(JSOp op, uint32 index);
|
||||||
|
|
||||||
#define STUB_CALL_TYPE(type) \
|
#define STUB_CALL_TYPE(type) \
|
||||||
Call stubCall(type stub, Uses uses, Defs defs) { \
|
Call stubCall(type stub, Uses uses, Defs defs) { \
|
||||||
|
@ -115,7 +115,8 @@ FrameState::pop()
|
|||||||
inline void
|
inline void
|
||||||
FrameState::freeReg(RegisterID reg)
|
FrameState::freeReg(RegisterID reg)
|
||||||
{
|
{
|
||||||
forgetReg(reg);
|
JS_ASSERT(regstate[reg].fe == NULL);
|
||||||
|
freeRegs.putReg(reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
@ -215,6 +216,25 @@ FrameState::pushTypedPayload(uint32 tag, RegisterID payload)
|
|||||||
regstate[payload] = RegisterState(fe, RematInfo::DATA, true);
|
regstate[payload] = RegisterState(fe, RematInfo::DATA, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
FrameState::pushUntypedPayload(uint32 tag, RegisterID payload)
|
||||||
|
{
|
||||||
|
JS_ASSERT(!freeRegs.hasReg(payload));
|
||||||
|
|
||||||
|
FrameEntry *fe = rawPush();
|
||||||
|
|
||||||
|
/* The forceful type sync will assert otherwise. */
|
||||||
|
#ifdef DEBUG
|
||||||
|
fe->type.unsync();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
masm.storeTypeTag(Imm32(tag), addressOf(fe));
|
||||||
|
fe->type.sync();
|
||||||
|
fe->data.unsync();
|
||||||
|
fe->data.setRegister(payload);
|
||||||
|
regstate[payload] = RegisterState(fe, RematInfo::DATA, true);
|
||||||
|
}
|
||||||
|
|
||||||
inline JSC::MacroAssembler::RegisterID
|
inline JSC::MacroAssembler::RegisterID
|
||||||
FrameState::tempRegForType(FrameEntry *fe)
|
FrameState::tempRegForType(FrameEntry *fe)
|
||||||
{
|
{
|
||||||
@ -245,26 +265,10 @@ FrameState::tempRegForData(FrameEntry *fe)
|
|||||||
return reg;
|
return reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JSC::MacroAssembler::RegisterID
|
inline bool
|
||||||
FrameState::ownRegForData(FrameEntry *fe)
|
FrameState::shouldAvoidTypeRemat(FrameEntry *fe)
|
||||||
{
|
{
|
||||||
JS_ASSERT(!fe->data.isConstant());
|
return fe->type.inMemory();
|
||||||
|
|
||||||
if (fe->data.inRegister()) {
|
|
||||||
/* Remove ownership of this register. */
|
|
||||||
RegisterID reg = fe->data.reg();
|
|
||||||
JS_ASSERT(regstate[reg].fe == fe);
|
|
||||||
JS_ASSERT(regstate[reg].type == RematInfo::DATA);
|
|
||||||
regstate[reg].fe = NULL;
|
|
||||||
fe->data.invalidate();
|
|
||||||
return reg;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* :XXX: X64 */
|
|
||||||
|
|
||||||
RegisterID reg = alloc(fe, RematInfo::DATA, true);
|
|
||||||
masm.loadData32(addressOf(fe), reg);
|
|
||||||
return reg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
@ -306,6 +310,7 @@ FrameState::syncData(const FrameEntry *fe, Assembler &masm) const
|
|||||||
inline void
|
inline void
|
||||||
FrameState::learnType(FrameEntry *fe, uint32 tag)
|
FrameState::learnType(FrameEntry *fe, uint32 tag)
|
||||||
{
|
{
|
||||||
|
JS_ASSERT(!fe->type.inRegister());
|
||||||
fe->setTypeTag(tag);
|
fe->setTypeTag(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,6 +322,14 @@ FrameState::addressOf(const FrameEntry *fe) const
|
|||||||
return Address(Assembler::FpReg, sizeof(JSStackFrame) + sizeof(Value) * index);
|
return Address(Assembler::FpReg, sizeof(JSStackFrame) + sizeof(Value) * index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline JSC::MacroAssembler::Jump
|
||||||
|
FrameState::testInt32(Assembler::Condition cond, FrameEntry *fe)
|
||||||
|
{
|
||||||
|
if (shouldAvoidTypeRemat(fe))
|
||||||
|
return masm.testInt32(cond, addressOf(fe));
|
||||||
|
return masm.testInt32(cond, tempRegForType(fe));
|
||||||
|
}
|
||||||
|
|
||||||
} /* namspace mjit */
|
} /* namspace mjit */
|
||||||
} /* namspace js */
|
} /* namspace js */
|
||||||
|
|
||||||
|
@ -124,11 +124,11 @@ FrameState::storeTo(FrameEntry *fe, Address address, bool popped)
|
|||||||
JS_ASSERT(!freeRegs.hasReg(address.base));
|
JS_ASSERT(!freeRegs.hasReg(address.base));
|
||||||
|
|
||||||
if (fe->data.inRegister()) {
|
if (fe->data.inRegister()) {
|
||||||
masm.storeData32(fe->data.reg(), addressOf(fe));
|
masm.storeData32(fe->data.reg(), address);
|
||||||
} else {
|
} else {
|
||||||
RegisterID reg = popped ? alloc() : alloc(fe, RematInfo::DATA, true);
|
RegisterID reg = popped ? alloc() : alloc(fe, RematInfo::DATA, true);
|
||||||
masm.loadData32(addressOf(fe), reg);
|
masm.loadData32(addressOf(fe), reg);
|
||||||
masm.storeData32(reg, addressOf(fe));
|
masm.storeData32(reg, address);
|
||||||
if (popped)
|
if (popped)
|
||||||
freeReg(reg);
|
freeReg(reg);
|
||||||
else
|
else
|
||||||
@ -136,13 +136,13 @@ FrameState::storeTo(FrameEntry *fe, Address address, bool popped)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fe->isTypeKnown()) {
|
if (fe->isTypeKnown()) {
|
||||||
masm.storeTypeTag(Imm32(fe->getTypeTag()), addressOf(fe));
|
masm.storeTypeTag(Imm32(fe->getTypeTag()), address);
|
||||||
} else if (fe->type.inRegister()) {
|
} else if (fe->type.inRegister()) {
|
||||||
masm.storeTypeTag(fe->type.reg(), addressOf(fe));
|
masm.storeTypeTag(fe->type.reg(), address);
|
||||||
} else {
|
} else {
|
||||||
RegisterID reg = popped ? alloc() : alloc(fe, RematInfo::TYPE, true);
|
RegisterID reg = popped ? alloc() : alloc(fe, RematInfo::TYPE, true);
|
||||||
masm.loadTypeTag(addressOf(fe), reg);
|
masm.loadTypeTag(addressOf(fe), reg);
|
||||||
masm.storeTypeTag(reg, addressOf(fe));
|
masm.storeTypeTag(reg, address);
|
||||||
if (popped)
|
if (popped)
|
||||||
freeReg(reg);
|
freeReg(reg);
|
||||||
else
|
else
|
||||||
@ -252,3 +252,57 @@ FrameState::merge(Assembler &masm, uint32 iVD) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSC::MacroAssembler::RegisterID
|
||||||
|
FrameState::copyData(FrameEntry *fe)
|
||||||
|
{
|
||||||
|
JS_ASSERT(!fe->data.isConstant());
|
||||||
|
|
||||||
|
if (fe->data.inRegister()) {
|
||||||
|
RegisterID reg = fe->data.reg();
|
||||||
|
if (freeRegs.empty()) {
|
||||||
|
if (!fe->data.synced())
|
||||||
|
syncData(fe, masm);
|
||||||
|
fe->data.setMemory();
|
||||||
|
regstate[reg].fe = NULL;
|
||||||
|
} else {
|
||||||
|
RegisterID newReg = alloc();
|
||||||
|
masm.move(reg, newReg);
|
||||||
|
reg = newReg;
|
||||||
|
}
|
||||||
|
return reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisterID reg = alloc();
|
||||||
|
|
||||||
|
if (!freeRegs.empty())
|
||||||
|
masm.move(tempRegForData(fe), reg);
|
||||||
|
else
|
||||||
|
masm.loadData32(addressOf(fe),reg);
|
||||||
|
|
||||||
|
return reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSC::MacroAssembler::RegisterID
|
||||||
|
FrameState::ownRegForData(FrameEntry *fe)
|
||||||
|
{
|
||||||
|
JS_ASSERT(!fe->data.isConstant());
|
||||||
|
|
||||||
|
/* :XXX: X64 */
|
||||||
|
|
||||||
|
if (fe->data.inRegister()) {
|
||||||
|
RegisterID reg = fe->data.reg();
|
||||||
|
/* Remove ownership of this register. */
|
||||||
|
JS_ASSERT(regstate[reg].fe == fe);
|
||||||
|
JS_ASSERT(regstate[reg].type == RematInfo::DATA);
|
||||||
|
regstate[reg].fe = NULL;
|
||||||
|
fe->data.invalidate();
|
||||||
|
return reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_ASSERT(fe->data.inMemory());
|
||||||
|
|
||||||
|
RegisterID reg = alloc();
|
||||||
|
masm.loadData32(addressOf(fe), reg);
|
||||||
|
return reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -89,6 +89,7 @@ class FrameState
|
|||||||
{
|
{
|
||||||
typedef JSC::MacroAssembler::RegisterID RegisterID;
|
typedef JSC::MacroAssembler::RegisterID RegisterID;
|
||||||
typedef JSC::MacroAssembler::Address Address;
|
typedef JSC::MacroAssembler::Address Address;
|
||||||
|
typedef JSC::MacroAssembler::Jump Jump;
|
||||||
typedef JSC::MacroAssembler::Imm32 Imm32;
|
typedef JSC::MacroAssembler::Imm32 Imm32;
|
||||||
|
|
||||||
struct Tracker {
|
struct Tracker {
|
||||||
@ -160,6 +161,13 @@ class FrameState
|
|||||||
*/
|
*/
|
||||||
inline void pushTypedPayload(uint32 tag, RegisterID payload);
|
inline void pushTypedPayload(uint32 tag, RegisterID payload);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pushes a known type and allocated payload onto the operation stack.
|
||||||
|
* This must be used when the type is known, but cannot be propagated
|
||||||
|
* because it is not known to be correct at a slow-path merge point.
|
||||||
|
*/
|
||||||
|
inline void pushUntypedPayload(uint32 tag, RegisterID payload);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pops a value off the operation stack, freeing any of its resources.
|
* Pops a value off the operation stack, freeing any of its resources.
|
||||||
*/
|
*/
|
||||||
@ -172,21 +180,42 @@ class FrameState
|
|||||||
inline void popn(uint32 n);
|
inline void popn(uint32 n);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocates a temporary register for a FrameEntry's type.
|
* Allocates a temporary register for a FrameEntry's type. The register
|
||||||
|
* can be spilled or clobbered by the frame. The compiler may only operate
|
||||||
|
* on it temporarily, and must take care not to clobber it.
|
||||||
*/
|
*/
|
||||||
inline RegisterID tempRegForType(FrameEntry *fe);
|
inline RegisterID tempRegForType(FrameEntry *fe);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocates a data register for a FrameEntry's type.
|
* Returns a register that is guaranteed to contain the frame entry's
|
||||||
|
* data payload. The compiler may not modify the contents of the register,
|
||||||
|
* though it may explicitly free it.
|
||||||
*/
|
*/
|
||||||
inline RegisterID tempRegForData(FrameEntry *fe);
|
inline RegisterID tempRegForData(FrameEntry *fe);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocates a register for a FrameEntry's data, such that the compiler
|
* Allocates a register for a FrameEntry's data, such that the compiler
|
||||||
* can modify it in-place. If the slot already has a temporary register,
|
* can modify it in-place.
|
||||||
* it is cleared, and thus the entry is invalidated!
|
*
|
||||||
|
* The caller guarantees the FrameEntry will not be observed again. This
|
||||||
|
* allows the compiler to avoid spilling. Only call this if the FE is
|
||||||
|
* going to be popped before stubcc joins/guards or the end of the current
|
||||||
|
* opcode.
|
||||||
*/
|
*/
|
||||||
inline RegisterID ownRegForData(FrameEntry *fe);
|
RegisterID ownRegForData(FrameEntry *fe);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocates a register for a FrameEntry's data, such that the compiler
|
||||||
|
* can modify it in-place. The actual FE is not modified.
|
||||||
|
*/
|
||||||
|
RegisterID copyData(FrameEntry *fe);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Types don't always have to be in registers, sometimes the compiler
|
||||||
|
* can use addresses and avoid spilling. If this FrameEntry has a synced
|
||||||
|
* address and no register, this returns true.
|
||||||
|
*/
|
||||||
|
inline bool shouldAvoidTypeRemat(FrameEntry *fe);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Payloads don't always have to be in registers, sometimes the compiler
|
* Payloads don't always have to be in registers, sometimes the compiler
|
||||||
@ -253,6 +282,12 @@ class FrameState
|
|||||||
*/
|
*/
|
||||||
inline void learnType(FrameEntry *fe, uint32 tag);
|
inline void learnType(FrameEntry *fe, uint32 tag);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function. Tests if a slot's type is an integer. Condition should
|
||||||
|
* be Equal or NotEqual.
|
||||||
|
*/
|
||||||
|
inline Jump testInt32(Assembler::Condition cond, FrameEntry *fe);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the current stack depth of the frame.
|
* Returns the current stack depth of the frame.
|
||||||
*/
|
*/
|
||||||
|
@ -180,7 +180,7 @@ extern "C" void JaegerStubVeneer(void);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef void (JS_FASTCALL *VoidStub)(VMFrame &);
|
typedef void (JS_FASTCALL *VoidStub)(VMFrame &);
|
||||||
typedef void (JS_FASTCALL *VoidVpStub)(VMFrame &, jsval *);
|
typedef void (JS_FASTCALL *VoidVpStub)(VMFrame &, Value *);
|
||||||
typedef void (JS_FASTCALL *VoidStubUInt32)(VMFrame &, uint32);
|
typedef void (JS_FASTCALL *VoidStubUInt32)(VMFrame &, uint32);
|
||||||
typedef void (JS_FASTCALL *VoidStubInt32)(VMFrame &, int32);
|
typedef void (JS_FASTCALL *VoidStubInt32)(VMFrame &, int32);
|
||||||
typedef JSBool (JS_FASTCALL *BoolStub)(VMFrame &);
|
typedef JSBool (JS_FASTCALL *BoolStub)(VMFrame &);
|
||||||
|
@ -72,12 +72,10 @@ struct RematInfo {
|
|||||||
PhysLoc_Constant,
|
PhysLoc_Constant,
|
||||||
|
|
||||||
/* Backing bits are in a register. */
|
/* Backing bits are in a register. */
|
||||||
PhysLoc_Register
|
PhysLoc_Register,
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
/* Backing bits are invalid/unknown. */
|
/* Backing bits are invalid/unknown. */
|
||||||
, PhysLoc_Invalid
|
PhysLoc_Invalid
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void setRegister(RegisterID reg) {
|
void setRegister(RegisterID reg) {
|
||||||
@ -96,9 +94,7 @@ struct RematInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void invalidate() {
|
void invalidate() {
|
||||||
#ifdef DEBUG
|
|
||||||
location_ = PhysLoc_Invalid;
|
location_ = PhysLoc_Invalid;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setConstant() { location_ = PhysLoc_Constant; }
|
void setConstant() { location_ = PhysLoc_Constant; }
|
||||||
|
@ -624,3 +624,59 @@ mjit::stubs::BitAnd(VMFrame &f)
|
|||||||
f.regs.sp[-2].setInt32(i);
|
f.regs.sp[-2].setInt32(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <int32 N>
|
||||||
|
static inline bool
|
||||||
|
PostInc(VMFrame &f, Value *vp)
|
||||||
|
{
|
||||||
|
double d;
|
||||||
|
if (!ValueToNumber(f.cx, *vp, &d))
|
||||||
|
return false;
|
||||||
|
f.regs.sp++;
|
||||||
|
f.regs.sp[-1].setDouble(d);
|
||||||
|
d += N;
|
||||||
|
vp->setDouble(d);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int32 N>
|
||||||
|
static inline bool
|
||||||
|
PreInc(VMFrame &f, Value *vp)
|
||||||
|
{
|
||||||
|
double d;
|
||||||
|
if (!ValueToNumber(f.cx, *vp, &d))
|
||||||
|
return false;
|
||||||
|
d += N;
|
||||||
|
vp->setDouble(d);
|
||||||
|
f.regs.sp++;
|
||||||
|
f.regs.sp[-1].setDouble(d);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JS_FASTCALL
|
||||||
|
stubs::VpInc(VMFrame &f, Value *vp)
|
||||||
|
{
|
||||||
|
if (!PostInc<1>(f, vp))
|
||||||
|
THROW();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JS_FASTCALL
|
||||||
|
stubs::VpDec(VMFrame &f, Value *vp)
|
||||||
|
{
|
||||||
|
if (!PostInc<-1>(f, vp))
|
||||||
|
THROW();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JS_FASTCALL
|
||||||
|
stubs::DecVp(VMFrame &f, Value *vp)
|
||||||
|
{
|
||||||
|
if (!PreInc<-1>(f, vp))
|
||||||
|
THROW();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JS_FASTCALL
|
||||||
|
stubs::IncVp(VMFrame &f, Value *vp)
|
||||||
|
{
|
||||||
|
if (!PreInc<1>(f, vp))
|
||||||
|
THROW();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,11 @@ JSObject * JS_FASTCALL BindName(VMFrame &f);
|
|||||||
void JS_FASTCALL SetName(VMFrame &f, uint32 index);
|
void JS_FASTCALL SetName(VMFrame &f, uint32 index);
|
||||||
void JS_FASTCALL Name(VMFrame &f, uint32 index);
|
void JS_FASTCALL Name(VMFrame &f, uint32 index);
|
||||||
|
|
||||||
|
void JS_FASTCALL VpInc(VMFrame &f, Value *vp);
|
||||||
|
void JS_FASTCALL VpDec(VMFrame &f, Value *vp);
|
||||||
|
void JS_FASTCALL DecVp(VMFrame &f, Value *vp);
|
||||||
|
void JS_FASTCALL IncVp(VMFrame &f, Value *vp);
|
||||||
|
|
||||||
void JS_FASTCALL BitAnd(VMFrame &f);
|
void JS_FASTCALL BitAnd(VMFrame &f);
|
||||||
|
|
||||||
}}} /* namespace stubs,mjit,js */
|
}}} /* namespace stubs,mjit,js */
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "StubCalls.h"
|
||||||
#include "StubCompiler.h"
|
#include "StubCompiler.h"
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
#include "assembler/assembler/LinkBuffer.h"
|
#include "assembler/assembler/LinkBuffer.h"
|
||||||
@ -106,10 +107,16 @@ typedef JSC::MacroAssembler::Imm32 Imm32;
|
|||||||
|
|
||||||
JSC::MacroAssembler::Call
|
JSC::MacroAssembler::Call
|
||||||
StubCompiler::stubCall(void *ptr)
|
StubCompiler::stubCall(void *ptr)
|
||||||
|
{
|
||||||
|
return stubCall(ptr, frame.stackDepth() + script->nfixed);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSC::MacroAssembler::Call
|
||||||
|
StubCompiler::stubCall(void *ptr, uint32 slots)
|
||||||
{
|
{
|
||||||
generation++;
|
generation++;
|
||||||
JaegerSpew(JSpew_Insns, " ---- BEGIN SLOW CALL CODE ---- \n");
|
JaegerSpew(JSpew_Insns, " ---- BEGIN SLOW CALL CODE ---- \n");
|
||||||
Call cl = masm.stubCall(ptr, cc.getPC(), frame.stackDepth() + script->nfixed);
|
Call cl = masm.stubCall(ptr, cc.getPC(), slots);
|
||||||
JaegerSpew(JSpew_Insns, " ---- END SLOW CALL CODE ---- \n");
|
JaegerSpew(JSpew_Insns, " ---- END SLOW CALL CODE ---- \n");
|
||||||
return cl;
|
return cl;
|
||||||
}
|
}
|
||||||
@ -133,3 +140,38 @@ StubCompiler::finalize(uint8 *ncode)
|
|||||||
masm.finalize(ncode);
|
masm.finalize(ncode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSC::MacroAssembler::Call
|
||||||
|
StubCompiler::vpInc(JSOp op, bool pushed)
|
||||||
|
{
|
||||||
|
uint32 slots = frame.stackDepth() + script->nfixed;
|
||||||
|
if (pushed) {
|
||||||
|
JS_ASSERT(frame.stackDepth());
|
||||||
|
slots--;
|
||||||
|
}
|
||||||
|
|
||||||
|
VoidVpStub stub = NULL;
|
||||||
|
switch (op) {
|
||||||
|
case JSOP_GLOBALINC:
|
||||||
|
stub = stubs::VpInc;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JSOP_GLOBALDEC:
|
||||||
|
stub = stubs::VpDec;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JSOP_INCGLOBAL:
|
||||||
|
stub = stubs::IncVp;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JSOP_DECGLOBAL:
|
||||||
|
stub = stubs::DecVp;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
JS_NOT_REACHED("unknown incdec op");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stubCall(JS_FUNC_TO_DATA_PTR(void *, stub), slots);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -72,7 +72,11 @@ class StubCompiler
|
|||||||
Compiler &cc;
|
Compiler &cc;
|
||||||
FrameState &frame;
|
FrameState &frame;
|
||||||
JSScript *script;
|
JSScript *script;
|
||||||
|
|
||||||
|
public:
|
||||||
Assembler masm;
|
Assembler masm;
|
||||||
|
|
||||||
|
private:
|
||||||
uint32 generation;
|
uint32 generation;
|
||||||
uint32 lastGeneration;
|
uint32 lastGeneration;
|
||||||
|
|
||||||
@ -94,6 +98,8 @@ class StubCompiler
|
|||||||
return masm.buffer();
|
return masm.buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Call vpInc(JSOp op, bool pushed);
|
||||||
|
|
||||||
#define STUB_CALL_TYPE(type) \
|
#define STUB_CALL_TYPE(type) \
|
||||||
Call call(type stub) { \
|
Call call(type stub) { \
|
||||||
return stubCall(JS_FUNC_TO_DATA_PTR(void *, stub)); \
|
return stubCall(JS_FUNC_TO_DATA_PTR(void *, stub)); \
|
||||||
@ -122,6 +128,7 @@ class StubCompiler
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Call stubCall(void *ptr);
|
Call stubCall(void *ptr);
|
||||||
|
Call stubCall(void *ptr, uint32 slots);
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namepsace mjit */
|
} /* namepsace mjit */
|
||||||
|
@ -91,6 +91,14 @@ class Assembler : public BaseAssembler
|
|||||||
if (!v.isUndefined())
|
if (!v.isUndefined())
|
||||||
store32(Imm32(jv.s.payload.u32), payloadOf(address));
|
store32(Imm32(jv.s.payload.u32), payloadOf(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Jump testInt32(Assembler::Condition cond, RegisterID reg) {
|
||||||
|
return branch32(cond, reg, Imm32(JSVAL_MASK32_INT32));
|
||||||
|
}
|
||||||
|
|
||||||
|
Jump testInt32(Assembler::Condition cond, Address address) {
|
||||||
|
return branch32(cond, tagOf(address), Imm32(JSVAL_MASK32_INT32));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
@ -85,16 +85,14 @@ mjit::Compiler::jsop_bitop(JSOp op)
|
|||||||
/* Test the types. */
|
/* Test the types. */
|
||||||
if (!rhs->isTypeKnown()) {
|
if (!rhs->isTypeKnown()) {
|
||||||
RegisterID reg = frame.tempRegForType(rhs);
|
RegisterID reg = frame.tempRegForType(rhs);
|
||||||
Jump rhsFail = masm.branch32(Assembler::NotEqual, reg, Imm32(JSVAL_MASK32_INT32));
|
Jump rhsFail = masm.testInt32(Assembler::NotEqual, reg);
|
||||||
stubcc.linkExit(rhsFail);
|
stubcc.linkExit(rhsFail);
|
||||||
frame.freeReg(reg);
|
|
||||||
frame.learnType(rhs, JSVAL_MASK32_INT32);
|
frame.learnType(rhs, JSVAL_MASK32_INT32);
|
||||||
}
|
}
|
||||||
if (!lhs->isTypeKnown()) {
|
if (!lhs->isTypeKnown()) {
|
||||||
RegisterID reg = frame.tempRegForType(lhs);
|
RegisterID reg = frame.tempRegForType(lhs);
|
||||||
Jump lhsFail = masm.branch32(Assembler::NotEqual, reg, Imm32(JSVAL_MASK32_INT32));
|
Jump lhsFail = masm.testInt32(Assembler::NotEqual, reg);
|
||||||
stubcc.linkExit(lhsFail);
|
stubcc.linkExit(lhsFail);
|
||||||
frame.freeReg(reg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stubcc.leave();
|
stubcc.leave();
|
||||||
@ -153,3 +151,58 @@ mjit::Compiler::jsop_bitop(JSOp op)
|
|||||||
stubcc.rejoin(2);
|
stubcc.rejoin(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mjit::Compiler::jsop_globalinc(JSOp op, uint32 index)
|
||||||
|
{
|
||||||
|
uint32 slot = script->getGlobalSlot(index);
|
||||||
|
|
||||||
|
bool popped = false;
|
||||||
|
PC += JSOP_GLOBALINC_LENGTH;
|
||||||
|
if (JSOp(*PC) == JSOP_POP && !analysis[PC].nincoming) {
|
||||||
|
popped = true;
|
||||||
|
PC += JSOP_POP_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
int amt = (js_CodeSpec[op].format & JOF_INC) ? 1 : -1;
|
||||||
|
bool post = !!(js_CodeSpec[op].format & JOF_POST);
|
||||||
|
|
||||||
|
RegisterID data;
|
||||||
|
RegisterID reg = frame.allocReg();
|
||||||
|
Address addr = masm.objSlotRef(globalObj, reg, slot);
|
||||||
|
|
||||||
|
if (post && !popped) {
|
||||||
|
frame.push(addr);
|
||||||
|
FrameEntry *fe = frame.peek(-1);
|
||||||
|
Jump notInt = frame.testInt32(Assembler::NotEqual, fe);
|
||||||
|
stubcc.linkExit(notInt);
|
||||||
|
data = frame.copyData(fe);
|
||||||
|
} else {
|
||||||
|
Jump notInt = masm.testInt32(Assembler::NotEqual, addr);
|
||||||
|
stubcc.linkExit(notInt);
|
||||||
|
data = frame.allocReg();
|
||||||
|
masm.loadData32(addr, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Jump ovf;
|
||||||
|
if (amt > 0)
|
||||||
|
ovf = masm.branchAdd32(Assembler::Overflow, Imm32(1), data);
|
||||||
|
else
|
||||||
|
ovf = masm.branchSub32(Assembler::Overflow, Imm32(1), data);
|
||||||
|
stubcc.linkExit(ovf);
|
||||||
|
|
||||||
|
stubcc.leave();
|
||||||
|
stubcc.masm.lea(addr, Registers::ArgReg1);
|
||||||
|
stubcc.vpInc(op, post && !popped);
|
||||||
|
|
||||||
|
masm.storeData32(data, addr);
|
||||||
|
|
||||||
|
if (!post && !popped)
|
||||||
|
frame.pushUntypedPayload(JSVAL_MASK32_INT32, data);
|
||||||
|
else
|
||||||
|
frame.freeReg(data);
|
||||||
|
|
||||||
|
frame.freeReg(reg);
|
||||||
|
|
||||||
|
stubcc.rejoin(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user