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 {
Reduction JSContextSpecialization::Reduce(Node* node) {
switch (node->opcode()) {
case IrOpcode::kParameter:
return ReduceParameter(node);
case IrOpcode::kJSLoadContext:
return ReduceJSLoadContext(node);
case IrOpcode::kJSStoreContext:
......@@ -30,37 +28,43 @@ Reduction JSContextSpecialization::Reduce(Node* node) {
}
Reduction JSContextSpecialization::ReduceParameter(Node* node) {
DCHECK_EQ(IrOpcode::kParameter, node->opcode());
Node* const start = NodeProperties::GetValueInput(node, 0);
DCHECK_EQ(IrOpcode::kStart, start->opcode());
int const index = ParameterIndexOf(node->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) {
Handle<Context> context_constant;
if (context().ToHandle(&context_constant)) {
return Replace(jsgraph()->Constant(context_constant));
MaybeHandle<Context> JSContextSpecialization::GetSpecializationContext(
Node* node) {
DCHECK(node->opcode() == IrOpcode::kJSLoadContext ||
node->opcode() == IrOpcode::kJSStoreContext);
Node* const object = NodeProperties::GetValueInput(node, 0);
switch (object->opcode()) {
case IrOpcode::kHeapConstant:
return Handle<Context>::cast(
OpParameter<Unique<HeapObject>>(object).handle());
case IrOpcode::kParameter: {
Node* const start = NodeProperties::GetValueInput(object, 0);
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) {
DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
HeapObjectMatcher m(NodeProperties::GetValueInput(node, 0));
// If the context is not constant, no reduction can occur.
if (!m.HasValue()) {
return NoChange();
}
const ContextAccess& access = ContextAccessOf(node->op());
// Get the specialization context from the node.
Handle<Context> context;
if (!GetSpecializationContext(node).ToHandle(&context)) return NoChange();
// 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) {
context = handle(context->previous(), isolate());
}
......@@ -100,21 +104,17 @@ Reduction JSContextSpecialization::ReduceJSLoadContext(Node* node) {
Reduction JSContextSpecialization::ReduceJSStoreContext(Node* node) {
DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
HeapObjectMatcher m(NodeProperties::GetValueInput(node, 0));
// If the context is not constant, no reduction can occur.
if (!m.HasValue()) {
return NoChange();
}
const ContextAccess& access = ContextAccessOf(node->op());
// Get the specialization context from the node.
Handle<Context> context;
if (!GetSpecializationContext(node).ToHandle(&context)) return NoChange();
// The access does not have to look up a parent, nothing to fold.
const ContextAccess& access = ContextAccessOf(node->op());
if (access.depth() == 0) {
return NoChange();
}
// Find the right parent context.
Handle<Context> context = Handle<Context>::cast(m.Value().handle());
for (size_t i = access.depth(); i > 0; --i) {
context = handle(context->previous(), isolate());
}
......
......@@ -27,10 +27,12 @@ class JSContextSpecialization final : public AdvancedReducer {
Reduction Reduce(Node* node) final;
private:
Reduction ReduceParameter(Node* node);
Reduction ReduceJSLoadContext(Node* node);
Reduction ReduceJSStoreContext(Node* node);
// Returns the {Context} to specialize {node} to (if any).
MaybeHandle<Context> GetSpecializationContext(Node* node);
Isolate* isolate() const;
JSOperatorBuilder* javascript() const;
JSGraph* jsgraph() const { return jsgraph_; }
......
......@@ -498,7 +498,9 @@ struct InliningPhase {
CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
data->common(), data->machine());
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(),
data->jsgraph());
JSInliner inliner(&graph_reducer, data->info()->is_inlining_enabled()
......@@ -510,9 +512,7 @@ struct InliningPhase {
if (data->info()->is_frame_specializing()) {
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);
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