Commit 443b071a authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Context specialization should only specialize loads/stores.

The JSContextSpecialization should only care about loads from the
context and stores to the context, where the context is either a
HeapConstant or the special context Parameter (and a context for the
outer most function is provided). This way we don't eagerly embed
arbitrary context constants for no benefit, but we still specialize the
loads and store which we actually care about.

R=mstarzinger@chromium.org

Review URL: https://codereview.chromium.org/1227963005

Cr-Commit-Position: refs/heads/master@{#29602}
parent 080d8f65
...@@ -17,8 +17,6 @@ namespace compiler { ...@@ -17,8 +17,6 @@ namespace compiler {
Reduction JSContextSpecialization::Reduce(Node* node) { Reduction JSContextSpecialization::Reduce(Node* node) {
switch (node->opcode()) { switch (node->opcode()) {
case IrOpcode::kParameter:
return ReduceParameter(node);
case IrOpcode::kJSLoadContext: case IrOpcode::kJSLoadContext:
return ReduceJSLoadContext(node); return ReduceJSLoadContext(node);
case IrOpcode::kJSStoreContext: case IrOpcode::kJSStoreContext:
...@@ -30,37 +28,43 @@ Reduction JSContextSpecialization::Reduce(Node* node) { ...@@ -30,37 +28,43 @@ Reduction JSContextSpecialization::Reduce(Node* node) {
} }
Reduction JSContextSpecialization::ReduceParameter(Node* node) { MaybeHandle<Context> JSContextSpecialization::GetSpecializationContext(
DCHECK_EQ(IrOpcode::kParameter, node->opcode()); Node* node) {
Node* const start = NodeProperties::GetValueInput(node, 0); DCHECK(node->opcode() == IrOpcode::kJSLoadContext ||
DCHECK_EQ(IrOpcode::kStart, start->opcode()); node->opcode() == IrOpcode::kJSStoreContext);
int const index = ParameterIndexOf(node->op()); Node* const object = NodeProperties::GetValueInput(node, 0);
// The context is always the last parameter to a JavaScript function, and switch (object->opcode()) {
// {Parameter} indices start at -1, so value outputs of {Start} look like case IrOpcode::kHeapConstant:
// this: closure, receiver, param0, ..., paramN, context. return Handle<Context>::cast(
if (index == start->op()->ValueOutputCount() - 2) { OpParameter<Unique<HeapObject>>(object).handle());
Handle<Context> context_constant; case IrOpcode::kParameter: {
if (context().ToHandle(&context_constant)) { Node* const start = NodeProperties::GetValueInput(object, 0);
return Replace(jsgraph()->Constant(context_constant)); DCHECK_EQ(IrOpcode::kStart, start->opcode());
int const index = ParameterIndexOf(object->op());
// The context is always the last parameter to a JavaScript function, and
// {Parameter} indices start at -1, so value outputs of {Start} look like
// this: closure, receiver, param0, ..., paramN, context.
if (index == start->op()->ValueOutputCount() - 2) {
return context();
}
break;
} }
default:
break;
} }
return NoChange(); return MaybeHandle<Context>();
} }
Reduction JSContextSpecialization::ReduceJSLoadContext(Node* node) { Reduction JSContextSpecialization::ReduceJSLoadContext(Node* node) {
DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
HeapObjectMatcher m(NodeProperties::GetValueInput(node, 0)); // Get the specialization context from the node.
// If the context is not constant, no reduction can occur. Handle<Context> context;
if (!m.HasValue()) { if (!GetSpecializationContext(node).ToHandle(&context)) return NoChange();
return NoChange();
}
const ContextAccess& access = ContextAccessOf(node->op());
// Find the right parent context. // Find the right parent context.
Handle<Context> context = Handle<Context>::cast(m.Value().handle()); const ContextAccess& access = ContextAccessOf(node->op());
for (size_t i = access.depth(); i > 0; --i) { for (size_t i = access.depth(); i > 0; --i) {
context = handle(context->previous(), isolate()); context = handle(context->previous(), isolate());
} }
...@@ -100,21 +104,17 @@ Reduction JSContextSpecialization::ReduceJSLoadContext(Node* node) { ...@@ -100,21 +104,17 @@ Reduction JSContextSpecialization::ReduceJSLoadContext(Node* node) {
Reduction JSContextSpecialization::ReduceJSStoreContext(Node* node) { Reduction JSContextSpecialization::ReduceJSStoreContext(Node* node) {
DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode()); DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
HeapObjectMatcher m(NodeProperties::GetValueInput(node, 0)); // Get the specialization context from the node.
// If the context is not constant, no reduction can occur. Handle<Context> context;
if (!m.HasValue()) { if (!GetSpecializationContext(node).ToHandle(&context)) return NoChange();
return NoChange();
}
const ContextAccess& access = ContextAccessOf(node->op());
// The access does not have to look up a parent, nothing to fold. // The access does not have to look up a parent, nothing to fold.
const ContextAccess& access = ContextAccessOf(node->op());
if (access.depth() == 0) { if (access.depth() == 0) {
return NoChange(); return NoChange();
} }
// Find the right parent context. // Find the right parent context.
Handle<Context> context = Handle<Context>::cast(m.Value().handle());
for (size_t i = access.depth(); i > 0; --i) { for (size_t i = access.depth(); i > 0; --i) {
context = handle(context->previous(), isolate()); context = handle(context->previous(), isolate());
} }
......
...@@ -27,10 +27,12 @@ class JSContextSpecialization final : public AdvancedReducer { ...@@ -27,10 +27,12 @@ class JSContextSpecialization final : public AdvancedReducer {
Reduction Reduce(Node* node) final; Reduction Reduce(Node* node) final;
private: private:
Reduction ReduceParameter(Node* node);
Reduction ReduceJSLoadContext(Node* node); Reduction ReduceJSLoadContext(Node* node);
Reduction ReduceJSStoreContext(Node* node); Reduction ReduceJSStoreContext(Node* node);
// Returns the {Context} to specialize {node} to (if any).
MaybeHandle<Context> GetSpecializationContext(Node* node);
Isolate* isolate() const; Isolate* isolate() const;
JSOperatorBuilder* javascript() const; JSOperatorBuilder* javascript() const;
JSGraph* jsgraph() const { return jsgraph_; } JSGraph* jsgraph() const { return jsgraph_; }
......
...@@ -498,7 +498,9 @@ struct InliningPhase { ...@@ -498,7 +498,9 @@ struct InliningPhase {
CommonOperatorReducer common_reducer(&graph_reducer, data->graph(), CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
data->common(), data->machine()); data->common(), data->machine());
JSContextSpecialization context_specialization( JSContextSpecialization context_specialization(
&graph_reducer, data->jsgraph(), data->info()->context()); &graph_reducer, data->jsgraph(), data->info()->is_context_specializing()
? data->info()->context()
: MaybeHandle<Context>());
JSFrameSpecialization frame_specialization(data->info()->osr_frame(), JSFrameSpecialization frame_specialization(data->info()->osr_frame(),
data->jsgraph()); data->jsgraph());
JSInliner inliner(&graph_reducer, data->info()->is_inlining_enabled() JSInliner inliner(&graph_reducer, data->info()->is_inlining_enabled()
...@@ -510,9 +512,7 @@ struct InliningPhase { ...@@ -510,9 +512,7 @@ struct InliningPhase {
if (data->info()->is_frame_specializing()) { if (data->info()->is_frame_specializing()) {
AddReducer(data, &graph_reducer, &frame_specialization); AddReducer(data, &graph_reducer, &frame_specialization);
} }
if (data->info()->is_context_specializing()) { AddReducer(data, &graph_reducer, &context_specialization);
AddReducer(data, &graph_reducer, &context_specialization);
}
AddReducer(data, &graph_reducer, &inliner); AddReducer(data, &graph_reducer, &inliner);
graph_reducer.ReduceGraph(); graph_reducer.ReduceGraph();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment