From d0a24e913f6653531786bc237793fdb0e7ebfa53 Mon Sep 17 00:00:00 2001 From: bmeurer Date: Wed, 25 Jan 2017 00:48:49 -0800 Subject: [PATCH] [turbofan] Constant-fold JSGetSuperConstructor. This adds support to constant-fold JSGetSuperConstructor(constructor) for constructors with stable maps, i.e. where we can add a stability dependency on the constructors map to get notified when the [[Prototype]] of constructor changes. R=petermarshall@chromium.org BUG=v8:5517 Review-Url: https://codereview.chromium.org/2652763010 Cr-Commit-Position: refs/heads/master@{#42647} --- .../js-native-context-specialization.cc | 37 +++++++++++++++++++ .../js-native-context-specialization.h | 1 + 2 files changed, 38 insertions(+) diff --git a/src/compiler/js-native-context-specialization.cc b/src/compiler/js-native-context-specialization.cc index b2e2ab8a55..b84896bba8 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::kJSGetSuperConstructor: + return ReduceJSGetSuperConstructor(node); case IrOpcode::kJSInstanceOf: return ReduceJSInstanceOf(node); case IrOpcode::kJSOrdinaryHasInstance: @@ -91,6 +93,41 @@ Reduction JSNativeContextSpecialization::Reduce(Node* node) { return NoChange(); } +Reduction JSNativeContextSpecialization::ReduceJSGetSuperConstructor( + Node* node) { + DCHECK_EQ(IrOpcode::kJSGetSuperConstructor, node->opcode()); + Node* constructor = NodeProperties::GetValueInput(node, 0); + + // If deoptimization is disabled, we cannot optimize. + if (!(flags() & kDeoptimizationEnabled)) return NoChange(); + + // Check if the input is a known JSFunction. + HeapObjectMatcher m(constructor); + if (!m.HasValue()) return NoChange(); + Handle function = Handle::cast(m.Value()); + Handle function_map(function->map(), isolate()); + Handle function_prototype(function_map->prototype(), isolate()); + + // We can constant-fold the super constructor access if the + // {function}s map is stable, i.e. we can use a code dependency + // to guard against [[Prototype]] changes of {function}. + if (function_map->is_stable()) { + Node* value = jsgraph()->Constant(function_prototype); + dependencies()->AssumeMapStable(function_map); + if (function_prototype->IsConstructor()) { + ReplaceWithValue(node, value); + return Replace(value); + } else { + node->InsertInput(graph()->zone(), 0, value); + NodeProperties::ChangeOp( + node, javascript()->CallRuntime(Runtime::kThrowNotSuperConstructor)); + return Changed(node); + } + } + + return NoChange(); +} + Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) { DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode()); Node* object = NodeProperties::GetValueInput(node, 0); diff --git a/src/compiler/js-native-context-specialization.h b/src/compiler/js-native-context-specialization.h index 7fedf32e92..436949596c 100644 --- a/src/compiler/js-native-context-specialization.h +++ b/src/compiler/js-native-context-specialization.h @@ -53,6 +53,7 @@ class JSNativeContextSpecialization final : public AdvancedReducer { Reduction Reduce(Node* node) final; private: + Reduction ReduceJSGetSuperConstructor(Node* node); Reduction ReduceJSInstanceOf(Node* node); Reduction ReduceJSOrdinaryHasInstance(Node* node); Reduction ReduceJSLoadContext(Node* node);