From 7b0ee8c76e164b2a799891aa9e1e935668b700f0 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Sat, 25 Oct 2014 00:50:28 -0400 Subject: [PATCH] Bug 1084150. Don't generate a getter or setter baseline IC stub if we know up front it won't match the sort of object we just did a get or set on. r=efaust --- js/src/jit/BaselineIC.cpp | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index 328e2d2739b..0dc84433a70 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -3533,7 +3533,7 @@ IsCacheableSetPropAddSlot(JSContext *cx, HandleObject obj, HandleShape oldShape, } static bool -IsCacheableSetPropCall(JSContext *cx, JSObject *obj, JSObject *holder, Shape *shape, bool *isScripted) +IsCacheableSetPropCall(JSContext *cx, JSObject *obj, JSObject *holder, Shape *shape, Shape* oldShape, bool *isScripted) { MOZ_ASSERT(isScripted); @@ -3541,6 +3541,13 @@ IsCacheableSetPropCall(JSContext *cx, JSObject *obj, JSObject *holder, Shape *sh if (obj == holder) return false; + if (obj->lastProperty() != oldShape) { + // During the property set, the shape of the object changed. Not much + // point caching this based on the post-set shape, since the object + // wouldn't have matched such an IC stub anyway. + return false; + } + if (!shape || !IsCacheableProtoChain(obj, holder)) return false; @@ -6281,7 +6288,8 @@ StripPreliminaryObjectStubs(JSContext *cx, ICFallbackStub *stub) static bool TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICGetProp_Fallback *stub, HandlePropertyName name, - HandleValue val, HandleValue res, bool *attached) + HandleValue val, HandleShape oldShape, + HandleValue res, bool *attached) { MOZ_ASSERT(!*attached); @@ -6290,6 +6298,11 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, RootedObject obj(cx, &val.toObject()); + if (oldShape != obj->lastProperty()) { + // No point attaching anything, since we know the shape guard will fail + return true; + } + bool isDOMProxy; bool domProxyHasGeneration; DOMProxyShadowsResult domProxyShadowsResult; @@ -6593,6 +6606,11 @@ DoGetPropFallback(JSContext *cx, BaselineFrame *frame, ICGetProp_Fallback *stub_ MOZ_ASSERT(op == JSOP_GETPROP || op == JSOP_CALLPROP || op == JSOP_LENGTH || op == JSOP_GETXPROP); + // Grab our old shape before it goes away. + RootedShape oldShape(cx); + if (val.isObject()) + oldShape = val.toObject().lastProperty(); + // After the Genericstub was added, we should never reach the Fallbackstub again. MOZ_ASSERT(!stub->hasStub(ICStub::GetProp_Generic)); @@ -6638,7 +6656,8 @@ DoGetPropFallback(JSContext *cx, BaselineFrame *frame, ICGetProp_Fallback *stub_ RootedScript script(cx, frame->script()); - if (!TryAttachNativeGetPropStub(cx, script, pc, stub, name, val, res, &attached)) + if (!TryAttachNativeGetPropStub(cx, script, pc, stub, name, val, oldShape, + res, &attached)) return false; if (attached) return true; @@ -7616,6 +7635,8 @@ TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetPr GetFixedOrDynamicSlotOffset(&obj->as(), shape->slot(), &isFixedSlot, &offset); JitSpew(JitSpew_BaselineIC, " Generating SetProp(NativeObject.PROP) stub"); + MOZ_ASSERT(obj->lastProperty() == oldShape, + "Should this really be a SetPropWriteSlot?"); ICSetProp_Native::Compiler compiler(cx, obj, isFixedSlot, offset); ICSetProp_Native *newStub = compiler.getStub(compiler.getStubSpace(script)); if (!newStub) @@ -7634,7 +7655,7 @@ TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetPr } bool isScripted = false; - bool cacheableCall = IsCacheableSetPropCall(cx, obj, holder, shape, &isScripted); + bool cacheableCall = IsCacheableSetPropCall(cx, obj, holder, shape, oldShape, &isScripted); // Try handling scripted setters. if (cacheableCall && isScripted) {