Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1226)

Unified Diff: src/compiler/js-typed-lowering.cc

Issue 2511223003: [turbofan] Properly optimize instanceof (even in the presence of @@hasInstance). (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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:

Powered by Google App Engine
This is Rietveld 408576698