From 986ed711e2b6a7fc951be8bd2ea51ce01ff7accc Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Tue, 23 Apr 2013 16:34:02 -0600 Subject: [PATCH] Bug 862103 - Split GuardShapeOrType into GuardShape and GuardObjectType, r=dvander. --- js/src/ion/IonBuilder.cpp | 4 +- js/src/ion/LOpcodes.h | 3 +- js/src/ion/MIR.cpp | 9 +- js/src/ion/MIR.h | 84 +++++++++++++------ js/src/ion/MOpcodes.h | 3 +- js/src/ion/ParallelArrayAnalysis.cpp | 3 +- js/src/ion/arm/CodeGenerator-arm.cpp | 27 +++--- js/src/ion/arm/CodeGenerator-arm.h | 3 +- js/src/ion/arm/LIR-arm.h | 28 +++++-- js/src/ion/arm/Lowering-arm.cpp | 18 +++- js/src/ion/arm/Lowering-arm.h | 3 +- .../ion/shared/CodeGenerator-x86-shared.cpp | 20 +++-- js/src/ion/shared/CodeGenerator-x86-shared.h | 3 +- js/src/ion/shared/LIR-x86-shared.h | 24 ++++-- js/src/ion/shared/Lowering-x86-shared.cpp | 17 +++- js/src/ion/shared/Lowering-x86-shared.h | 3 +- 16 files changed, 178 insertions(+), 74 deletions(-) diff --git a/js/src/ion/IonBuilder.cpp b/js/src/ion/IonBuilder.cpp index f4128cda893..a2a39d5848c 100644 --- a/js/src/ion/IonBuilder.cpp +++ b/js/src/ion/IonBuilder.cpp @@ -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. diff --git a/js/src/ion/LOpcodes.h b/js/src/ion/LOpcodes.h index d0fd6d75c7d..af1fe56f1bb 100644 --- a/js/src/ion/LOpcodes.h +++ b/js/src/ion/LOpcodes.h @@ -130,7 +130,8 @@ _(LoadSlotT) \ _(StoreSlotV) \ _(StoreSlotT) \ - _(GuardShapeOrType) \ + _(GuardShape) \ + _(GuardObjectType) \ _(GuardClass) \ _(ParWriteGuard) \ _(ParDump) \ diff --git a/js/src/ion/MIR.cpp b/js/src/ion/MIR.cpp index ddb9ed69126..ca8d3ccfa79 100644 --- a/js/src/ion/MIR.cpp +++ b/js/src/ion/MIR.cpp @@ -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; } diff --git a/js/src/ion/MIR.h b/js/src/ion/MIR.h index 7a85f3d59cf..59c43e101b9 100644 --- a/js/src/ion/MIR.h +++ b/js/src/ion/MIR.h @@ -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 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 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); } diff --git a/js/src/ion/MOpcodes.h b/js/src/ion/MOpcodes.h index c77ae23d665..1808ca4f730 100644 --- a/js/src/ion/MOpcodes.h +++ b/js/src/ion/MOpcodes.h @@ -102,7 +102,8 @@ namespace ion { _(GetPropertyCache) \ _(GetElementCache) \ _(BindNameCache) \ - _(GuardShapeOrType) \ + _(GuardShape) \ + _(GuardObjectType) \ _(GuardClass) \ _(ArrayLength) \ _(TypedArrayLength) \ diff --git a/js/src/ion/ParallelArrayAnalysis.cpp b/js/src/ion/ParallelArrayAnalysis.cpp index e2ad285949d..cfe7c616d6b 100644 --- a/js/src/ion/ParallelArrayAnalysis.cpp +++ b/js/src/ion/ParallelArrayAnalysis.cpp @@ -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) diff --git a/js/src/ion/arm/CodeGenerator-arm.cpp b/js/src/ion/arm/CodeGenerator-arm.cpp index 693c2f978ac..a8eb1fd76f3 100644 --- a/js/src/ion/arm/CodeGenerator-arm.cpp +++ b/js/src/ion/arm/CodeGenerator-arm.cpp @@ -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 diff --git a/js/src/ion/arm/CodeGenerator-arm.h b/js/src/ion/arm/CodeGenerator-arm.h index 0f5a9000f35..d2965216424 100644 --- a/js/src/ion/arm/CodeGenerator-arm.h +++ b/js/src/ion/arm/CodeGenerator-arm.h @@ -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); diff --git a/js/src/ion/arm/LIR-arm.h b/js/src/ion/arm/LIR-arm.h index 083289b884b..83db1da05f6 100644 --- a/js/src/ion/arm/LIR-arm.h +++ b/js/src/ion/arm/LIR-arm.h @@ -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(); diff --git a/js/src/ion/arm/Lowering-arm.cpp b/js/src/ion/arm/Lowering-arm.cpp index eea2e5b8245..baf27342811 100644 --- a/js/src/ion/arm/Lowering-arm.cpp +++ b/js/src/ion/arm/Lowering-arm.cpp @@ -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) { diff --git a/js/src/ion/arm/Lowering-arm.h b/js/src/ion/arm/Lowering-arm.h index ee9bf91f348..27103ac5d24 100644 --- a/js/src/ion/arm/Lowering-arm.h +++ b/js/src/ion/arm/Lowering-arm.h @@ -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); diff --git a/js/src/ion/shared/CodeGenerator-x86-shared.cpp b/js/src/ion/shared/CodeGenerator-x86-shared.cpp index 0b4526b518e..9672f5c0100 100644 --- a/js/src/ion/shared/CodeGenerator-x86-shared.cpp +++ b/js/src/ion/shared/CodeGenerator-x86-shared.cpp @@ -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 diff --git a/js/src/ion/shared/CodeGenerator-x86-shared.h b/js/src/ion/shared/CodeGenerator-x86-shared.h index ca031a6d564..c970813134a 100644 --- a/js/src/ion/shared/CodeGenerator-x86-shared.h +++ b/js/src/ion/shared/CodeGenerator-x86-shared.h @@ -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); diff --git a/js/src/ion/shared/LIR-x86-shared.h b/js/src/ion/shared/LIR-x86-shared.h index d1fc52261eb..d743ebf41a1 100644 --- a/js/src/ion/shared/LIR-x86-shared.h +++ b/js/src/ion/shared/LIR-x86-shared.h @@ -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(); } }; diff --git a/js/src/ion/shared/Lowering-x86-shared.cpp b/js/src/ion/shared/Lowering-x86-shared.cpp index 1fdfa7422b0..607eecc6de1 100644 --- a/js/src/ion/shared/Lowering-x86-shared.cpp +++ b/js/src/ion/shared/Lowering-x86-shared.cpp @@ -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) { diff --git a/js/src/ion/shared/Lowering-x86-shared.h b/js/src/ion/shared/Lowering-x86-shared.h index 751acedfe23..7a299269937 100644 --- a/js/src/ion/shared/Lowering-x86-shared.h +++ b/js/src/ion/shared/Lowering-x86-shared.h @@ -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);