[JAEGER] Convert FrameState to use types, not tags.

This commit is contained in:
David Anderson 2010-07-01 01:17:42 -07:00
parent 88a1f5a480
commit 3d36343449
12 changed files with 179 additions and 151 deletions

View File

@ -3425,12 +3425,22 @@ class Value
return data.asBits; return data.asBits;
} }
JSValueType extractNonDoubleObjectType() const { JSValueType extractNonDoubleType() const {
return JSVAL_EXTRACT_NON_DOUBLE_OBJECT_TYPE_IMPL(data); return JSVAL_EXTRACT_TYPE_IMPL(data);
} }
JSValueTag extractNonDoubleObjectTag() const { JSValueTag extractNonDoubleTag() const {
return JSVAL_EXTRACT_NON_DOUBLE_OBJECT_TAG_IMPL(data); return JSVAL_EXTRACT_TAG_IMPL(data);
}
JSValueType extractNonDoubleObjectTraceType() const {
JS_ASSERT(!isObject());
return JSVAL_EXTRACT_TYPE_IMPL(data);
}
JSValueTag extractNonDoubleObjectTraceTag() const {
JS_ASSERT(!isObject());
return JSVAL_EXTRACT_TAG_IMPL(data);
} }
void unboxNonDoubleTo(uint64 *out) const { void unboxNonDoubleTo(uint64 *out) const {

View File

@ -600,18 +600,18 @@ JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
} }
static JS_ALWAYS_INLINE JSValueType static JS_ALWAYS_INLINE JSValueType
JSVAL_EXTRACT_NON_DOUBLE_OBJECT_TYPE_IMPL(jsval_layout l) JSVAL_EXTRACT_TYPE_IMPL(jsval_layout l)
{ {
uint32 type = l.s.tag & 0xF; uint32 type = l.s.tag & 0xF;
JS_ASSERT(type > JSVAL_TYPE_DOUBLE && type < JSVAL_TYPE_OBJECT); JS_ASSERT(type > JSVAL_TYPE_DOUBLE && type <= JSVAL_TYPE_OBJECT);
return (JSValueType)type; return (JSValueType)type;
} }
static JS_ALWAYS_INLINE JSValueTag static JS_ALWAYS_INLINE JSValueTag
JSVAL_EXTRACT_NON_DOUBLE_OBJECT_TAG_IMPL(jsval_layout l) JSVAL_EXTRACT_TAG_IMPL(jsval_layout l)
{ {
JSValueTag tag = l.s.tag; JSValueTag tag = l.s.tag;
JS_ASSERT(tag >= JSVAL_TAG_INT32 && tag != JSVAL_TAG_OBJECT); JS_ASSERT(tag >= JSVAL_TAG_INT32);
return tag; return tag;
} }

View File

@ -1043,7 +1043,7 @@ GetPromotedType(const Value &v)
return JSVAL_TYPE_DOUBLE; return JSVAL_TYPE_DOUBLE;
if (v.isObject()) if (v.isObject())
return v.asObject().isFunction() ? JSVAL_TYPE_FUNOBJ : JSVAL_TYPE_NONFUNOBJ; return v.asObject().isFunction() ? JSVAL_TYPE_FUNOBJ : JSVAL_TYPE_NONFUNOBJ;
return v.extractNonDoubleObjectType(); return v.extractNonDoubleObjectTraceType();
} }
/* Return JSVAL_TYPE_INT32 for all whole numbers that fit into signed 32-bit and the tag otherwise. */ /* Return JSVAL_TYPE_INT32 for all whole numbers that fit into signed 32-bit and the tag otherwise. */
@ -1058,7 +1058,7 @@ getCoercedType(const Value &v)
} }
if (v.isObject()) if (v.isObject())
return v.asObject().isFunction() ? JSVAL_TYPE_FUNOBJ : JSVAL_TYPE_NONFUNOBJ; return v.asObject().isFunction() ? JSVAL_TYPE_FUNOBJ : JSVAL_TYPE_NONFUNOBJ;
return v.extractNonDoubleObjectType(); return v.extractNonDoubleObjectTraceType();
} }
/* Constant seed and accumulate step borrowed from the DJB hash. */ /* Constant seed and accumulate step borrowed from the DJB hash. */
@ -3820,7 +3820,7 @@ TraceRecorder::determineSlotType(Value* vp)
if (vp->isObject()) if (vp->isObject())
return vp->asObject().isFunction() ? JSVAL_TYPE_FUNOBJ : JSVAL_TYPE_NONFUNOBJ; return vp->asObject().isFunction() ? JSVAL_TYPE_FUNOBJ : JSVAL_TYPE_NONFUNOBJ;
return vp->extractNonDoubleObjectType(); return vp->extractNonDoubleObjectTraceType();
} }
class DetermineTypesVisitor : public SlotVisitorBase class DetermineTypesVisitor : public SlotVisitorBase
@ -9452,7 +9452,7 @@ TraceRecorder::unbox_value(const Value &v, LIns *vaddr_ins, ptrdiff_t offset, VM
return unbox_object(vaddr_ins, offset, tag_ins, type, exit, accSet); return unbox_object(vaddr_ins, offset, tag_ins, type, exit, accSet);
} }
JSValueType type = v.extractNonDoubleObjectType(); JSValueType type = v.extractNonDoubleObjectTraceType();
return unbox_non_double_object(vaddr_ins, offset, tag_ins, type, exit, accSet); return unbox_non_double_object(vaddr_ins, offset, tag_ins, type, exit, accSet);
} }
@ -9500,7 +9500,7 @@ TraceRecorder::box_value_into(const Value &v, LIns *v_ins, LIns *dstaddr_ins, pt
} else if (v.isNull()) { } else if (v.isNull()) {
box_null_into(dstaddr_ins, offset, accSet); box_null_into(dstaddr_ins, offset, accSet);
} else { } else {
JSValueTag tag = v.isObject() ? JSVAL_TAG_OBJECT : v.extractNonDoubleObjectTag(); JSValueTag tag = v.isObject() ? JSVAL_TAG_OBJECT : v.extractNonDoubleObjectTraceTag();
lir->insStore(INS_CONSTU(tag), dstaddr_ins, offset + sTagOffset, ACC_OTHER); lir->insStore(INS_CONSTU(tag), dstaddr_ins, offset + sTagOffset, ACC_OTHER);
lir->insStore(v_ins, dstaddr_ins, offset + sPayloadOffset, ACC_OTHER); lir->insStore(v_ins, dstaddr_ins, offset + sPayloadOffset, ACC_OTHER);
} }

View File

@ -967,7 +967,7 @@ mjit::Compiler::generateMethod()
stubCall(stubs::NewInitObject, Uses(0), Defs(1)); stubCall(stubs::NewInitObject, Uses(0), Defs(1));
} }
frame.takeReg(Registers::ReturnReg); frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, Registers::ReturnReg); frame.pushTypedPayload(JSVAL_TYPE_OBJECT, Registers::ReturnReg);
} }
END_CASE(JSOP_NEWINIT) END_CASE(JSOP_NEWINIT)
@ -1099,7 +1099,7 @@ mjit::Compiler::generateMethod()
masm.move(ImmPtr(fun), Registers::ArgReg1); masm.move(ImmPtr(fun), Registers::ArgReg1);
stubCall(stubs::Lambda, Uses(0), Defs(1)); stubCall(stubs::Lambda, Uses(0), Defs(1));
frame.takeReg(Registers::ReturnReg); frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, Registers::ReturnReg); frame.pushTypedPayload(JSVAL_TYPE_OBJECT, Registers::ReturnReg);
} }
END_CASE(JSOP_LAMBDA) END_CASE(JSOP_LAMBDA)
@ -1135,7 +1135,7 @@ mjit::Compiler::generateMethod()
masm.move(ImmPtr(fun), Registers::ArgReg1); masm.move(ImmPtr(fun), Registers::ArgReg1);
stubCall(stubs::DefLocalFun, Uses(0), Defs(0)); stubCall(stubs::DefLocalFun, Uses(0), Defs(0));
frame.takeReg(Registers::ReturnReg); frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, Registers::ReturnReg); frame.pushTypedPayload(JSVAL_TYPE_OBJECT, Registers::ReturnReg);
frame.storeLocal(slot); frame.storeLocal(slot);
frame.pop(); frame.pop();
} }
@ -1163,7 +1163,7 @@ mjit::Compiler::generateMethod()
masm.move(ImmPtr(regex), Registers::ArgReg1); masm.move(ImmPtr(regex), Registers::ArgReg1);
stubCall(stubs::RegExp, Uses(0), Defs(1)); stubCall(stubs::RegExp, Uses(0), Defs(1));
frame.takeReg(Registers::ReturnReg); frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, Registers::ReturnReg); frame.pushTypedPayload(JSVAL_TYPE_OBJECT, Registers::ReturnReg);
} }
END_CASE(JSOP_REGEXP) END_CASE(JSOP_REGEXP)
@ -1255,7 +1255,7 @@ mjit::Compiler::generateMethod()
stubCall(stubs::NewArray, Uses(len), Defs(1)); stubCall(stubs::NewArray, Uses(len), Defs(1));
frame.popn(len); frame.popn(len);
frame.takeReg(Registers::ReturnReg); frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, Registers::ReturnReg); frame.pushTypedPayload(JSVAL_TYPE_OBJECT, Registers::ReturnReg);
} }
END_CASE(JSOP_NEWARRAY) END_CASE(JSOP_NEWARRAY)
@ -1266,7 +1266,7 @@ mjit::Compiler::generateMethod()
masm.move(ImmPtr(fun), Registers::ArgReg1); masm.move(ImmPtr(fun), Registers::ArgReg1);
stubCall(stubs::FlatLambda, Uses(0), Defs(1)); stubCall(stubs::FlatLambda, Uses(0), Defs(1));
frame.takeReg(Registers::ReturnReg); frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, Registers::ReturnReg); frame.pushTypedPayload(JSVAL_TYPE_OBJECT, Registers::ReturnReg);
} }
END_CASE(JSOP_LAMBDA_FC) END_CASE(JSOP_LAMBDA_FC)
@ -1294,7 +1294,7 @@ mjit::Compiler::generateMethod()
stubCall(stubs::ConcatN, Uses(argc), Defs(1)); stubCall(stubs::ConcatN, Uses(argc), Defs(1));
frame.popn(argc); frame.popn(argc);
frame.takeReg(Registers::ReturnReg); frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_STRING, Registers::ReturnReg); frame.pushTypedPayload(JSVAL_TYPE_STRING, Registers::ReturnReg);
} }
END_CASE(JSOP_CONCATN) END_CASE(JSOP_CONCATN)
@ -1567,7 +1567,7 @@ mjit::Compiler::inlineCallHelper(uint32 argc, bool callingNew)
FrameEntry *fe = frame.peek(-int(argc + 2)); FrameEntry *fe = frame.peek(-int(argc + 2));
bool typeKnown = fe->isTypeKnown(); bool typeKnown = fe->isTypeKnown();
if (typeKnown && fe->getTypeTag() != JSVAL_TAG_OBJECT) { if (typeKnown && fe->getKnownType() != JSVAL_TYPE_OBJECT) {
VoidPtrStubUInt32 stub = callingNew ? stubs::SlowNew : stubs::SlowCall; VoidPtrStubUInt32 stub = callingNew ? stubs::SlowNew : stubs::SlowCall;
masm.move(Imm32(argc), Registers::ArgReg1); masm.move(Imm32(argc), Registers::ArgReg1);
masm.stubCall(stub, PC, frame.stackDepth() + script->nfixed); masm.stubCall(stub, PC, frame.stackDepth() + script->nfixed);
@ -1801,7 +1801,7 @@ mjit::Compiler::emitStubCmpOp(BoolStub stub, jsbytecode *target, JSOp fused)
if (!target) { if (!target) {
frame.takeReg(Registers::ReturnReg); frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_BOOLEAN, Registers::ReturnReg); frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, Registers::ReturnReg);
} else { } else {
JS_ASSERT(fused == JSOP_IFEQ || fused == JSOP_IFNE); JS_ASSERT(fused == JSOP_IFEQ || fused == JSOP_IFNE);
@ -1851,7 +1851,7 @@ mjit::Compiler::jsop_length()
{ {
FrameEntry *top = frame.peek(-1); FrameEntry *top = frame.peek(-1);
if (top->isTypeKnown() && top->getTypeTag() == JSVAL_TAG_STRING) { if (top->isTypeKnown() && top->getKnownType() == JSVAL_TYPE_STRING) {
if (top->isConstant()) { if (top->isConstant()) {
JSString *str = top->getValue().asString(); JSString *str = top->getValue().asString();
Value v; Value v;
@ -1862,7 +1862,7 @@ mjit::Compiler::jsop_length()
RegisterID str = frame.ownRegForData(top); RegisterID str = frame.ownRegForData(top);
masm.loadPtr(Address(str, offsetof(JSString, mLength)), str); masm.loadPtr(Address(str, offsetof(JSString, mLength)), str);
frame.pop(); frame.pop();
frame.pushTypedPayload(JSVAL_TAG_INT32, str); frame.pushTypedPayload(JSVAL_TYPE_INT32, str);
} }
return; return;
} }
@ -1884,9 +1884,9 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck)
FrameEntry *top = frame.peek(-1); FrameEntry *top = frame.peek(-1);
/* If the incoming type will never PIC, take slow path. */ /* If the incoming type will never PIC, take slow path. */
if (top->isTypeKnown() && top->getTypeTag() != JSVAL_TAG_OBJECT) { if (top->isTypeKnown() && top->getKnownType() != JSVAL_TYPE_OBJECT) {
JS_ASSERT_IF(atom == cx->runtime->atomState.lengthAtom, JS_ASSERT_IF(atom == cx->runtime->atomState.lengthAtom,
top->getTypeTag() != JSVAL_TAG_STRING); top->getKnownType() != JSVAL_TYPE_STRING);
jsop_getprop_slow(); jsop_getprop_slow();
return; return;
} }
@ -2068,7 +2068,7 @@ mjit::Compiler::jsop_callprop_str(JSAtom *atom)
/* Force into a register because getprop won't expect a constant. */ /* Force into a register because getprop won't expect a constant. */
RegisterID reg = frame.allocReg(); RegisterID reg = frame.allocReg();
masm.move(ImmPtr(obj), reg); masm.move(ImmPtr(obj), reg);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, reg); frame.pushTypedPayload(JSVAL_TYPE_OBJECT, reg);
/* Get the property. */ /* Get the property. */
jsop_getprop(atom); jsop_getprop(atom);
@ -2116,7 +2116,7 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom)
PICGenInfo pic(ic::PICInfo::CALL); PICGenInfo pic(ic::PICInfo::CALL);
JS_ASSERT(top->isTypeKnown()); JS_ASSERT(top->isTypeKnown());
JS_ASSERT(top->getTypeTag() == JSVAL_TAG_OBJECT); JS_ASSERT(top->getKnownType() == JSVAL_TYPE_OBJECT);
pic.hotPathBegin = masm.label(); pic.hotPathBegin = masm.label();
pic.hasTypeCheck = false; pic.hasTypeCheck = false;
@ -2178,8 +2178,8 @@ mjit::Compiler::jsop_callprop(JSAtom *atom)
FrameEntry *top = frame.peek(-1); FrameEntry *top = frame.peek(-1);
/* If the incoming type will never PIC, take slow path. */ /* If the incoming type will never PIC, take slow path. */
if (top->isTypeKnown() && top->getTypeTag() != JSVAL_TAG_OBJECT) { if (top->isTypeKnown() && top->getKnownType() != JSVAL_TYPE_OBJECT) {
if (top->getTypeTag() == JSVAL_TAG_STRING) if (top->getKnownType() == JSVAL_TYPE_STRING)
return jsop_callprop_str(atom); return jsop_callprop_str(atom);
return jsop_callprop_slow(atom); return jsop_callprop_slow(atom);
} }
@ -2196,7 +2196,7 @@ mjit::Compiler::jsop_setprop(JSAtom *atom)
FrameEntry *rhs = frame.peek(-1); FrameEntry *rhs = frame.peek(-1);
/* If the incoming type will never PIC, take slow path. */ /* If the incoming type will never PIC, take slow path. */
if (lhs->isTypeKnown() && lhs->getTypeTag() != JSVAL_TAG_OBJECT) { if (lhs->isTypeKnown() && lhs->getKnownType() != JSVAL_TYPE_OBJECT) {
jsop_setprop_slow(atom); jsop_setprop_slow(atom);
return; return;
} }
@ -2212,7 +2212,7 @@ mjit::Compiler::jsop_setprop(JSAtom *atom)
/* Start the hot path where it's easy to patch it. */ /* Start the hot path where it's easy to patch it. */
pic.hotPathBegin = masm.label(); pic.hotPathBegin = masm.label();
Jump j = masm.branch32(Assembler::NotEqual, reg, ImmTag(JSVAL_TAG_OBJECT)); Jump j = masm.testObject(Assembler::NotEqual, reg);
pic.typeCheck = stubcc.masm.label(); pic.typeCheck = stubcc.masm.label();
stubcc.linkExit(j); stubcc.linkExit(j);
@ -2240,7 +2240,7 @@ mjit::Compiler::jsop_setprop(JSAtom *atom)
vr.isConstant = false; vr.isConstant = false;
vr.u.s.isTypeKnown = rhs->isTypeKnown(); vr.u.s.isTypeKnown = rhs->isTypeKnown();
if (vr.u.s.isTypeKnown) { if (vr.u.s.isTypeKnown) {
vr.u.s.type.tag = rhs->getTypeTag(); vr.u.s.type.tag = rhs->getKnownTag();
} else { } else {
vr.u.s.type.reg = frame.tempRegForType(rhs); vr.u.s.type.reg = frame.tempRegForType(rhs);
frame.pinReg(vr.u.s.type.reg); frame.pinReg(vr.u.s.type.reg);
@ -2351,7 +2351,7 @@ mjit::Compiler::jsop_this()
RegisterID reg = frame.allocReg(); RegisterID reg = frame.allocReg();
masm.loadData32(thisvAddr, reg); masm.loadData32(thisvAddr, reg);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, reg); frame.pushTypedPayload(JSVAL_TYPE_OBJECT, reg);
} else { } else {
frame.push(thisvAddr); frame.push(thisvAddr);
Jump null = frame.testNull(Assembler::Equal, frame.peek(-1)); Jump null = frame.testNull(Assembler::Equal, frame.peek(-1));
@ -2507,7 +2507,7 @@ mjit::Compiler::iterNext()
stubcc.leave(); stubcc.leave();
stubcc.call(stubs::IterNext); stubcc.call(stubs::IterNext);
frame.pushUntypedPayload(JSVAL_TAG_STRING, T3); frame.pushUntypedPayload(JSVAL_TYPE_STRING, T3);
/* Join with the stub call. */ /* Join with the stub call. */
stubcc.rejoin(1); stubcc.rejoin(1);
@ -2588,7 +2588,7 @@ mjit::Compiler::jsop_bindgname()
prepareStubCall(); prepareStubCall();
stubCall(stubs::BindGlobalName, Uses(0), Defs(1)); stubCall(stubs::BindGlobalName, Uses(0), Defs(1));
frame.takeReg(Registers::ReturnReg); frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, Registers::ReturnReg); frame.pushTypedPayload(JSVAL_TYPE_OBJECT, Registers::ReturnReg);
} }
void void
@ -2598,7 +2598,7 @@ mjit::Compiler::jsop_getgname(uint32 index)
jsop_bindgname(); jsop_bindgname();
FrameEntry *fe = frame.peek(-1); FrameEntry *fe = frame.peek(-1);
JS_ASSERT(fe->isTypeKnown() && fe->getTypeTag() == JSVAL_TAG_OBJECT); JS_ASSERT(fe->isTypeKnown() && fe->getKnownType() == JSVAL_TYPE_OBJECT);
MICGenInfo mic; MICGenInfo mic;
RegisterID objReg; RegisterID objReg;
@ -2674,7 +2674,7 @@ mjit::Compiler::jsop_setgname(uint32 index)
{ {
#if ENABLE_MIC #if ENABLE_MIC
FrameEntry *objFe = frame.peek(-2); FrameEntry *objFe = frame.peek(-2);
JS_ASSERT_IF(objFe->isTypeKnown(), objFe->getTypeTag() == JSVAL_TAG_OBJECT); JS_ASSERT_IF(objFe->isTypeKnown(), objFe->getKnownType() == JSVAL_TYPE_OBJECT);
MICGenInfo mic; MICGenInfo mic;
RegisterID objReg; RegisterID objReg;
@ -2718,7 +2718,7 @@ mjit::Compiler::jsop_setgname(uint32 index)
Value v; Value v;
RegisterID typeReg = Registers::ReturnReg; RegisterID typeReg = Registers::ReturnReg;
RegisterID dataReg = Registers::ReturnReg; RegisterID dataReg = Registers::ReturnReg;
JSValueTag typeTag = JSVAL_TAG_INT32; JSValueType typeTag = JSVAL_TYPE_INT32;
mic.typeConst = fe->isTypeKnown(); mic.typeConst = fe->isTypeKnown();
mic.dataConst = fe->isConstant(); mic.dataConst = fe->isConstant();
@ -2729,7 +2729,7 @@ mjit::Compiler::jsop_setgname(uint32 index)
if (!mic.typeConst) if (!mic.typeConst)
typeReg = frame.ownRegForType(fe); typeReg = frame.ownRegForType(fe);
else else
typeTag = fe->getTypeTag(); typeTag = fe->getKnownType();
} else { } else {
v = fe->getValue(); v = fe->getValue();
} }
@ -2742,7 +2742,7 @@ mjit::Compiler::jsop_setgname(uint32 index)
masm.storeValue(v, address); masm.storeValue(v, address);
} else { } else {
if (mic.typeConst) if (mic.typeConst)
masm.storeTypeTag(ImmTag(typeTag), address); masm.storeTypeTag(ImmType(typeTag), address);
else else
masm.storeTypeTag(typeReg, address); masm.storeTypeTag(typeReg, address);
masm.storeData32(dataReg, address); masm.storeData32(dataReg, address);
@ -2803,12 +2803,12 @@ mjit::Compiler::jsop_instanceof()
* thus have fun_instanceOf, which we're inlining. * thus have fun_instanceOf, which we're inlining.
*/ */
if (rhs->isTypeKnown() && rhs->getTypeTag() != JSVAL_TAG_OBJECT) { if (rhs->isTypeKnown() && rhs->getKnownType() != JSVAL_TYPE_OBJECT) {
prepareStubCall(); prepareStubCall();
stubCall(stubs::InstanceOf, Uses(2), Defs(1)); stubCall(stubs::InstanceOf, Uses(2), Defs(1));
frame.popn(2); frame.popn(2);
frame.takeReg(Registers::ReturnReg); frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_BOOLEAN, Registers::ReturnReg); frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, Registers::ReturnReg);
return; return;
} }
@ -2873,7 +2873,7 @@ mjit::Compiler::jsop_instanceof()
stubcc.call(stubs::FastInstanceOf); stubcc.call(stubs::FastInstanceOf);
frame.popn(3); frame.popn(3);
frame.pushTypedPayload(JSVAL_TAG_BOOLEAN, temp); frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, temp);
firstSlow.linkTo(stubcc.masm.label(), &stubcc.masm); firstSlow.linkTo(stubcc.masm.label(), &stubcc.masm);
stubcc.rejoin(1); stubcc.rejoin(1);

View File

@ -72,19 +72,25 @@ class FrameEntry
return type.isConstant(); return type.isConstant();
} }
JSValueTag getTypeTag() const { JSValueTag getKnownTag() const {
return v_.s.tag; return v_.s.tag;
} }
JSValueType getKnownType() const {
JS_ASSERT(isTypeKnown());
return knownType;
}
uint32 getPayload32() const { uint32 getPayload32() const {
//JS_ASSERT(!Valueify(v_.asBits).isDouble() || type.synced()); //JS_ASSERT(!Valueify(v_.asBits).isDouble() || type.synced());
return v_.s.payload.u32; return v_.s.payload.u32;
} }
private: private:
void setTypeTag(JSValueTag u32) { void setType(JSValueType type_) {
type.setConstant(); type.setConstant();
v_.s.tag = u32; v_.s.tag = JSVAL_TYPE_TO_TAG(type_);
knownType = type_;
} }
void track(uint32 index) { void track(uint32 index) {
@ -133,6 +139,11 @@ class FrameEntry
type.setConstant(); type.setConstant();
data.setConstant(); data.setConstant();
v_.asBits = JSVAL_BITS(v); v_.asBits = JSVAL_BITS(v);
Value cv = Valueify(v);
if (cv.isDouble())
knownType = JSVAL_TYPE_DOUBLE;
else
knownType = cv.extractNonDoubleType();
} }
bool isCopied() const { bool isCopied() const {
@ -167,13 +178,14 @@ class FrameEntry
} }
private: private:
JSValueType knownType;
jsval_layout v_; jsval_layout v_;
RematInfo type; RematInfo type;
RematInfo data; RematInfo data;
uint32 index_; uint32 index_;
FrameEntry *copy; FrameEntry *copy;
bool copied; bool copied;
char padding[7]; char padding[3];
}; };
} /* namespace mjit */ } /* namespace mjit */

View File

@ -216,23 +216,23 @@ FrameState::pushSynced()
} }
inline void inline void
FrameState::pushSyncedType(JSValueTag tag) FrameState::pushSyncedType(JSValueType type)
{ {
FrameEntry *fe = rawPush(); FrameEntry *fe = rawPush();
fe->resetSynced(); fe->resetSynced();
fe->setTypeTag(tag); fe->setType(type);
} }
inline void inline void
FrameState::pushSynced(JSValueTag tag, RegisterID reg) FrameState::pushSynced(JSValueType type, RegisterID reg)
{ {
FrameEntry *fe = rawPush(); FrameEntry *fe = rawPush();
fe->resetUnsynced(); fe->resetUnsynced();
fe->type.sync(); fe->type.sync();
fe->data.sync(); fe->data.sync();
fe->setTypeTag(tag); fe->setType(type);
fe->data.setRegister(reg); fe->data.setRegister(reg);
regstate[reg] = RegisterState(fe, RematInfo::DATA); regstate[reg] = RegisterState(fe, RematInfo::DATA);
} }
@ -278,20 +278,20 @@ FrameState::pushRegs(RegisterID type, RegisterID data)
} }
inline void inline void
FrameState::pushTypedPayload(JSValueTag tag, RegisterID payload) FrameState::pushTypedPayload(JSValueType type, RegisterID payload)
{ {
JS_ASSERT(!freeRegs.hasReg(payload)); JS_ASSERT(!freeRegs.hasReg(payload));
FrameEntry *fe = rawPush(); FrameEntry *fe = rawPush();
fe->resetUnsynced(); fe->resetUnsynced();
fe->setTypeTag(tag); fe->setType(type);
fe->data.setRegister(payload); fe->data.setRegister(payload);
regstate[payload] = RegisterState(fe, RematInfo::DATA); regstate[payload] = RegisterState(fe, RematInfo::DATA);
} }
inline void inline void
FrameState::pushUntypedPayload(JSValueTag tag, RegisterID payload, FrameState::pushUntypedPayload(JSValueType type, RegisterID payload,
bool popGuaranteed, bool fastType) bool popGuaranteed, bool fastType)
{ {
JS_ASSERT(!freeRegs.hasReg(payload)); JS_ASSERT(!freeRegs.hasReg(payload));
@ -308,10 +308,10 @@ FrameState::pushUntypedPayload(JSValueTag tag, RegisterID payload,
* consuming values, so the value has been properly initialized. * consuming values, so the value has been properly initialized.
*/ */
if (popGuaranteed) { if (popGuaranteed) {
fe->setTypeTag(tag); fe->setType(type);
} else { } else {
if (!fastType || !fe->type.synced()) if (!fastType || !fe->type.synced())
masm.storeTypeTag(ImmTag(tag), addressOf(fe)); masm.storeTypeTag(ImmType(type), addressOf(fe));
/* The forceful type sync will assert otherwise. */ /* The forceful type sync will assert otherwise. */
#ifdef DEBUG #ifdef DEBUG
@ -450,7 +450,7 @@ FrameState::syncType(const FrameEntry *fe, Address to, Assembler &masm) const
if (fe->type.isConstant()) { if (fe->type.isConstant()) {
JS_ASSERT(fe->isTypeKnown()); JS_ASSERT(fe->isTypeKnown());
masm.storeTypeTag(ImmTag(fe->getTypeTag()), to); masm.storeTypeTag(ImmTag(fe->getKnownTag()), to);
} else { } else {
masm.storeTypeTag(fe->type.reg(), to); masm.storeTypeTag(fe->type.reg(), to);
} }
@ -483,11 +483,11 @@ FrameState::forgetType(FrameEntry *fe)
} }
inline void inline void
FrameState::learnType(FrameEntry *fe, JSValueTag tag) FrameState::learnType(FrameEntry *fe, JSValueType type)
{ {
if (fe->type.inRegister()) if (fe->type.inRegister())
forgetReg(fe->type.reg()); forgetReg(fe->type.reg());
fe->setTypeTag(tag); fe->setType(type);
} }
inline JSC::MacroAssembler::Address inline JSC::MacroAssembler::Address

View File

@ -226,7 +226,7 @@ FrameState::storeTo(FrameEntry *fe, Address address, bool popped)
} }
if (fe->isTypeKnown()) { if (fe->isTypeKnown()) {
masm.storeTypeTag(ImmTag(fe->getTypeTag()), address); masm.storeTypeTag(ImmTag(fe->getKnownTag()), address);
} else if (fe->type.inRegister()) { } else if (fe->type.inRegister()) {
masm.storeTypeTag(fe->type.reg(), address); masm.storeTypeTag(fe->type.reg(), address);
} else { } else {
@ -341,7 +341,7 @@ FrameState::sync(Assembler &masm) const
/* :TODO: we can do better, the type is learned for all copies. */ /* :TODO: we can do better, the type is learned for all copies. */
if (fe->isTypeKnown()) { if (fe->isTypeKnown()) {
//JS_ASSERT(fe->getTypeTag() == backing->getTypeTag()); //JS_ASSERT(fe->getTypeTag() == backing->getTypeTag());
masm.storeTypeTag(ImmTag(fe->getTypeTag()), address); masm.storeTypeTag(ImmTag(fe->getKnownTag()), address);
} else { } else {
masm.storeTypeTag(backing->type.reg(), address); masm.storeTypeTag(backing->type.reg(), address);
} }
@ -676,7 +676,7 @@ FrameState::pushCopyOf(uint32 index)
fe->setConstant(Jsvalify(backing->getValue())); fe->setConstant(Jsvalify(backing->getValue()));
} else { } else {
if (backing->isTypeKnown()) if (backing->isTypeKnown())
fe->setTypeTag(backing->getTypeTag()); fe->setType(backing->getKnownType());
else else
fe->type.invalidate(); fe->type.invalidate();
fe->data.invalidate(); fe->data.invalidate();
@ -755,7 +755,7 @@ FrameState::uncopy(FrameEntry *original)
moveOwnership(fe->type.reg(), fe); moveOwnership(fe->type.reg(), fe);
} else { } else {
JS_ASSERT(fe->isTypeKnown()); JS_ASSERT(fe->isTypeKnown());
JS_ASSERT(fe->getTypeTag() == original->getTypeTag()); JS_ASSERT(fe->getKnownTag() == original->getKnownTag());
} }
if (original->data.inMemory() && !fe->data.synced()) if (original->data.inMemory() && !fe->data.synced())
tempRegForData(original); tempRegForData(original);
@ -833,7 +833,7 @@ FrameState::storeLocal(uint32 n, bool popGuaranteed, bool typeChange)
localFe->setNotCopied(); localFe->setNotCopied();
localFe->setCopyOf(backing); localFe->setCopyOf(backing);
if (backing->isTypeKnown()) if (backing->isTypeKnown())
localFe->setTypeTag(backing->getTypeTag()); localFe->setType(backing->getKnownType());
else else
localFe->type.invalidate(); localFe->type.invalidate();
localFe->data.invalidate(); localFe->data.invalidate();
@ -887,7 +887,7 @@ FrameState::storeLocal(uint32 n, bool popGuaranteed, bool typeChange)
if (typeChange) { if (typeChange) {
if (backing->isTypeKnown()) { if (backing->isTypeKnown()) {
localFe->setTypeTag(backing->getTypeTag()); localFe->setType(backing->getKnownType());
} else { } else {
RegisterID reg = tempRegForType(backing); RegisterID reg = tempRegForType(backing);
localFe->type.setRegister(reg); localFe->type.setRegister(reg);
@ -895,7 +895,7 @@ FrameState::storeLocal(uint32 n, bool popGuaranteed, bool typeChange)
} }
} else { } else {
if (!wasSynced) if (!wasSynced)
masm.storeTypeTag(ImmTag(backing->getTypeTag()), addressOf(localFe)); masm.storeTypeTag(ImmTag(backing->getKnownTag()), addressOf(localFe));
localFe->type.setMemory(); localFe->type.setMemory();
} }

View File

@ -160,12 +160,12 @@ class FrameState
/* /*
* Pushes a slot that has a known, synced type and payload. * Pushes a slot that has a known, synced type and payload.
*/ */
inline void pushSyncedType(JSValueTag tag); inline void pushSyncedType(JSValueType type);
/* /*
* Pushes a slot that has a known, synced type and payload. * Pushes a slot that has a known, synced type and payload.
*/ */
inline void pushSynced(JSValueTag tag, RegisterID reg); inline void pushSynced(JSValueType type, RegisterID reg);
/* /*
* Pushes a constant value. * Pushes a constant value.
@ -180,7 +180,7 @@ class FrameState
/* /*
* Pushes a known type and allocated payload onto the operation stack. * Pushes a known type and allocated payload onto the operation stack.
*/ */
inline void pushTypedPayload(JSValueTag tag, RegisterID payload); inline void pushTypedPayload(JSValueType type, RegisterID payload);
/* /*
* Pushes a type register and data register pair. * Pushes a type register and data register pair.
@ -196,7 +196,7 @@ class FrameState
* the value it replaces on the stack had the same tag if the fast-path * the value it replaces on the stack had the same tag if the fast-path
* was taken. * was taken.
*/ */
inline void pushUntypedPayload(JSValueTag tag, RegisterID payload, inline void pushUntypedPayload(JSValueType type, RegisterID payload,
bool popGuaranteed = false, bool popGuaranteed = false,
bool fastTyped = false); bool fastTyped = false);
@ -416,7 +416,7 @@ class FrameState
/* /*
* Mark an existing slot with a type. * Mark an existing slot with a type.
*/ */
inline void learnType(FrameEntry *fe, JSValueTag tag); inline void learnType(FrameEntry *fe, JSValueType type);
/* /*
* Forget a type, syncing in the process. * Forget a type, syncing in the process.

View File

@ -203,7 +203,7 @@ ImmutableSync::syncCopy(FrameEntry *fe)
if (fe->isTypeKnown() && !e.learnedType) { if (fe->isTypeKnown() && !e.learnedType) {
e.learnedType = true; e.learnedType = true;
e.typeTag = fe->getTypeTag(); e.typeTag = fe->getKnownTag();
} }
if (!fe->data.synced()) if (!fe->data.synced())
@ -226,7 +226,7 @@ ImmutableSync::syncNormal(FrameEntry *fe)
if (fe->isTypeKnown()) { if (fe->isTypeKnown()) {
e.learnedType = true; e.learnedType = true;
e.typeTag = fe->getTypeTag(); e.typeTag = fe->getKnownTag();
} }
if (!fe->data.synced() && !e.dataSynced) { if (!fe->data.synced() && !e.dataSynced) {

View File

@ -53,6 +53,13 @@ class ImmTag : public JSC::MacroAssembler::Imm32
{ } { }
}; };
struct ImmType : ImmTag
{
ImmType(JSValueType type)
: ImmTag(JSVAL_TYPE_TO_TAG(type))
{ }
};
class Assembler : public BaseAssembler class Assembler : public BaseAssembler
{ {
static const uint32 PAYLOAD_OFFSET = 0; static const uint32 PAYLOAD_OFFSET = 0;

View File

@ -229,7 +229,7 @@ mjit::Compiler::slowLoadConstantDouble(Assembler &masm,
FrameEntry *fe, FPRegisterID fpreg) FrameEntry *fe, FPRegisterID fpreg)
{ {
jsdpun u; jsdpun u;
if (fe->getTypeTag() == JSVAL_TAG_INT32) if (fe->getKnownType() == JSVAL_TYPE_INT32)
u.d = (double)fe->getValue().asInt32(); u.d = (double)fe->getValue().asInt32();
else else
u.d = fe->getValue().asDouble(); u.d = fe->getValue().asDouble();
@ -248,7 +248,7 @@ mjit::Compiler::maybeJumpIfNotInt32(Assembler &masm, MaybeJump &mj, FrameEntry *
mj.setJump(masm.testInt32(Assembler::NotEqual, mreg.getReg())); mj.setJump(masm.testInt32(Assembler::NotEqual, mreg.getReg()));
else else
mj.setJump(masm.testInt32(Assembler::NotEqual, frame.addressOf(fe))); mj.setJump(masm.testInt32(Assembler::NotEqual, frame.addressOf(fe)));
} else if (fe->getTypeTag() != JSVAL_TAG_INT32) { } else if (fe->getKnownType() != JSVAL_TYPE_INT32) {
mj.setJump(masm.jump()); mj.setJump(masm.jump());
} }
} }
@ -262,7 +262,7 @@ mjit::Compiler::maybeJumpIfNotDouble(Assembler &masm, MaybeJump &mj, FrameEntry
mj.setJump(masm.testDouble(Assembler::NotEqual, mreg.getReg())); mj.setJump(masm.testDouble(Assembler::NotEqual, mreg.getReg()));
else else
mj.setJump(masm.testDouble(Assembler::NotEqual, frame.addressOf(fe))); mj.setJump(masm.testDouble(Assembler::NotEqual, frame.addressOf(fe)));
} else if (fe->getTypeTag() >= JSVAL_TAG_CLEAR) { } else if (fe->getKnownType() != JSVAL_TYPE_DOUBLE) {
mj.setJump(masm.jump()); mj.setJump(masm.jump());
} }
} }
@ -283,21 +283,21 @@ mjit::Compiler::jsop_binary(JSOp op, VoidStub stub)
* This is temporary while ops are still being implemented. * This is temporary while ops are still being implemented.
*/ */
if ((op == JSOP_MOD) || if ((op == JSOP_MOD) ||
(lhs->isTypeKnown() && (lhs->getTypeTag() > JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET)) || (lhs->isTypeKnown() && (lhs->getKnownType() > JSVAL_UPPER_INCL_TYPE_OF_NUMBER_SET)) ||
(rhs->isTypeKnown() && (rhs->getTypeTag() > JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET)) (rhs->isTypeKnown() && (rhs->getKnownType() > JSVAL_UPPER_INCL_TYPE_OF_NUMBER_SET))
#if defined(JS_CPU_ARM) #if defined(JS_CPU_ARM)
/* ARM cannot detect integer overflow with multiplication. */ /* ARM cannot detect integer overflow with multiplication. */
|| op == JSOP_MUL || op == JSOP_MUL
#endif /* JS_CPU_ARM */ #endif /* JS_CPU_ARM */
) { ) {
bool isStringResult = (op == JSOP_ADD) && bool isStringResult = (op == JSOP_ADD) &&
((lhs->isTypeKnown() && lhs->getTypeTag() == JSVAL_TAG_STRING) || ((lhs->isTypeKnown() && lhs->getKnownType() == JSVAL_TYPE_STRING) ||
(rhs->isTypeKnown() && rhs->getTypeTag() == JSVAL_TAG_STRING)); (rhs->isTypeKnown() && rhs->getKnownType() == JSVAL_TYPE_STRING));
prepareStubCall(); prepareStubCall();
stubCall(stub, Uses(2), Defs(1)); stubCall(stub, Uses(2), Defs(1));
frame.popn(2); frame.popn(2);
if (isStringResult) if (isStringResult)
frame.pushSyncedType(JSVAL_TAG_STRING); frame.pushSyncedType(JSVAL_TYPE_STRING);
else else
frame.pushSynced(); frame.pushSynced();
return; return;
@ -305,8 +305,8 @@ mjit::Compiler::jsop_binary(JSOp op, VoidStub stub)
/* Can do int math iff there is no double constant and the op is not division. */ /* Can do int math iff there is no double constant and the op is not division. */
bool canDoIntMath = op != JSOP_DIV && bool canDoIntMath = op != JSOP_DIV &&
!((rhs->isTypeKnown() && rhs->getTypeTag() < JSVAL_TAG_CLEAR) || !((rhs->isTypeKnown() && rhs->getKnownType() == JSVAL_TYPE_DOUBLE) ||
(lhs->isTypeKnown() && lhs->getTypeTag() < JSVAL_TAG_CLEAR)); (lhs->isTypeKnown() && lhs->getKnownType() == JSVAL_TYPE_DOUBLE));
frame.syncAllRegs(Registers::AvailRegs); frame.syncAllRegs(Registers::AvailRegs);
@ -369,7 +369,7 @@ mjit::Compiler::jsop_binary(JSOp op, VoidStub stub)
Label lblCvtPath2 = stubcc.masm.label(); Label lblCvtPath2 = stubcc.masm.label();
{ {
/* Don't bother emitting double conversion for a known double. */ /* Don't bother emitting double conversion for a known double. */
if (!lhs->isTypeKnown() || lhs->getTypeTag() >= JSVAL_TAG_CLEAR) { if (!lhs->isTypeKnown() || lhs->getKnownType() != JSVAL_TYPE_DOUBLE) {
maybeJumpIfNotInt32(stubcc.masm, jmpCvtPath2NotInt, lhs, lhsTypeReg); maybeJumpIfNotInt32(stubcc.masm, jmpCvtPath2NotInt, lhs, lhsTypeReg);
if (!lhs->isConstant()) if (!lhs->isConstant())
@ -390,7 +390,7 @@ mjit::Compiler::jsop_binary(JSOp op, VoidStub stub)
Label lblCvtPath3 = stubcc.masm.label(); Label lblCvtPath3 = stubcc.masm.label();
{ {
/* Don't bother emitting double checking code for a known int. */ /* Don't bother emitting double checking code for a known int. */
if (!lhs->isTypeKnown() || lhs->getTypeTag() != JSVAL_TAG_INT32) { if (!lhs->isTypeKnown() || lhs->getKnownType() != JSVAL_TYPE_INT32) {
maybeJumpIfNotDouble(stubcc.masm, jmpCvtPath3NotDbl, lhs, lhsTypeReg); maybeJumpIfNotDouble(stubcc.masm, jmpCvtPath3NotDbl, lhs, lhsTypeReg);
if (!rhs->isConstant()) if (!rhs->isConstant())
@ -545,7 +545,7 @@ mjit::Compiler::jsop_binary(JSOp op, VoidStub stub)
frame.popn(2); frame.popn(2);
if (canDoIntMath) if (canDoIntMath)
frame.pushUntypedPayload(JSVAL_TAG_INT32, returnReg); frame.pushUntypedPayload(JSVAL_TYPE_INT32, returnReg);
else else
frame.pushSynced(); frame.pushSynced();
@ -560,7 +560,7 @@ mjit::Compiler::jsop_neg()
{ {
FrameEntry *fe = frame.peek(-1); FrameEntry *fe = frame.peek(-1);
if (fe->isTypeKnown() && fe->getTypeTag() > JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET) { if (fe->isTypeKnown() && fe->getKnownType() > JSVAL_UPPER_INCL_TYPE_OF_NUMBER_SET) {
prepareStubCall(); prepareStubCall();
stubCall(stubs::Neg, Uses(1), Defs(1)); stubCall(stubs::Neg, Uses(1), Defs(1));
frame.pop(); frame.pop();

View File

@ -65,7 +65,7 @@ mjit::Compiler::jsop_bindname(uint32 index)
stubcc.leave(); stubcc.leave();
stubcc.call(stubs::BindName); stubcc.call(stubs::BindName);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, reg); frame.pushTypedPayload(JSVAL_TYPE_OBJECT, reg);
stubcc.rejoin(1); stubcc.rejoin(1);
} }
@ -76,11 +76,11 @@ mjit::Compiler::jsop_bitnot()
FrameEntry *top = frame.peek(-1); FrameEntry *top = frame.peek(-1);
/* We only want to handle integers here. */ /* We only want to handle integers here. */
if (top->isTypeKnown() && top->getTypeTag() != JSVAL_TAG_INT32) { if (top->isTypeKnown() && top->getKnownType() != JSVAL_TYPE_INT32) {
prepareStubCall(); prepareStubCall();
stubCall(stubs::BitNot, Uses(1), Defs(1)); stubCall(stubs::BitNot, Uses(1), Defs(1));
frame.pop(); frame.pop();
frame.pushSyncedType(JSVAL_TAG_INT32); frame.pushSyncedType(JSVAL_TYPE_INT32);
return; return;
} }
@ -89,7 +89,7 @@ mjit::Compiler::jsop_bitnot()
if (!top->isTypeKnown()) { if (!top->isTypeKnown()) {
Jump intFail = frame.testInt32(Assembler::NotEqual, top); Jump intFail = frame.testInt32(Assembler::NotEqual, top);
stubcc.linkExit(intFail); stubcc.linkExit(intFail);
frame.learnType(top, JSVAL_TAG_INT32); frame.learnType(top, JSVAL_TYPE_INT32);
stubNeeded = true; stubNeeded = true;
} }
@ -101,7 +101,7 @@ mjit::Compiler::jsop_bitnot()
RegisterID reg = frame.ownRegForData(top); RegisterID reg = frame.ownRegForData(top);
masm.not32(reg); masm.not32(reg);
frame.pop(); frame.pop();
frame.pushTypedPayload(JSVAL_TAG_INT32, reg); frame.pushTypedPayload(JSVAL_TYPE_INT32, reg);
if (stubNeeded) if (stubNeeded)
stubcc.rejoin(1); stubcc.rejoin(1);
@ -136,12 +136,12 @@ mjit::Compiler::jsop_bitop(JSOp op)
} }
/* We only want to handle integers here. */ /* We only want to handle integers here. */
if ((rhs->isTypeKnown() && rhs->getTypeTag() != JSVAL_TAG_INT32) || if ((rhs->isTypeKnown() && rhs->getKnownType() != JSVAL_TYPE_INT32) ||
(lhs->isTypeKnown() && lhs->getTypeTag() != JSVAL_TAG_INT32)) { (lhs->isTypeKnown() && lhs->getKnownType() != JSVAL_TYPE_INT32)) {
prepareStubCall(); prepareStubCall();
stubCall(stub, Uses(2), Defs(1)); stubCall(stub, Uses(2), Defs(1));
frame.popn(2); frame.popn(2);
frame.pushSyncedType(JSVAL_TAG_INT32); frame.pushSyncedType(JSVAL_TYPE_INT32);
return; return;
} }
@ -150,7 +150,7 @@ mjit::Compiler::jsop_bitop(JSOp op)
if (!rhs->isTypeKnown()) { if (!rhs->isTypeKnown()) {
Jump rhsFail = frame.testInt32(Assembler::NotEqual, rhs); Jump rhsFail = frame.testInt32(Assembler::NotEqual, rhs);
stubcc.linkExit(rhsFail); stubcc.linkExit(rhsFail);
frame.learnType(rhs, JSVAL_TAG_INT32); frame.learnType(rhs, JSVAL_TYPE_INT32);
stubNeeded = true; stubNeeded = true;
} }
if (!lhs->isTypeKnown()) { if (!lhs->isTypeKnown()) {
@ -248,7 +248,7 @@ mjit::Compiler::jsop_bitop(JSOp op)
* Type of LHS should be learned already. * Type of LHS should be learned already.
*/ */
frame.popn(2); frame.popn(2);
frame.pushTypedPayload(JSVAL_TAG_INT32, reg); frame.pushTypedPayload(JSVAL_TYPE_INT32, reg);
if (stubNeeded) if (stubNeeded)
stubcc.rejoin(1); stubcc.rejoin(1);
return; return;
@ -302,7 +302,7 @@ mjit::Compiler::jsop_bitop(JSOp op)
frame.pop(); frame.pop();
frame.pop(); frame.pop();
frame.pushTypedPayload(JSVAL_TAG_INT32, reg); frame.pushTypedPayload(JSVAL_TYPE_INT32, reg);
if (stubNeeded) if (stubNeeded)
stubcc.rejoin(2); stubcc.rejoin(2);
@ -355,7 +355,7 @@ mjit::Compiler::jsop_globalinc(JSOp op, uint32 index)
masm.storeData32(data, addr); masm.storeData32(data, addr);
if (!post && !popped) if (!post && !popped)
frame.pushUntypedPayload(JSVAL_TAG_INT32, data); frame.pushUntypedPayload(JSVAL_TYPE_INT32, data);
else else
frame.freeReg(data); frame.freeReg(data);
@ -365,16 +365,12 @@ mjit::Compiler::jsop_globalinc(JSOp op, uint32 index)
} }
static inline bool static inline bool
CheckNullOrUndefined(FrameEntry *fe, JSValueTag &mask) CheckNullOrUndefined(FrameEntry *fe)
{ {
if (!fe->isTypeKnown()) if (!fe->isTypeKnown())
return false; return false;
mask = fe->getTypeTag(); JSValueType type = fe->getKnownType();
if (mask == JSVAL_TAG_NULL) return type == JSVAL_TYPE_NULL || type == JSVAL_TYPE_UNDEFINED;
return true;
else if (mask == JSVAL_TAG_UNDEFINED)
return true;
return false;
} }
void void
@ -387,8 +383,7 @@ mjit::Compiler::jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp f
JS_ASSERT(!(rhs->isConstant() && lhs->isConstant())); JS_ASSERT(!(rhs->isConstant() && lhs->isConstant()));
bool lhsTest; bool lhsTest;
JSValueTag mask; if ((lhsTest = CheckNullOrUndefined(lhs)) || CheckNullOrUndefined(rhs)) {
if ((lhsTest = CheckNullOrUndefined(lhs, mask)) || CheckNullOrUndefined(rhs, mask)) {
/* What's the other mask? */ /* What's the other mask? */
FrameEntry *test = lhsTest ? rhs : lhs; FrameEntry *test = lhsTest ? rhs : lhs;
@ -431,7 +426,7 @@ mjit::Compiler::jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp f
j.linkTo(masm.label(), &masm); j.linkTo(masm.label(), &masm);
masm.move(Imm32(op == JSOP_EQ), reg); masm.move(Imm32(op == JSOP_EQ), reg);
j3.linkTo(masm.label(), &masm); j3.linkTo(masm.label(), &masm);
frame.pushTypedPayload(JSVAL_TAG_BOOLEAN, reg); frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, reg);
} }
return; return;
} }
@ -449,8 +444,8 @@ mjit::Compiler::jsop_relational(JSOp op, BoolStub stub, jsbytecode *target, JSOp
JS_ASSERT(!(rhs->isConstant() && lhs->isConstant())); JS_ASSERT(!(rhs->isConstant() && lhs->isConstant()));
/* Always slow path... */ /* Always slow path... */
if ((rhs->isTypeKnown() && rhs->getTypeTag() != JSVAL_TAG_INT32) || if ((rhs->isTypeKnown() && rhs->getKnownType() != JSVAL_TYPE_INT32) ||
(lhs->isTypeKnown() && lhs->getTypeTag() != JSVAL_TAG_INT32)) { (lhs->isTypeKnown() && lhs->getKnownType() != JSVAL_TYPE_INT32)) {
if (op == JSOP_EQ || op == JSOP_NE) if (op == JSOP_EQ || op == JSOP_NE)
jsop_equality(op, stub, target, fused); jsop_equality(op, stub, target, fused);
else else
@ -462,7 +457,7 @@ mjit::Compiler::jsop_relational(JSOp op, BoolStub stub, jsbytecode *target, JSOp
if (!rhs->isTypeKnown()) { if (!rhs->isTypeKnown()) {
Jump rhsFail = frame.testInt32(Assembler::NotEqual, rhs); Jump rhsFail = frame.testInt32(Assembler::NotEqual, rhs);
stubcc.linkExit(rhsFail); stubcc.linkExit(rhsFail);
frame.learnType(rhs, JSVAL_TAG_INT32); frame.learnType(rhs, JSVAL_TYPE_INT32);
} }
if (!lhs->isTypeKnown()) { if (!lhs->isTypeKnown()) {
Jump lhsFail = frame.testInt32(Assembler::NotEqual, lhs); Jump lhsFail = frame.testInt32(Assembler::NotEqual, lhs);
@ -626,7 +621,7 @@ mjit::Compiler::jsop_relational(JSOp op, BoolStub stub, jsbytecode *target, JSOp
frame.pop(); frame.pop();
if (reg != resultReg) if (reg != resultReg)
frame.freeReg(reg); frame.freeReg(reg);
frame.pushTypedPayload(JSVAL_TAG_BOOLEAN, resultReg); frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, resultReg);
stubcc.rejoin(1); stubcc.rejoin(1);
} }
} }
@ -653,9 +648,9 @@ mjit::Compiler::jsop_not()
} }
if (top->isTypeKnown()) { if (top->isTypeKnown()) {
uint32 mask = top->getTypeTag(); JSValueType type = top->getKnownType();
switch (mask) { switch (type) {
case JSVAL_TAG_INT32: case JSVAL_TYPE_INT32:
{ {
RegisterID data = frame.allocReg(Registers::SingleByteRegs); RegisterID data = frame.allocReg(Registers::SingleByteRegs);
if (frame.shouldAvoidDataRemat(top)) if (frame.shouldAvoidDataRemat(top))
@ -666,22 +661,22 @@ mjit::Compiler::jsop_not()
masm.set32(Assembler::Equal, data, Imm32(0), data); masm.set32(Assembler::Equal, data, Imm32(0), data);
frame.pop(); frame.pop();
frame.pushTypedPayload(JSVAL_TAG_BOOLEAN, data); frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, data);
break; break;
} }
case JSVAL_TAG_BOOLEAN: case JSVAL_TYPE_BOOLEAN:
{ {
RegisterID reg = frame.ownRegForData(top); RegisterID reg = frame.ownRegForData(top);
masm.xor32(Imm32(1), reg); masm.xor32(Imm32(1), reg);
frame.pop(); frame.pop();
frame.pushTypedPayload(JSVAL_TAG_BOOLEAN, reg); frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, reg);
break; break;
} }
case JSVAL_TAG_OBJECT: case JSVAL_TYPE_OBJECT:
{ {
frame.pop(); frame.pop();
frame.push(BooleanTag(false)); frame.push(BooleanTag(false));
@ -698,7 +693,7 @@ mjit::Compiler::jsop_not()
masm.xor32(Imm32(1), reg); masm.xor32(Imm32(1), reg);
frame.pop(); frame.pop();
frame.pushTypedPayload(JSVAL_TAG_BOOLEAN, reg); frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, reg);
break; break;
} }
} }
@ -751,7 +746,7 @@ mjit::Compiler::jsop_not()
stubcc.call(stubs::Not); stubcc.call(stubs::Not);
frame.pop(); frame.pop();
frame.pushTypedPayload(JSVAL_TAG_BOOLEAN, data); frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, data);
stubcc.rejoin(1); stubcc.rejoin(1);
} }
@ -765,20 +760,20 @@ mjit::Compiler::jsop_typeof()
JSRuntime *rt = cx->runtime; JSRuntime *rt = cx->runtime;
JSAtom *atom = NULL; JSAtom *atom = NULL;
switch (fe->getTypeTag()) { switch (fe->getKnownType()) {
case JSVAL_TAG_STRING: case JSVAL_TYPE_STRING:
atom = rt->atomState.typeAtoms[JSTYPE_STRING]; atom = rt->atomState.typeAtoms[JSTYPE_STRING];
break; break;
case JSVAL_TAG_UNDEFINED: case JSVAL_TYPE_UNDEFINED:
atom = rt->atomState.typeAtoms[JSTYPE_VOID]; atom = rt->atomState.typeAtoms[JSTYPE_VOID];
break; break;
case JSVAL_TAG_NULL: case JSVAL_TYPE_NULL:
atom = rt->atomState.typeAtoms[JSTYPE_OBJECT]; atom = rt->atomState.typeAtoms[JSTYPE_OBJECT];
break; break;
case JSVAL_TAG_OBJECT: case JSVAL_TYPE_OBJECT:
atom = NULL; atom = NULL;
break; break;
case JSVAL_TAG_BOOLEAN: case JSVAL_TYPE_BOOLEAN:
atom = rt->atomState.typeAtoms[JSTYPE_BOOLEAN]; atom = rt->atomState.typeAtoms[JSTYPE_BOOLEAN];
break; break;
default: default:
@ -797,7 +792,7 @@ mjit::Compiler::jsop_typeof()
stubCall(stubs::TypeOf, Uses(1), Defs(1)); stubCall(stubs::TypeOf, Uses(1), Defs(1));
frame.pop(); frame.pop();
frame.takeReg(Registers::ReturnReg); frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_STRING, Registers::ReturnReg); frame.pushTypedPayload(JSVAL_TYPE_STRING, Registers::ReturnReg);
} }
void void
@ -828,7 +823,7 @@ mjit::Compiler::jsop_localinc(JSOp op, uint32 slot, bool popped)
fe = frame.peek(-1); fe = frame.peek(-1);
} }
if (!fe->isTypeKnown() || fe->getTypeTag() != JSVAL_TAG_INT32) { if (!fe->isTypeKnown() || fe->getKnownType() != JSVAL_TYPE_INT32) {
/* :TODO: do something smarter for the known-type-is-bad case. */ /* :TODO: do something smarter for the known-type-is-bad case. */
if (fe->isTypeKnown()) { if (fe->isTypeKnown()) {
Jump j = masm.jump(); Jump j = masm.jump();
@ -856,7 +851,7 @@ mjit::Compiler::jsop_localinc(JSOp op, uint32 slot, bool popped)
Registers::ArgReg1); Registers::ArgReg1);
stubcc.vpInc(op, depth); stubcc.vpInc(op, depth);
frame.pushUntypedPayload(JSVAL_TAG_INT32, reg, true, true); frame.pushUntypedPayload(JSVAL_TYPE_INT32, reg, true, true);
frame.storeLocal(slot, post || popped, false); frame.storeLocal(slot, post || popped, false);
if (post || popped) if (post || popped)
@ -897,7 +892,7 @@ mjit::Compiler::jsop_arginc(JSOp op, uint32 slot, bool popped)
stubcc.masm.addPtr(Imm32(sizeof(Value) * slot), Registers::ArgReg1, Registers::ArgReg1); stubcc.masm.addPtr(Imm32(sizeof(Value) * slot), Registers::ArgReg1, Registers::ArgReg1);
stubcc.vpInc(op, depth); stubcc.vpInc(op, depth);
frame.pushTypedPayload(JSVAL_TAG_INT32, reg); frame.pushTypedPayload(JSVAL_TYPE_INT32, reg);
fe = frame.peek(-1); fe = frame.peek(-1);
reg = frame.allocReg(); reg = frame.allocReg();
@ -921,8 +916,8 @@ mjit::Compiler::jsop_setelem()
FrameEntry *id = frame.peek(-2); FrameEntry *id = frame.peek(-2);
FrameEntry *fe = frame.peek(-1); FrameEntry *fe = frame.peek(-1);
if ((obj->isTypeKnown() && obj->getTypeTag() != JSVAL_TAG_OBJECT) || if ((obj->isTypeKnown() && obj->getKnownType() != JSVAL_TYPE_OBJECT) ||
(id->isTypeKnown() && id->getTypeTag() != JSVAL_TAG_INT32) || (id->isTypeKnown() && id->getKnownType() != JSVAL_TYPE_INT32) ||
(id->isConstant() && id->getValue().asInt32() < 0)) { (id->isConstant() && id->getValue().asInt32() < 0)) {
jsop_setelem_slow(); jsop_setelem_slow();
return; return;
@ -977,7 +972,7 @@ mjit::Compiler::jsop_setelem()
} else { } else {
masm.storeData32(frame.tempRegForData(fe), slot); masm.storeData32(frame.tempRegForData(fe), slot);
if (fe->isTypeKnown()) if (fe->isTypeKnown())
masm.storeTypeTag(ImmTag(fe->getTypeTag()), slot); masm.storeTypeTag(ImmTag(fe->getKnownTag()), slot);
else else
masm.storeTypeTag(frame.tempRegForType(fe), slot); masm.storeTypeTag(frame.tempRegForType(fe), slot);
} }
@ -1006,7 +1001,7 @@ mjit::Compiler::jsop_setelem()
} else { } else {
masm.storeData32(frame.tempRegForData(fe), slot); masm.storeData32(frame.tempRegForData(fe), slot);
if (fe->isTypeKnown()) if (fe->isTypeKnown())
masm.storeTypeTag(ImmTag(fe->getTypeTag()), slot); masm.storeTypeTag(ImmTag(fe->getKnownTag()), slot);
else else
masm.storeTypeTag(frame.tempRegForType(fe), slot); masm.storeTypeTag(frame.tempRegForType(fe), slot);
} }
@ -1025,8 +1020,8 @@ mjit::Compiler::jsop_getelem()
FrameEntry *obj = frame.peek(-2); FrameEntry *obj = frame.peek(-2);
FrameEntry *id = frame.peek(-1); FrameEntry *id = frame.peek(-1);
if ((obj->isTypeKnown() && obj->getTypeTag() != JSVAL_TAG_OBJECT) || if ((obj->isTypeKnown() && obj->getKnownType() != JSVAL_TYPE_OBJECT) ||
(id->isTypeKnown() && id->getTypeTag() != JSVAL_TAG_INT32) || (id->isTypeKnown() && id->getKnownType() != JSVAL_TYPE_INT32) ||
(id->isConstant() && id->getValue().asInt32() < 0)) { (id->isConstant() && id->getValue().asInt32() < 0)) {
jsop_getelem_slow(); jsop_getelem_slow();
return; return;
@ -1102,18 +1097,18 @@ mjit::Compiler::jsop_getelem()
} }
static inline bool static inline bool
ReallySimpleStrictTest(FrameEntry *fe, JSValueTag &mask) ReallySimpleStrictTest(FrameEntry *fe)
{ {
if (!fe->isTypeKnown()) if (!fe->isTypeKnown())
return false; return false;
mask = fe->getTypeTag(); JSValueType type = fe->getKnownType();
return mask == JSVAL_TAG_NULL || mask == JSVAL_TAG_UNDEFINED; return type == JSVAL_TYPE_NULL || type == JSVAL_TYPE_UNDEFINED;
} }
static inline bool static inline bool
BooleanStrictTest(FrameEntry *fe) BooleanStrictTest(FrameEntry *fe)
{ {
return fe->isConstant() && fe->getTypeTag() == JSVAL_TAG_BOOLEAN; return fe->isConstant() && fe->getKnownType() == JSVAL_TYPE_BOOLEAN;
} }
void void
@ -1126,16 +1121,20 @@ mjit::Compiler::jsop_stricteq(JSOp op)
/* Comparison against undefined or null is super easy. */ /* Comparison against undefined or null is super easy. */
bool lhsTest; bool lhsTest;
JSValueTag mask; if ((lhsTest = ReallySimpleStrictTest(lhs)) || ReallySimpleStrictTest(rhs)) {
if ((lhsTest = ReallySimpleStrictTest(lhs, mask)) || ReallySimpleStrictTest(rhs, mask)) {
FrameEntry *test = lhsTest ? rhs : lhs; FrameEntry *test = lhsTest ? rhs : lhs;
if (test->isTypeKnown()) { if (test->isTypeKnown()) {
FrameEntry *known = lhsTest ? lhs : rhs;
frame.popn(2); frame.popn(2);
frame.push(BooleanTag((test->getTypeTag() == mask) == (op == JSOP_STRICTEQ))); frame.push(BooleanTag((test->getKnownType() == known->getKnownType()) ==
(op == JSOP_STRICTEQ)));
return; return;
} }
FrameEntry *known = lhsTest ? lhs : rhs;
JSValueTag mask = known->getKnownTag();
/* This is only true if the other side is |null|. */ /* This is only true if the other side is |null|. */
RegisterID result = frame.allocReg(Registers::SingleByteRegs); RegisterID result = frame.allocReg(Registers::SingleByteRegs);
if (frame.shouldAvoidTypeRemat(test)) if (frame.shouldAvoidTypeRemat(test))
@ -1143,7 +1142,7 @@ mjit::Compiler::jsop_stricteq(JSOp op)
else else
masm.set32(cond, frame.tempRegForType(test), Imm32(mask), result); masm.set32(cond, frame.tempRegForType(test), Imm32(mask), result);
frame.popn(2); frame.popn(2);
frame.pushTypedPayload(JSVAL_TAG_BOOLEAN, result); frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, result);
return; return;
} }
@ -1151,7 +1150,7 @@ mjit::Compiler::jsop_stricteq(JSOp op)
if ((lhsTest = BooleanStrictTest(lhs)) || BooleanStrictTest(rhs)) { if ((lhsTest = BooleanStrictTest(lhs)) || BooleanStrictTest(rhs)) {
FrameEntry *test = lhsTest ? rhs : lhs; FrameEntry *test = lhsTest ? rhs : lhs;
if (test->isTypeKnown() && test->getTypeTag() != JSVAL_TAG_BOOLEAN) { if (test->isTypeKnown() && test->getKnownType() != JSVAL_TYPE_BOOLEAN) {
frame.popn(2); frame.popn(2);
frame.push(BooleanTag(op == JSOP_STRICTNE)); frame.push(BooleanTag(op == JSOP_STRICTNE));
return; return;
@ -1187,7 +1186,7 @@ mjit::Compiler::jsop_stricteq(JSOp op)
} }
frame.popn(2); frame.popn(2);
frame.pushTypedPayload(JSVAL_TAG_BOOLEAN, result); frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, result);
return; return;
} }
@ -1198,7 +1197,7 @@ mjit::Compiler::jsop_stricteq(JSOp op)
stubCall(stubs::StrictNe, Uses(2), Defs(1)); stubCall(stubs::StrictNe, Uses(2), Defs(1));
frame.popn(2); frame.popn(2);
frame.takeReg(Registers::ReturnReg); frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_BOOLEAN, Registers::ReturnReg); frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, Registers::ReturnReg);
} }
void void
@ -1207,7 +1206,7 @@ mjit::Compiler::jsop_pos()
FrameEntry *top = frame.peek(-1); FrameEntry *top = frame.peek(-1);
if (top->isTypeKnown()) { if (top->isTypeKnown()) {
if (top->getTypeTag() <= JSVAL_TAG_INT32) if (top->getKnownType() <= JSVAL_TYPE_INT32)
return; return;
prepareStubCall(); prepareStubCall();
stubCall(stubs::Pos, Uses(1), Defs(1)); stubCall(stubs::Pos, Uses(1), Defs(1));