author | Eric Faust <efaustbmo@gmail.com> |
Wed, 28 Nov 2012 16:28:36 -0500 | |
changeset 114409 | c5c30b93ee5e109f9b3d7d55aafa1763c066f6c6 |
parent 114408 | 70c54d5c94b7b3914690c3a73dd0ab1a1a93b7d2 |
child 114410 | a5f259c99090e7f87323d6326090e39e7560b2a5 |
push id | 23917 |
push user | emorley@mozilla.com |
push date | Thu, 29 Nov 2012 14:20:29 +0000 |
treeherder | mozilla-central@c72d38e7a212 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | sstangl |
bugs | 747289 |
milestone | 20.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/src/ion/IonBuilder.cpp +++ b/js/src/ion/IonBuilder.cpp @@ -5346,17 +5346,18 @@ IonBuilder::jsop_not() current->add(ins); current->push(ins); return true; } inline bool IonBuilder::TestCommonPropFunc(JSContext *cx, types::StackTypeSet *types, HandleId id, - JSFunction **funcp, bool isGetter, bool *isDOM) + JSFunction **funcp, bool isGetter, bool *isDOM, + MDefinition **guardOut) { JSObject *found = NULL; JSObject *foundProto = NULL; *funcp = NULL; *isDOM = false; bool thinkDOM = true; @@ -5490,16 +5491,22 @@ IonBuilder::TestCommonPropFunc(JSContext // Add a shape guard on the prototype we found the property on. The rest of // the prototype chain is guarded by TI freezes. Note that a shape guard is // good enough here, even in the proxy case, because we have ensured there // are no lookup hooks for this property. MInstruction *wrapper = MConstant::New(ObjectValue(*foundProto)); current->add(wrapper); wrapper = addShapeGuard(wrapper, foundProto->lastProperty(), Bailout_ShapeGuard); + // Pass the guard back so it can be an operand. + if (isGetter) { + JS_ASSERT(wrapper->isGuardShape()); + *guardOut = wrapper; + } + // Now we have to freeze all the property typesets to ensure there isn't a // lower shadowing getter or setter installed in the future. types::TypeObject *curType; for (unsigned i = 0; i < types->getObjectCount(); i++) { curType = types->getTypeObject(i); JSObject *obj = NULL; if (!curType) { obj = types->getSingleObject(i); @@ -5952,32 +5959,36 @@ IonBuilder::getPropTryDefiniteSlot(bool bool IonBuilder::getPropTryCommonGetter(bool *emitted, HandleId id, types::StackTypeSet *barrier, types::StackTypeSet *types, TypeOracle::UnaryTypes unaryTypes) { JS_ASSERT(*emitted == false); JSFunction *commonGetter; bool isDOM; - - if (!TestCommonPropFunc(cx, unaryTypes.inTypes, id, &commonGetter, true, &isDOM)) + MDefinition *guard; + + if (!TestCommonPropFunc(cx, unaryTypes.inTypes, id, &commonGetter, true, + &isDOM, &guard)) + { return false; + } if (!commonGetter) return true; MDefinition *obj = current->pop(); RootedFunction getter(cx, commonGetter); if (isDOM && TestShouldDOMCall(cx, unaryTypes.inTypes, getter)) { const JSJitInfo *jitinfo = getter->jitInfo(); - MGetDOMProperty *get = MGetDOMProperty::New(jitinfo->op, obj, jitinfo->isInfallible); + MGetDOMProperty *get = MGetDOMProperty::New(jitinfo, obj, guard); current->add(get); current->push(get); - if (!resumeAfter(get)) + if (get->isEffectful() && !resumeAfter(get)) return false; if (!pushTypeBarrier(get, types, barrier)) return false; *emitted = true; return true; } @@ -6112,17 +6123,17 @@ IonBuilder::jsop_setprop(HandlePropertyN } } RootedId id(cx, NameToId(name)); types::StackTypeSet *types = binaryTypes.lhsTypes; JSFunction *commonSetter; bool isDOM; - if (!TestCommonPropFunc(cx, types, id, &commonSetter, false, &isDOM)) + if (!TestCommonPropFunc(cx, types, id, &commonSetter, false, &isDOM, NULL)) return false; if (!monitored && commonSetter) { RootedFunction setter(cx, commonSetter); if (isDOM && TestShouldDOMCall(cx, types, setter)) { MSetDOMProperty *set = MSetDOMProperty::New(setter->jitInfo()->op, obj, value); if (!set) return false;
--- a/js/src/ion/IonBuilder.h +++ b/js/src/ion/IonBuilder.h @@ -418,17 +418,18 @@ class IonBuilder : public MIRGenerator bool makeInliningDecision(AutoObjectVector &targets, uint32 argc); MCall *makeCallHelper(HandleFunction target, uint32 argc, bool constructing); bool makeCallBarrier(HandleFunction target, uint32 argc, bool constructing, types::StackTypeSet *types, types::StackTypeSet *barrier); inline bool TestCommonPropFunc(JSContext *cx, types::StackTypeSet *types, HandleId id, JSFunction **funcp, - bool isGetter, bool *isDOM); + bool isGetter, bool *isDOM, + MDefinition **guardOut); bool annotateGetPropertyCache(JSContext *cx, MDefinition *obj, MGetPropertyCache *getPropCache, types::StackTypeSet *objTypes, types::StackTypeSet *pushedTypes); MGetPropertyCache *checkInlineableGetPropertyCache(uint32_t argc); MPolyInlineDispatch * makePolyInlineDispatch(JSContext *cx, AutoObjectVector &targets, int argc,
--- a/js/src/ion/MIR.h +++ b/js/src/ion/MIR.h @@ -4950,51 +4950,90 @@ class MSetDOMProperty } TypePolicy *typePolicy() { return this; } }; class MGetDOMProperty - : public MAryInstruction<1>, + : public MAryInstruction<2>, public ObjectPolicy<0> { - const JSJitPropertyOp func_; - bool isInfallible_; - - MGetDOMProperty(const JSJitPropertyOp func, MDefinition *obj, bool isInfallible) - : func_(func), isInfallible_(isInfallible) + const JSJitInfo *info_; + + MGetDOMProperty(const JSJitInfo *jitinfo, MDefinition *obj, MDefinition *guard) + : info_(jitinfo) { + JS_ASSERT(jitinfo); + initOperand(0, obj); + // Pin the guard as an operand if we want to hoist later + initOperand(1, guard); + + // We are movable iff the jitinfo says we can be. + if (jitinfo->isConstant) + setMovable(); + setResultType(MIRType_Value); } + protected: + const JSJitInfo *info() const { + return info_; + } + public: INSTRUCTION_HEADER(GetDOMProperty); - static MGetDOMProperty *New(const JSJitPropertyOp func, MDefinition *obj, bool isInfallible) + static MGetDOMProperty *New(const JSJitInfo *info, MDefinition *obj, MDefinition *guard) { - return new MGetDOMProperty(func, obj, isInfallible); + return new MGetDOMProperty(info, obj, guard); } const JSJitPropertyOp fun() { - return func_; - } - bool isInfallible() { - return isInfallible_; + return info_->op; + } + bool isInfallible() const { + return info_->isInfallible; + } + bool isDomConstant() const { + return info_->isConstant; } MDefinition *object() { return getOperand(0); } TypePolicy *typePolicy() { return this; } + + bool congruentTo(MDefinition *const &ins) const { + if (!isDomConstant()) + return false; + + if (!ins->isGetDOMProperty()) + return false; + + // Checking the jitinfo is the same as checking the constant function + if (!(info() == ins->toGetDOMProperty()->info())) + return false; + + return congruentIfOperandsEqual(ins); + } + + AliasSet getAliasSet() const { + // The whole point of constancy is that it's non-effectful and doesn't + // conflict with anything + if (isDomConstant()) + return AliasSet::None(); + return AliasSet::Store(AliasSet::Any); + } + }; class MStringLength : public MUnaryInstruction, public StringPolicy { MStringLength(MDefinition *string) : MUnaryInstruction(string)