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

Unified Diff: src/compiler/js-native-context-specialization.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
« no previous file with comments | « src/compiler/js-native-context-specialization.h ('k') | src/compiler/js-operator.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/js-native-context-specialization.cc
diff --git a/src/compiler/js-native-context-specialization.cc b/src/compiler/js-native-context-specialization.cc
index 04911a208286c1744ec56f95688a4ae763482ab6..e96f4c11dd371e4589dc4a7241a85a29b8d37f13 100644
--- a/src/compiler/js-native-context-specialization.cc
+++ b/src/compiler/js-native-context-specialization.cc
@@ -69,6 +69,8 @@ JSNativeContextSpecialization::JSNativeContextSpecialization(
Reduction JSNativeContextSpecialization::Reduce(Node* node) {
switch (node->opcode()) {
+ case IrOpcode::kJSInstanceOf:
+ return ReduceJSInstanceOf(node);
case IrOpcode::kJSLoadContext:
return ReduceJSLoadContext(node);
case IrOpcode::kJSLoadNamed:
@@ -85,6 +87,92 @@ Reduction JSNativeContextSpecialization::Reduce(Node* node) {
return NoChange();
}
+Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
+ DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode());
+ Node* object = NodeProperties::GetValueInput(node, 0);
+ Node* constructor = NodeProperties::GetValueInput(node, 1);
+ Node* context = NodeProperties::GetContextInput(node);
+ Node* effect = NodeProperties::GetEffectInput(node);
+ Node* control = NodeProperties::GetControlInput(node);
+
+ // If deoptimization is disabled, we cannot optimize.
+ if (!(flags() & kDeoptimizationEnabled)) return NoChange();
+
+ // Check if the right hand side is a known {receiver}.
+ HeapObjectMatcher m(constructor);
+ if (!m.HasValue() || !m.Value()->IsJSObject()) return NoChange();
+ Handle<JSObject> receiver = Handle<JSObject>::cast(m.Value());
+ Handle<Map> receiver_map(receiver->map(), isolate());
+
+ // Compute property access info for @@hasInstance on {receiver}.
+ PropertyAccessInfo access_info;
+ AccessInfoFactory access_info_factory(dependencies(), native_context(),
+ graph()->zone());
+ if (!access_info_factory.ComputePropertyAccessInfo(
+ receiver_map, factory()->has_instance_symbol(), AccessMode::kLoad,
+ &access_info)) {
+ return NoChange();
+ }
+
+ if (access_info.IsNotFound()) {
+ // If there's no @@hasInstance handler, the OrdinaryHasInstance operation
+ // takes over, but that requires the {receiver} to be callable.
+ if (receiver->IsCallable()) {
+ // Determine actual holder and perform prototype chain checks.
+ Handle<JSObject> holder;
+ if (access_info.holder().ToHandle(&holder)) {
+ AssumePrototypesStable(access_info.receiver_maps(), holder);
+ }
+
+ // Monomorphic property access.
+ effect =
+ BuildCheckMaps(constructor, effect, control, MapList{receiver_map});
+
+ // Lower to OrdinaryHasInstance(C, O).
+ NodeProperties::ReplaceValueInput(node, constructor, 0);
+ NodeProperties::ReplaceValueInput(node, object, 1);
+ NodeProperties::ReplaceEffectInput(node, effect);
+ NodeProperties::ChangeOp(node, javascript()->OrdinaryHasInstance());
Yang 2016/11/18 06:26:47 Would it make sense to constant fold if the lhs is
Benedikt Meurer 2016/11/18 06:28:51 Doable, but as discussed offline, there's no real
+ return Changed(node);
+ }
+ } else if (access_info.IsDataConstant()) {
+ DCHECK(access_info.constant()->IsCallable());
Yang 2016/11/18 06:26:47 Can we assume this? What if I store a non-callable
Benedikt Meurer 2016/11/18 06:28:51 Yes, all data constants stored on the map are curr
+
+ // Determine actual holder and perform prototype chain checks.
+ Handle<JSObject> holder;
+ if (access_info.holder().ToHandle(&holder)) {
+ AssumePrototypesStable(access_info.receiver_maps(), holder);
+ }
+
+ // Monomorphic property access.
+ effect =
+ BuildCheckMaps(constructor, effect, control, MapList{receiver_map});
+
+ // Call the @@hasInstance handler.
+ Node* target = jsgraph()->Constant(access_info.constant());
+ node->InsertInput(graph()->zone(), 0, target);
+ node->ReplaceInput(1, constructor);
+ node->ReplaceInput(2, object);
+ NodeProperties::ChangeOp(
+ node,
+ javascript()->CallFunction(3, 0.0f, VectorSlotPair(),
+ ConvertReceiverMode::kNotNullOrUndefined));
+
+ // Rewire the value uses of {node} to ToBoolean conversion of the result.
+ Node* value = graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
+ node, context);
+ for (Edge edge : node->use_edges()) {
+ if (NodeProperties::IsValueEdge(edge) && edge.from() != value) {
+ edge.UpdateTo(value);
+ Revisit(edge.from());
+ }
+ }
+ return Changed(node);
+ }
+
+ return NoChange();
+}
+
Reduction JSNativeContextSpecialization::ReduceJSLoadContext(Node* node) {
DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
ContextAccess const& access = ContextAccessOf(node->op());
« no previous file with comments | « src/compiler/js-native-context-specialization.h ('k') | src/compiler/js-operator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698