Loading js/src/jit-test/tests/basic/bug1492920.jsdeleted 100644 → 0 +0 −41 Original line number Diff line number Diff line var N = 20; var k = 15; // k < N /* test 1: insertion of new blank object in ctor.__proto__ chain */ function C() {} C.__proto__ = Object.create(Function.prototype); for (var i = 0; i < N; i++) { var o = new C(); assertEq(o instanceof C, true); } /* test 2: overriding of @@hasInstance on the proto chain, partway * through execution (should trigger a guard) */ function D() {} for (var i = 0; i < N; i++) { var o = new D(); if (i == k) { D.__proto__ = {[Symbol.hasInstance]() { return false; }}; } assertEq(o instanceof D, i < k); } /* test 3: overriding of @@hasInstance on an intermediate object in the proto * chain */ function E() {} E.__proto__ = Object.create(Object.create(Object.create(Function.prototype))); var intermediateProto = E.__proto__.__proto__; for (var i = 0; i < N; i++) { var o = new E; if (i == k) { intermediateProto.__proto__ = {[Symbol.hasInstance]() { return false; }}; } assertEq(o instanceof E, i < k); } js/src/jit/CacheIR.cpp +8 −30 Original line number Diff line number Diff line Loading @@ -4416,35 +4416,22 @@ AttachDecision InstanceOfIRGenerator::tryAttachStub() { return AttachDecision::NoAction; } // Look up the @@hasInstance property, and check that Function.__proto__ is // the property holder, and that no object further down the prototype chain // (including this function) has shadowed it; together with the fact that // Function.__proto__[@@hasInstance] is immutable, this ensures that the // hasInstance hook will not change without the need to guard on the actual // property value. PropertyResult hasInstanceProp; JSObject* hasInstanceHolder = nullptr; jsid hasInstanceID = SYMBOL_TO_JSID(cx_->wellKnownSymbols().hasInstance); if (!LookupPropertyPure(cx_, fun, hasInstanceID, &hasInstanceHolder, &hasInstanceProp) || !hasInstanceProp.isFound() || hasInstanceProp.isNonNativeProperty()) { // If the user has supplied their own @@hasInstance method we shouldn't // clobber it. if (!js::FunctionHasDefaultHasInstance(fun, cx_->wellKnownSymbols())) { trackAttached(IRGenerator::NotAttached); return AttachDecision::NoAction; } Value funProto = cx_->global()->getPrototype(JSProto_Function); if (hasInstanceHolder != &funProto.toObject()) { // Refuse to optimize any function whose [[Prototype]] isn't // Function.prototype. if (!fun->hasStaticPrototype() || fun->hasUncacheableProto()) { trackAttached(IRGenerator::NotAttached); return AttachDecision::NoAction; } // If the above succeeded, then these should be true about @@hasInstance, // because the property on Function.__proto__ is an immutable data property: MOZ_ASSERT(hasInstanceProp.shape()->isDataProperty()); MOZ_ASSERT(!hasInstanceProp.shape()->configurable()); MOZ_ASSERT(!hasInstanceProp.shape()->writable()); if (!IsCacheableProtoChain(fun, hasInstanceHolder)) { Value funProto = cx_->global()->getPrototype(JSProto_Function); if (!funProto.isObject() || fun->staticPrototype() != &funProto.toObject()) { trackAttached(IRGenerator::NotAttached); return AttachDecision::NoAction; } Loading Loading @@ -4473,15 +4460,6 @@ AttachDecision InstanceOfIRGenerator::tryAttachStub() { ObjOperandId rhsId = writer.guardToObject(rhs); writer.guardShape(rhsId, fun->lastProperty()); // Ensure that the shapes up the prototype chain for the RHS remain the same // so that @@hasInstance is not shadowed by some intermediate prototype // object. if (hasInstanceHolder != fun) { GeneratePrototypeGuards(writer, fun, hasInstanceHolder, rhsId); ObjOperandId holderId = writer.loadObject(hasInstanceHolder); TestMatchingHolder(writer, hasInstanceHolder, holderId); } // Load prototypeObject into the cache -- consumed twice in the IC ObjOperandId protoId = writer.loadObject(prototypeObject); // Ensure that rhs[slot] == prototypeObject. Loading js/src/vm/JSFunction.cpp +0 −8 Original line number Diff line number Diff line Loading @@ -1026,14 +1026,6 @@ bool js::FunctionHasDefaultHasInstance(JSFunction* fun, const Value hasInstance = fun->as<NativeObject>().getSlot(shape->slot()); return IsNativeFunction(hasInstance, fun_symbolHasInstance); } #ifdef DEBUG // The proto must be Function.__proto__. It has an immutable @@hasInstance // property. (Callers should check this first.) Value funProto = fun->global().getPrototype(JSProto_Function); MOZ_ASSERT(fun->staticPrototype() == &funProto.toObject()); #endif return true; } Loading js/src/vm/JSFunction.h +0 −3 Original line number Diff line number Diff line Loading @@ -1097,9 +1097,6 @@ extern bool fun_toString(JSContext* cx, unsigned argc, Value* vp); struct WellKnownSymbols; // Assumes that fun.__proto__ === Function.__proto__, i.e., does not check for // the case where a function with a non-default __proto__ has an overridden // @@hasInstance handler. Will assert if not. extern bool FunctionHasDefaultHasInstance(JSFunction* fun, const WellKnownSymbols& symbols); Loading Loading
js/src/jit-test/tests/basic/bug1492920.jsdeleted 100644 → 0 +0 −41 Original line number Diff line number Diff line var N = 20; var k = 15; // k < N /* test 1: insertion of new blank object in ctor.__proto__ chain */ function C() {} C.__proto__ = Object.create(Function.prototype); for (var i = 0; i < N; i++) { var o = new C(); assertEq(o instanceof C, true); } /* test 2: overriding of @@hasInstance on the proto chain, partway * through execution (should trigger a guard) */ function D() {} for (var i = 0; i < N; i++) { var o = new D(); if (i == k) { D.__proto__ = {[Symbol.hasInstance]() { return false; }}; } assertEq(o instanceof D, i < k); } /* test 3: overriding of @@hasInstance on an intermediate object in the proto * chain */ function E() {} E.__proto__ = Object.create(Object.create(Object.create(Function.prototype))); var intermediateProto = E.__proto__.__proto__; for (var i = 0; i < N; i++) { var o = new E; if (i == k) { intermediateProto.__proto__ = {[Symbol.hasInstance]() { return false; }}; } assertEq(o instanceof E, i < k); }
js/src/jit/CacheIR.cpp +8 −30 Original line number Diff line number Diff line Loading @@ -4416,35 +4416,22 @@ AttachDecision InstanceOfIRGenerator::tryAttachStub() { return AttachDecision::NoAction; } // Look up the @@hasInstance property, and check that Function.__proto__ is // the property holder, and that no object further down the prototype chain // (including this function) has shadowed it; together with the fact that // Function.__proto__[@@hasInstance] is immutable, this ensures that the // hasInstance hook will not change without the need to guard on the actual // property value. PropertyResult hasInstanceProp; JSObject* hasInstanceHolder = nullptr; jsid hasInstanceID = SYMBOL_TO_JSID(cx_->wellKnownSymbols().hasInstance); if (!LookupPropertyPure(cx_, fun, hasInstanceID, &hasInstanceHolder, &hasInstanceProp) || !hasInstanceProp.isFound() || hasInstanceProp.isNonNativeProperty()) { // If the user has supplied their own @@hasInstance method we shouldn't // clobber it. if (!js::FunctionHasDefaultHasInstance(fun, cx_->wellKnownSymbols())) { trackAttached(IRGenerator::NotAttached); return AttachDecision::NoAction; } Value funProto = cx_->global()->getPrototype(JSProto_Function); if (hasInstanceHolder != &funProto.toObject()) { // Refuse to optimize any function whose [[Prototype]] isn't // Function.prototype. if (!fun->hasStaticPrototype() || fun->hasUncacheableProto()) { trackAttached(IRGenerator::NotAttached); return AttachDecision::NoAction; } // If the above succeeded, then these should be true about @@hasInstance, // because the property on Function.__proto__ is an immutable data property: MOZ_ASSERT(hasInstanceProp.shape()->isDataProperty()); MOZ_ASSERT(!hasInstanceProp.shape()->configurable()); MOZ_ASSERT(!hasInstanceProp.shape()->writable()); if (!IsCacheableProtoChain(fun, hasInstanceHolder)) { Value funProto = cx_->global()->getPrototype(JSProto_Function); if (!funProto.isObject() || fun->staticPrototype() != &funProto.toObject()) { trackAttached(IRGenerator::NotAttached); return AttachDecision::NoAction; } Loading Loading @@ -4473,15 +4460,6 @@ AttachDecision InstanceOfIRGenerator::tryAttachStub() { ObjOperandId rhsId = writer.guardToObject(rhs); writer.guardShape(rhsId, fun->lastProperty()); // Ensure that the shapes up the prototype chain for the RHS remain the same // so that @@hasInstance is not shadowed by some intermediate prototype // object. if (hasInstanceHolder != fun) { GeneratePrototypeGuards(writer, fun, hasInstanceHolder, rhsId); ObjOperandId holderId = writer.loadObject(hasInstanceHolder); TestMatchingHolder(writer, hasInstanceHolder, holderId); } // Load prototypeObject into the cache -- consumed twice in the IC ObjOperandId protoId = writer.loadObject(prototypeObject); // Ensure that rhs[slot] == prototypeObject. Loading
js/src/vm/JSFunction.cpp +0 −8 Original line number Diff line number Diff line Loading @@ -1026,14 +1026,6 @@ bool js::FunctionHasDefaultHasInstance(JSFunction* fun, const Value hasInstance = fun->as<NativeObject>().getSlot(shape->slot()); return IsNativeFunction(hasInstance, fun_symbolHasInstance); } #ifdef DEBUG // The proto must be Function.__proto__. It has an immutable @@hasInstance // property. (Callers should check this first.) Value funProto = fun->global().getPrototype(JSProto_Function); MOZ_ASSERT(fun->staticPrototype() == &funProto.toObject()); #endif return true; } Loading
js/src/vm/JSFunction.h +0 −3 Original line number Diff line number Diff line Loading @@ -1097,9 +1097,6 @@ extern bool fun_toString(JSContext* cx, unsigned argc, Value* vp); struct WellKnownSymbols; // Assumes that fun.__proto__ === Function.__proto__, i.e., does not check for // the case where a function with a non-default __proto__ has an overridden // @@hasInstance handler. Will assert if not. extern bool FunctionHasDefaultHasInstance(JSFunction* fun, const WellKnownSymbols& symbols); Loading