| Index: src/compiler/js-typed-lowering.cc
|
| diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc
|
| index 026b1a2eacc52a6239dda16a4881eba9e379b7b2..9939ae07326b40006b8a6ee65bcc0837be4cea33 100644
|
| --- a/src/compiler/js-typed-lowering.cc
|
| +++ b/src/compiler/js-typed-lowering.cc
|
| @@ -1276,6 +1276,10 @@ Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) {
|
| Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) {
|
| DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode());
|
| VectorSlotPair const& feedback = VectorSlotPairOf(node->op());
|
| + Node* right = NodeProperties::GetValueInput(node, 1);
|
| + Type* right_type = NodeProperties::GetType(right);
|
| + Node* effect = NodeProperties::GetEffectInput(node);
|
| + Node* control = NodeProperties::GetControlInput(node);
|
|
|
| // If deoptimization is disabled, we cannot optimize.
|
| if (!(flags() & kDeoptimizationEnabled)) return NoChange();
|
| @@ -1291,40 +1295,53 @@ Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) {
|
| return NoChange();
|
| }
|
|
|
| - JSBinopReduction r(this, node);
|
| - if (!r.right_type()->IsConstant() ||
|
| - !r.right_type()->AsConstant()->Value()->IsJSFunction()) {
|
| - return NoChange();
|
| - }
|
| + // We can only use the fast case if @@hasInstance was not used so far.
|
| + if (!isolate()->IsHasInstanceLookupChainIntact()) return NoChange();
|
|
|
| - Handle<JSFunction> function =
|
| - Handle<JSFunction>::cast(r.right_type()->AsConstant()->Value());
|
| - Handle<SharedFunctionInfo> shared(function->shared(), isolate());
|
| + if (right_type->IsConstant() &&
|
| + right_type->AsConstant()->Value()->IsJSFunction()) {
|
| + Handle<JSFunction> function =
|
| + Handle<JSFunction>::cast(right_type->AsConstant()->Value());
|
| + Handle<SharedFunctionInfo> shared(function->shared(), isolate());
|
|
|
| - // Make sure the prototype of {function} is the %FunctionPrototype%, and it
|
| - // already has a meaningful initial map (i.e. we constructed at least one
|
| - // instance using the constructor {function}).
|
| - if (function->map()->prototype() != function->native_context()->closure() ||
|
| - function->map()->has_non_instance_prototype() ||
|
| - !function->has_initial_map()) {
|
| - return NoChange();
|
| + // Make sure the prototype of {function} is the %FunctionPrototype%, and it
|
| + // already has a meaningful initial map (i.e. we constructed at least one
|
| + // instance using the constructor {function}).
|
| + if (function->map()->prototype() != function->native_context()->closure() ||
|
| + function->map()->has_non_instance_prototype() ||
|
| + !function->has_initial_map()) {
|
| + return NoChange();
|
| + }
|
| +
|
| + Handle<Map> initial_map(function->initial_map(), isolate());
|
| + dependencies()->AssumeInitialMapCantChange(initial_map);
|
| + Handle<Object> prototype(initial_map->prototype(), isolate());
|
| + right = jsgraph()->Constant(prototype);
|
| + } else {
|
| + // The {right} hand side must be a HeapObject.
|
| + effect = graph()->NewNode(simplified()->CheckHeapObject(), right, effect,
|
| + control);
|
| +
|
| + // TODO(bmeurer): Properly check the right-hand side with above conditions.
|
| + right = effect = graph()->NewNode(
|
| + simplified()->LoadField(
|
| + AccessBuilder::ForJSFunctionPrototypeOrInitialMap()),
|
| + right, effect, control);
|
| + right = effect = graph()->NewNode(
|
| + simplified()->LoadField(AccessBuilder::ForMapPrototype()),
|
| + right, effect, control);
|
| }
|
|
|
| - // We can only use the fast case if @@hasInstance was not used so far.
|
| - if (!isolate()->IsHasInstanceLookupChainIntact()) return NoChange();
|
| + // Add the code dependency to protect against @@hasInstance.
|
| dependencies()->AssumePropertyCell(factory()->has_instance_protector());
|
|
|
| - Handle<Map> initial_map(function->initial_map(), isolate());
|
| - dependencies()->AssumeInitialMapCantChange(initial_map);
|
| - Node* prototype =
|
| - jsgraph()->Constant(handle(initial_map->prototype(), isolate()));
|
| -
|
| - // Morph the {node} into an optimistic prototype chain walk (which just
|
| + // Morph the {node} into an optimistic prototype chain walk (which just
|
| // deopts if it sees anything funny in the prototype chain, i.e. a proxy).
|
| RelaxControls(node);
|
| - node->ReplaceInput(1, prototype); // prototype
|
| - node->RemoveInput(3); // frame state
|
| - node->RemoveInput(2); // context
|
| + NodeProperties::ReplaceValueInput(node, right, 1); // prototype
|
| + NodeProperties::ReplaceEffectInput(node, effect); // effect
|
| + node->RemoveInput(3); // frame state
|
| + node->RemoveInput(2); // context
|
| NodeProperties::ChangeOp(node, simplified()->CheckHasInPrototypeChain());
|
| return Changed(node);
|
| }
|
|
|