[turbofan] Be consistent about prototype optimization condition.
Change-Id: Ib967337b140594e70307348e6989b1324a62d71e Reviewed-on: https://chromium-review.googlesource.com/1186641 Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Commit-Queue: Georg Neis <neis@chromium.org> Cr-Commit-Position: refs/heads/master@{#55443}
This commit is contained in:
parent
91f3555fce
commit
609ec4b760
@ -405,28 +405,24 @@ Reduction JSNativeContextSpecialization::ReduceJSOrdinaryHasInstance(
|
||||
return reduction.Changed() ? reduction : Changed(node);
|
||||
}
|
||||
|
||||
// Check if the {constructor} is a JSFunction.
|
||||
// Optimize if we currently know the "prototype" property.
|
||||
if (m.Value()->IsJSFunction()) {
|
||||
// Check if the {function} is a constructor and has an instance "prototype".
|
||||
Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value());
|
||||
if (function->IsConstructor() && function->has_prototype_slot() &&
|
||||
function->has_instance_prototype() &&
|
||||
function->prototype()->IsJSReceiver()) {
|
||||
// We need {function}'s initial map so that we can depend on it for the
|
||||
// prototype constant-folding below.
|
||||
if (!function->has_initial_map()) return NoChange();
|
||||
MapRef initial_map = dependencies()->DependOnInitialMap(
|
||||
JSFunctionRef(js_heap_broker(), function));
|
||||
Node* prototype = jsgraph()->Constant(
|
||||
handle(initial_map.object<Map>()->prototype(), isolate()));
|
||||
|
||||
// Lower the {node} to JSHasInPrototypeChain.
|
||||
NodeProperties::ReplaceValueInput(node, object, 0);
|
||||
NodeProperties::ReplaceValueInput(node, prototype, 1);
|
||||
NodeProperties::ChangeOp(node, javascript()->HasInPrototypeChain());
|
||||
Reduction const reduction = ReduceJSHasInPrototypeChain(node);
|
||||
return reduction.Changed() ? reduction : Changed(node);
|
||||
JSFunctionRef function = m.Ref(js_heap_broker()).AsJSFunction();
|
||||
// TODO(neis): Remove the has_prototype_slot condition once the broker is
|
||||
// always enabled.
|
||||
if (!function.map().has_prototype_slot() || !function.has_prototype() ||
|
||||
function.PrototypeRequiresRuntimeLookup()) {
|
||||
return NoChange();
|
||||
}
|
||||
ObjectRef prototype = dependencies()->DependOnPrototypeProperty(function);
|
||||
Node* prototype_constant = jsgraph()->Constant(prototype);
|
||||
|
||||
// Lower the {node} to JSHasInPrototypeChain.
|
||||
NodeProperties::ReplaceValueInput(node, object, 0);
|
||||
NodeProperties::ReplaceValueInput(node, prototype_constant, 1);
|
||||
NodeProperties::ChangeOp(node, javascript()->HasInPrototypeChain());
|
||||
Reduction const reduction = ReduceJSHasInPrototypeChain(node);
|
||||
return reduction.Changed() ? reduction : Changed(node);
|
||||
}
|
||||
|
||||
return NoChange();
|
||||
|
233
test/mjsunit/compiler/instanceof2.js
Normal file
233
test/mjsunit/compiler/instanceof2.js
Normal file
@ -0,0 +1,233 @@
|
||||
// Copyright 2018 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
|
||||
|
||||
// Without instance creation:
|
||||
|
||||
(function() {
|
||||
function Goo() {};
|
||||
const goo = {};
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertFalse(IsGoo(goo));
|
||||
assertFalse(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertFalse(IsGoo(goo));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function Goo() {};
|
||||
const goo = {};
|
||||
Goo.prototype = Object.prototype;
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertTrue(IsGoo(goo));
|
||||
assertTrue(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertTrue(IsGoo(goo));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function Goo() {};
|
||||
const goo = {};
|
||||
Goo.prototype = 42
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function Goo() {};
|
||||
const goo = {};
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertFalse(IsGoo(goo));
|
||||
assertFalse(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertFalse(IsGoo(goo));
|
||||
Goo.prototype = Object.prototype;
|
||||
assertTrue(IsGoo(goo));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function Goo() {};
|
||||
const goo = {};
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertFalse(IsGoo(goo));
|
||||
assertFalse(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertFalse(IsGoo(goo));
|
||||
Goo.prototype = 42;
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
})();
|
||||
|
||||
|
||||
// With instance creation:
|
||||
|
||||
(function() {
|
||||
function Goo() {};
|
||||
const goo = new Goo();
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertTrue(IsGoo(goo));
|
||||
assertTrue(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertTrue(IsGoo(goo));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function Goo() {};
|
||||
const goo = new Goo();
|
||||
Goo.prototype = {};
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertFalse(IsGoo(goo));
|
||||
assertFalse(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertFalse(IsGoo(goo));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function Goo() {};
|
||||
const goo = new Goo();
|
||||
Goo.prototype = 42;
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function Goo() {};
|
||||
const goo = new Goo();
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertTrue(IsGoo(goo));
|
||||
assertTrue(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertTrue(IsGoo(goo));
|
||||
Goo.prototype = {};
|
||||
assertFalse(IsGoo(goo));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function Goo() {};
|
||||
const goo = new Goo();
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertTrue(IsGoo(goo));
|
||||
assertTrue(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertTrue(IsGoo(goo));
|
||||
Goo.prototype = 42
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function Goo() {};
|
||||
Goo.prototype = 42;
|
||||
const goo = new Goo();
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
Goo.prototype = {};
|
||||
assertFalse(IsGoo(goo));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function Goo() {};
|
||||
Goo.prototype = 42;
|
||||
const goo = new Goo();
|
||||
Goo.prototype = {};
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertFalse(IsGoo(goo));
|
||||
assertFalse(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertFalse(IsGoo(goo));
|
||||
Goo.prototype = Object.prototype;
|
||||
assertTrue(IsGoo(goo));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function Goo() {};
|
||||
Goo.prototype = {};
|
||||
const goo = new Goo();
|
||||
Goo.prototype = 42;
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
Goo.prototype = Object.prototype;
|
||||
assertTrue(IsGoo(goo));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function Goo() {};
|
||||
Goo.prototype = {};
|
||||
const goo = new Goo();
|
||||
Goo.prototype = {};
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertFalse(IsGoo(goo));
|
||||
assertFalse(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
Goo.prototype = Object.prototype;
|
||||
assertTrue(IsGoo(goo));
|
||||
})();
|
233
test/mjsunit/compiler/instanceof3.js
Normal file
233
test/mjsunit/compiler/instanceof3.js
Normal file
@ -0,0 +1,233 @@
|
||||
// Copyright 2018 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
|
||||
|
||||
// Without instance creation:
|
||||
|
||||
(function() {
|
||||
function* Goo() {};
|
||||
const goo = {};
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertFalse(IsGoo(goo));
|
||||
assertFalse(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertFalse(IsGoo(goo));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function* Goo() {};
|
||||
const goo = {};
|
||||
Goo.prototype = Object.prototype;
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertTrue(IsGoo(goo));
|
||||
assertTrue(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertTrue(IsGoo(goo));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function* Goo() {};
|
||||
const goo = {};
|
||||
Goo.prototype = 42
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function* Goo() {};
|
||||
const goo = {};
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertFalse(IsGoo(goo));
|
||||
assertFalse(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertFalse(IsGoo(goo));
|
||||
Goo.prototype = Object.prototype;
|
||||
assertTrue(IsGoo(goo));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function* Goo() {};
|
||||
const goo = {};
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertFalse(IsGoo(goo));
|
||||
assertFalse(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertFalse(IsGoo(goo));
|
||||
Goo.prototype = 42;
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
})();
|
||||
|
||||
|
||||
// With instance creation:
|
||||
|
||||
(function() {
|
||||
function* Goo() {};
|
||||
const goo = Goo();
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertTrue(IsGoo(goo));
|
||||
assertTrue(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertTrue(IsGoo(goo));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function* Goo() {};
|
||||
const goo = Goo();
|
||||
Goo.prototype = {};
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertFalse(IsGoo(goo));
|
||||
assertFalse(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertFalse(IsGoo(goo));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function* Goo() {};
|
||||
const goo = Goo();
|
||||
Goo.prototype = 42;
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function* Goo() {};
|
||||
const goo = Goo();
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertTrue(IsGoo(goo));
|
||||
assertTrue(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertTrue(IsGoo(goo));
|
||||
Goo.prototype = {};
|
||||
assertFalse(IsGoo(goo));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function* Goo() {};
|
||||
const goo = Goo();
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertTrue(IsGoo(goo));
|
||||
assertTrue(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertTrue(IsGoo(goo));
|
||||
Goo.prototype = 42
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function* Goo() {};
|
||||
Goo.prototype = 42;
|
||||
const goo = Goo();
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
Goo.prototype = {};
|
||||
assertFalse(IsGoo(goo));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function* Goo() {};
|
||||
Goo.prototype = 42;
|
||||
const goo = Goo();
|
||||
Goo.prototype = {};
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertFalse(IsGoo(goo));
|
||||
assertFalse(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertFalse(IsGoo(goo));
|
||||
Goo.prototype = Object.prototype;
|
||||
assertTrue(IsGoo(goo));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function* Goo() {};
|
||||
Goo.prototype = {};
|
||||
const goo = Goo();
|
||||
Goo.prototype = 42;
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
assertThrows(_ => IsGoo(goo), TypeError);
|
||||
Goo.prototype = Object.prototype;
|
||||
assertTrue(IsGoo(goo));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function* Goo() {};
|
||||
Goo.prototype = {};
|
||||
const goo = Goo();
|
||||
Goo.prototype = {};
|
||||
|
||||
function IsGoo(x) {
|
||||
return x instanceof Goo;
|
||||
}
|
||||
|
||||
assertFalse(IsGoo(goo));
|
||||
assertFalse(IsGoo(goo));
|
||||
%OptimizeFunctionOnNextCall(IsGoo);
|
||||
Goo.prototype = Object.prototype;
|
||||
assertTrue(IsGoo(goo));
|
||||
})();
|
Loading…
Reference in New Issue
Block a user