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); |
} |