[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}
This commit is contained in:
bmeurer 2017-01-25 00:48:49 -08:00 committed by Commit bot
parent 4ec372801e
commit d0a24e913f
2 changed files with 38 additions and 0 deletions

View File

@ -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<JSFunction> function = Handle<JSFunction>::cast(m.Value());
Handle<Map> function_map(function->map(), isolate());
Handle<Object> 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);

View File

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