| Index: src/compiler/js-typed-lowering.cc
|
| diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc
|
| index 95ed453ce0f2295db0e25e2eefb7d7373fa1b387..dbbeca6e960d857a7f56973acb46c2b518a131fc 100644
|
| --- a/src/compiler/js-typed-lowering.cc
|
| +++ b/src/compiler/js-typed-lowering.cc
|
| @@ -1311,47 +1311,35 @@ Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) {
|
| return NoChange();
|
| }
|
|
|
| -Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) {
|
| - DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode());
|
| - Node* const context = NodeProperties::GetContextInput(node);
|
| - Node* const frame_state = NodeProperties::GetFrameStateInput(node);
|
| -
|
| - // If deoptimization is disabled, we cannot optimize.
|
| - if (!(flags() & kDeoptimizationEnabled)) return NoChange();
|
| -
|
| - // If we are in a try block, don't optimize since the runtime call
|
| - // in the proxy case can throw.
|
| - if (NodeProperties::IsExceptionalCall(node)) return NoChange();
|
| -
|
| - JSBinopReduction r(this, node);
|
| - Node* object = r.left();
|
| - Node* effect = r.effect();
|
| - Node* control = r.control();
|
| +Reduction JSTypedLowering::ReduceJSOrdinaryHasInstance(Node* node) {
|
| + DCHECK_EQ(IrOpcode::kJSOrdinaryHasInstance, node->opcode());
|
| + Node* constructor = NodeProperties::GetValueInput(node, 0);
|
| + Type* constructor_type = NodeProperties::GetType(constructor);
|
| + Node* object = NodeProperties::GetValueInput(node, 1);
|
| + Node* context = NodeProperties::GetContextInput(node);
|
| + Node* frame_state = NodeProperties::GetFrameStateInput(node);
|
| + Node* effect = NodeProperties::GetEffectInput(node);
|
| + Node* control = NodeProperties::GetControlInput(node);
|
|
|
| - if (!r.right_type()->IsHeapConstant() ||
|
| - !r.right_type()->AsHeapConstant()->Value()->IsJSFunction()) {
|
| + // Check if the {constructor} is a (known) JSFunction.
|
| + if (!constructor_type->IsHeapConstant() ||
|
| + !constructor_type->AsHeapConstant()->Value()->IsJSFunction()) {
|
| return NoChange();
|
| }
|
| -
|
| Handle<JSFunction> function =
|
| - Handle<JSFunction>::cast(r.right_type()->AsHeapConstant()->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();
|
| - }
|
| + Handle<JSFunction>::cast(constructor_type->AsHeapConstant()->Value());
|
| +
|
| + // Check if the {function} already has an initial map (i.e. the
|
| + // {function} has been used as a constructor at least once).
|
| + if (!function->has_initial_map()) return NoChange();
|
|
|
| - // We can only use the fast case if @@hasInstance was not used so far.
|
| - if (!isolate()->IsHasInstanceLookupChainIntact()) return NoChange();
|
| - dependencies()->AssumePropertyCell(factory()->has_instance_protector());
|
| + // Check if the {function}s "prototype" is a JSReceiver.
|
| + if (!function->prototype()->IsJSReceiver()) return NoChange();
|
|
|
| + // Install a code dependency on the {function}s initial map.
|
| Handle<Map> initial_map(function->initial_map(), isolate());
|
| dependencies()->AssumeInitialMapCantChange(initial_map);
|
| +
|
| Node* prototype =
|
| jsgraph()->Constant(handle(initial_map->prototype(), isolate()));
|
|
|
| @@ -1419,6 +1407,15 @@ Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) {
|
| javascript()->CallRuntime(Runtime::kHasInPrototypeChain), object,
|
| prototype, context, frame_state, efalse1, if_false1);
|
| if_false1 = graph()->NewNode(common()->IfSuccess(), vfalse1);
|
| +
|
| + // Replace any potential IfException on {node} to catch exceptions
|
| + // from this %HasInPrototypeChain runtime call instead.
|
| + for (Edge edge : node->use_edges()) {
|
| + if (edge.from()->opcode() == IrOpcode::kIfException) {
|
| + edge.UpdateTo(vfalse1);
|
| + Revisit(edge.from());
|
| + }
|
| + }
|
| }
|
|
|
| // Load the {object} prototype.
|
| @@ -2198,6 +2195,8 @@ Reduction JSTypedLowering::Reduce(Node* node) {
|
| case IrOpcode::kJSDivide:
|
| case IrOpcode::kJSModulus:
|
| return ReduceNumberBinop(node);
|
| + case IrOpcode::kJSOrdinaryHasInstance:
|
| + return ReduceJSOrdinaryHasInstance(node);
|
| case IrOpcode::kJSToBoolean:
|
| return ReduceJSToBoolean(node);
|
| case IrOpcode::kJSToInteger:
|
| @@ -2220,8 +2219,6 @@ Reduction JSTypedLowering::Reduce(Node* node) {
|
| return ReduceJSLoadProperty(node);
|
| case IrOpcode::kJSStoreProperty:
|
| return ReduceJSStoreProperty(node);
|
| - case IrOpcode::kJSInstanceOf:
|
| - return ReduceJSInstanceOf(node);
|
| case IrOpcode::kJSLoadContext:
|
| return ReduceJSLoadContext(node);
|
| case IrOpcode::kJSStoreContext:
|
|
|