Bug 862103 - Split GuardShapeOrType into GuardShape and GuardObjectType, r=dvander.

This commit is contained in:
Brian Hackett 2013-04-23 16:34:02 -06:00
parent cfcc459275
commit 986ed711e2
16 changed files with 178 additions and 74 deletions

View File

@ -6728,7 +6728,7 @@ IonBuilder::TestCommonPropFunc(JSContext *cx, types::StackTypeSet *types, Handle
// Pass the guard back so it can be an operand.
if (isGetter) {
JS_ASSERT(wrapper->isGuardShapeOrType());
JS_ASSERT(wrapper->isGuardShape());
*guardOut = wrapper;
}
@ -7746,7 +7746,7 @@ IonBuilder::addBoundsCheck(MDefinition *index, MDefinition *length)
MInstruction *
IonBuilder::addShapeGuard(MDefinition *obj, const RawShape shape, BailoutKind bailoutKind)
{
MGuardShapeOrType *guard = MGuardShapeOrType::New(obj, shape, NULL, false, bailoutKind);
MGuardShape *guard = MGuardShape::New(obj, shape, bailoutKind);
current->add(guard);
// If a shape guard failed in the past, don't optimize shape guard.

View File

@ -130,7 +130,8 @@
_(LoadSlotT) \
_(StoreSlotV) \
_(StoreSlotT) \
_(GuardShapeOrType) \
_(GuardShape) \
_(GuardObjectType) \
_(GuardClass) \
_(ParWriteGuard) \
_(ParDump) \

View File

@ -2480,13 +2480,12 @@ TryAddTypeBarrierForWrite(JSContext *cx, MBasicBlock *current, types::StackTypeS
static MInstruction *
AddTypeGuard(MBasicBlock *current, MDefinition *obj, types::TypeObject *typeObject,
bool bailOnEquality, BailoutKind bailoutKind)
bool bailOnEquality)
{
MGuardShapeOrType *guard = MGuardShapeOrType::New(obj, NULL, typeObject,
bailOnEquality, bailoutKind);
MGuardObjectType *guard = MGuardObjectType::New(obj, typeObject, bailOnEquality);
current->add(guard);
// For now, never move type guards.
// For now, never move type object guards.
guard->setNotMovable();
return guard;
@ -2576,6 +2575,6 @@ ion::PropertyWriteNeedsTypeBarrier(JSContext *cx, MBasicBlock *current, MDefinit
JS_ASSERT(excluded);
*pobj = AddTypeGuard(current, *pobj, excluded, /* bailOnEquality = */ true, Bailout_Normal);
*pobj = AddTypeGuard(current, *pobj, excluded, /* bailOnEquality = */ true);
return false;
}

View File

@ -5525,37 +5525,29 @@ class MBindNameCache
}
};
// Guard on an object's shape or type, either inclusively or exclusively.
class MGuardShapeOrType
// Guard on an object's shape.
class MGuardShape
: public MUnaryInstruction,
public SingleObjectPolicy
{
CompilerRootShape shape_;
CompilerRoot<types::TypeObject*> typeObject_;
bool bailOnEquality_;
BailoutKind bailoutKind_;
MGuardShapeOrType(MDefinition *obj, Shape *shape, types::TypeObject *typeObject,
bool bailOnEquality, BailoutKind bailoutKind)
MGuardShape(MDefinition *obj, Shape *shape, BailoutKind bailoutKind)
: MUnaryInstruction(obj),
shape_(shape),
typeObject_(typeObject),
bailOnEquality_(bailOnEquality),
bailoutKind_(bailoutKind)
{
// Exactly one of the shape or type object to guard on must be specified.
JS_ASSERT(!!shape != !!typeObject);
setGuard();
setMovable();
setResultType(MIRType_Object);
}
public:
INSTRUCTION_HEADER(GuardShapeOrType)
INSTRUCTION_HEADER(GuardShape)
static MGuardShapeOrType *New(MDefinition *obj, Shape *shape, types::TypeObject *typeObject,
bool bailOnEquality, BailoutKind bailoutKind) {
return new MGuardShapeOrType(obj, shape, typeObject, bailOnEquality, bailoutKind);
static MGuardShape *New(MDefinition *obj, Shape *shape, BailoutKind bailoutKind) {
return new MGuardShape(obj, shape, bailoutKind);
}
TypePolicy *typePolicy() {
@ -5567,25 +5559,67 @@ class MGuardShapeOrType
const RawShape shape() const {
return shape_;
}
types::TypeObject *typeObject() const {
BailoutKind bailoutKind() const {
return bailoutKind_;
}
bool congruentTo(MDefinition * const &ins) const {
if (!ins->isGuardShape())
return false;
if (shape() != ins->toGuardShape()->shape())
return false;
if (bailoutKind() != ins->toGuardShape()->bailoutKind())
return false;
return congruentIfOperandsEqual(ins);
}
AliasSet getAliasSet() const {
return AliasSet::Load(AliasSet::ObjectFields);
}
};
// Guard on an object's type, inclusively or exclusively.
class MGuardObjectType
: public MUnaryInstruction,
public SingleObjectPolicy
{
CompilerRoot<types::TypeObject *> typeObject_;
bool bailOnEquality_;
MGuardObjectType(MDefinition *obj, types::TypeObject *typeObject, bool bailOnEquality)
: MUnaryInstruction(obj),
typeObject_(typeObject),
bailOnEquality_(bailOnEquality)
{
setGuard();
setMovable();
setResultType(MIRType_Object);
}
public:
INSTRUCTION_HEADER(GuardObjectType)
static MGuardObjectType *New(MDefinition *obj, types::TypeObject *typeObject,
bool bailOnEquality) {
return new MGuardObjectType(obj, typeObject, bailOnEquality);
}
TypePolicy *typePolicy() {
return this;
}
MDefinition *obj() const {
return getOperand(0);
}
const types::TypeObject *typeObject() const {
return typeObject_;
}
bool bailOnEquality() const {
return bailOnEquality_;
}
BailoutKind bailoutKind() const {
return bailoutKind_;
}
bool congruentTo(MDefinition * const &ins) const {
if (!ins->isGuardShapeOrType())
if (!ins->isGuardObjectType())
return false;
if (shape() != ins->toGuardShapeOrType()->shape())
if (typeObject() != ins->toGuardObjectType()->typeObject())
return false;
if (typeObject() != ins->toGuardShapeOrType()->typeObject())
return false;
if (bailOnEquality() != ins->toGuardShapeOrType()->bailOnEquality())
return false;
if (bailoutKind() != ins->toGuardShapeOrType()->bailoutKind())
if (bailOnEquality() != ins->toGuardObjectType()->bailOnEquality())
return false;
return congruentIfOperandsEqual(ins);
}

View File

@ -102,7 +102,8 @@ namespace ion {
_(GetPropertyCache) \
_(GetElementCache) \
_(BindNameCache) \
_(GuardShapeOrType) \
_(GuardShape) \
_(GuardObjectType) \
_(GuardClass) \
_(ArrayLength) \
_(TypedArrayLength) \

View File

@ -191,7 +191,8 @@ class ParallelArrayVisitor : public MInstructionVisitor
SAFE_OP(GetPropertyCache)
UNSAFE_OP(GetElementCache)
UNSAFE_OP(BindNameCache)
SAFE_OP(GuardShapeOrType)
SAFE_OP(GuardShape)
SAFE_OP(GuardObjectType)
SAFE_OP(GuardClass)
SAFE_OP(ArrayLength)
SAFE_OP(TypedArrayLength)

View File

@ -1541,24 +1541,29 @@ CodeGeneratorARM::storeElementTyped(const LAllocation *value, MIRType valueType,
}
bool
CodeGeneratorARM::visitGuardShapeOrType(LGuardShapeOrType *guard)
CodeGeneratorARM::visitGuardShape(LGuardShape *guard)
{
Register obj = ToRegister(guard->input());
Register tmp = ToRegister(guard->tempInt());
if (guard->mir()->shape()) {
masm.ma_ldr(DTRAddr(obj, DtrOffImm(JSObject::offsetOfShape())), tmp);
masm.ma_cmp(tmp, ImmGCPtr(guard->mir()->shape()));
} else {
masm.ma_ldr(DTRAddr(obj, DtrOffImm(JSObject::offsetOfType())), tmp);
masm.ma_cmp(tmp, ImmGCPtr(guard->mir()->typeObject()));
}
masm.ma_ldr(DTRAddr(obj, DtrOffImm(JSObject::offsetOfShape())), tmp);
masm.ma_cmp(tmp, ImmGCPtr(guard->mir()->shape()));
return bailoutIf(Assembler::NotEqual, guard->snapshot());
}
bool
CodeGeneratorARM::visitGuardObjectType(LGuardObjectType *guard)
{
Register obj = ToRegister(guard->input());
Register tmp = ToRegister(guard->tempInt());
masm.ma_ldr(DTRAddr(obj, DtrOffImm(JSObject::offsetOfType())), tmp);
masm.ma_cmp(tmp, ImmGCPtr(guard->mir()->typeObject()));
Assembler::Condition cond =
guard->mir()->bailOnEquality() ? Assembler::Equal : Assembler::NotEqual;
if (!bailoutIf(cond, guard->snapshot()))
return false;
return true;
return bailoutIf(cond, guard->snapshot());
}
bool

View File

@ -134,7 +134,8 @@ class CodeGeneratorARM : public CodeGeneratorShared
bool visitLoadElementT(LLoadElementT *load);
bool visitGuardShapeOrType(LGuardShapeOrType *guard);
bool visitGuardShape(LGuardShape *guard);
bool visitGuardObjectType(LGuardObjectType *guard);
bool visitGuardClass(LGuardClass *guard);
bool visitImplicitThis(LImplicitThis *lir);

View File

@ -262,18 +262,34 @@ class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 2>
}
};
// Guard against an object's shape.
class LGuardShapeOrType : public LInstructionHelper<0, 1, 1>
class LGuardShape : public LInstructionHelper<0, 1, 1>
{
public:
LIR_HEADER(GuardShapeOrType);
LIR_HEADER(GuardShape);
LGuardShapeOrType(const LAllocation &in, const LDefinition &temp) {
LGuardShape(const LAllocation &in, const LDefinition &temp) {
setOperand(0, in);
setTemp(0, temp);
}
const MGuardShapeOrType *mir() const {
return mir_->toGuardShapeOrType();
const MGuardShape *mir() const {
return mir_->toGuardShape();
}
const LAllocation *tempInt() {
return getTemp(0)->output();
}
};
class LGuardObjectType : public LInstructionHelper<0, 1, 1>
{
public:
LIR_HEADER(GuardObjectType);
LGuardObjectType(const LAllocation &in, const LDefinition &temp) {
setOperand(0, in);
setTemp(0, temp);
}
const MGuardObjectType *mir() const {
return mir_->toGuardObjectType();
}
const LAllocation *tempInt() {
return getTemp(0)->output();

View File

@ -302,12 +302,12 @@ LIRGeneratorARM::newLGetPropertyCacheT(MGetPropertyCache *ins)
}
bool
LIRGeneratorARM::visitGuardShapeOrType(MGuardShapeOrType *ins)
LIRGeneratorARM::visitGuardShape(MGuardShape *ins)
{
JS_ASSERT(ins->obj()->type() == MIRType_Object);
LDefinition tempObj = temp(LDefinition::OBJECT);
LGuardShapeOrType *guard = new LGuardShapeOrType(useRegister(ins->obj()), tempObj);
LGuardShape *guard = new LGuardShape(useRegister(ins->obj()), tempObj);
if (!assignSnapshot(guard, ins->bailoutKind()))
return false;
if (!add(guard, ins))
@ -315,6 +315,20 @@ LIRGeneratorARM::visitGuardShapeOrType(MGuardShapeOrType *ins)
return redefine(ins, ins->obj());
}
bool
LIRGeneratorARM::visitGuardObjectType(MGuardObjectType *ins)
{
JS_ASSERT(ins->obj()->type() == MIRType_Object);
LDefinition tempObj = temp(LDefinition::OBJECT);
LGuardObjectType *guard = new LGuardObjectType(useRegister(ins->obj()), tempObj);
if (!assignSnapshot(guard))
return false;
if (!add(guard, ins))
return false;
return redefine(ins, ins->obj());
}
bool
LIRGeneratorARM::visitStoreTypedArrayElement(MStoreTypedArrayElement *ins)
{

View File

@ -64,7 +64,8 @@ class LIRGeneratorARM : public LIRGeneratorShared
bool visitUnbox(MUnbox *unbox);
bool visitReturn(MReturn *ret);
bool lowerPhi(MPhi *phi);
bool visitGuardShapeOrType(MGuardShapeOrType *ins);
bool visitGuardShape(MGuardShape *ins);
bool visitGuardObjectType(MGuardObjectType *ins);
bool visitStoreTypedArrayElement(MStoreTypedArrayElement *ins);
bool visitStoreTypedArrayElementHole(MStoreTypedArrayElementHole *ins);
bool visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble *ins);

View File

@ -1302,19 +1302,23 @@ CodeGeneratorX86Shared::visitRound(LRound *lir)
}
bool
CodeGeneratorX86Shared::visitGuardShapeOrType(LGuardShapeOrType *guard)
CodeGeneratorX86Shared::visitGuardShape(LGuardShape *guard)
{
Register obj = ToRegister(guard->input());
if (guard->mir()->shape())
masm.cmpPtr(Operand(obj, JSObject::offsetOfShape()), ImmGCPtr(guard->mir()->shape()));
else
masm.cmpPtr(Operand(obj, JSObject::offsetOfType()), ImmGCPtr(guard->mir()->typeObject()));
masm.cmpPtr(Operand(obj, JSObject::offsetOfShape()), ImmGCPtr(guard->mir()->shape()));
return bailoutIf(Assembler::NotEqual, guard->snapshot());
}
bool
CodeGeneratorX86Shared::visitGuardObjectType(LGuardObjectType *guard)
{
Register obj = ToRegister(guard->input());
masm.cmpPtr(Operand(obj, JSObject::offsetOfType()), ImmGCPtr(guard->mir()->typeObject()));
Assembler::Condition cond =
guard->mir()->bailOnEquality() ? Assembler::Equal : Assembler::NotEqual;
if (!bailoutIf(cond, guard->snapshot()))
return false;
return true;
return bailoutIf(cond, guard->snapshot());
}
bool

View File

@ -102,7 +102,8 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
virtual bool visitMathD(LMathD *math);
virtual bool visitFloor(LFloor *lir);
virtual bool visitRound(LRound *lir);
virtual bool visitGuardShapeOrType(LGuardShapeOrType *guard);
virtual bool visitGuardShape(LGuardShape *guard);
virtual bool visitGuardObjectType(LGuardObjectType *guard);
virtual bool visitGuardClass(LGuardClass *guard);
virtual bool visitEffectiveAddress(LEffectiveAddress *ins);
virtual bool visitAsmJSDivOrMod(LAsmJSDivOrMod *ins);

View File

@ -173,17 +173,29 @@ class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 3>
}
};
// Guard against an object's shape.
class LGuardShapeOrType : public LInstructionHelper<0, 1, 0>
class LGuardShape : public LInstructionHelper<0, 1, 0>
{
public:
LIR_HEADER(GuardShapeOrType)
LIR_HEADER(GuardShape)
LGuardShapeOrType(const LAllocation &in) {
LGuardShape(const LAllocation &in) {
setOperand(0, in);
}
const MGuardShapeOrType *mir() const {
return mir_->toGuardShapeOrType();
const MGuardShape *mir() const {
return mir_->toGuardShape();
}
};
class LGuardObjectType : public LInstructionHelper<0, 1, 0>
{
public:
LIR_HEADER(GuardObjectType)
LGuardObjectType(const LAllocation &in) {
setOperand(0, in);
}
const MGuardObjectType *mir() const {
return mir_->toGuardObjectType();
}
};

View File

@ -36,11 +36,11 @@ LIRGeneratorX86Shared::visitInterruptCheck(MInterruptCheck *ins)
}
bool
LIRGeneratorX86Shared::visitGuardShapeOrType(MGuardShapeOrType *ins)
LIRGeneratorX86Shared::visitGuardShape(MGuardShape *ins)
{
JS_ASSERT(ins->obj()->type() == MIRType_Object);
LGuardShapeOrType *guard = new LGuardShapeOrType(useRegister(ins->obj()));
LGuardShape *guard = new LGuardShape(useRegister(ins->obj()));
if (!assignSnapshot(guard, ins->bailoutKind()))
return false;
if (!add(guard, ins))
@ -48,6 +48,19 @@ LIRGeneratorX86Shared::visitGuardShapeOrType(MGuardShapeOrType *ins)
return redefine(ins, ins->obj());
}
bool
LIRGeneratorX86Shared::visitGuardObjectType(MGuardObjectType *ins)
{
JS_ASSERT(ins->obj()->type() == MIRType_Object);
LGuardObjectType *guard = new LGuardObjectType(useRegister(ins->obj()));
if (!assignSnapshot(guard))
return false;
if (!add(guard, ins))
return false;
return redefine(ins, ins->obj());
}
bool
LIRGeneratorX86Shared::visitPowHalf(MPowHalf *ins)
{

View File

@ -24,7 +24,8 @@ class LIRGeneratorX86Shared : public LIRGeneratorShared
LTableSwitchV *newLTableSwitchV(MTableSwitch *ins);
bool visitInterruptCheck(MInterruptCheck *ins);
bool visitGuardShapeOrType(MGuardShapeOrType *ins);
bool visitGuardShape(MGuardShape *ins);
bool visitGuardObjectType(MGuardObjectType *ins);
bool visitPowHalf(MPowHalf *ins);
bool visitConstant(MConstant *ins);
bool visitAsmJSNeg(MAsmJSNeg *ins);