Commit 4ea5e0bb authored by Mihai Alexandru Michis's avatar Mihai Alexandru Michis
Browse files

Backed out changeset 4b4511cf734e (bug 1492920) for landing on both autoland and inbound.

parent fe856b5d
Loading
Loading
Loading
Loading
+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);
}
+8 −30
Original line number Diff line number Diff line
@@ -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;
  }
@@ -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.
+0 −8
Original line number Diff line number Diff line
@@ -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;
}

+0 −3
Original line number Diff line number Diff line
@@ -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);