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

Side by Side Diff: src/compiler/js-context-specialization.cc

Issue 440053002: Update and extend context specialization. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 4 months 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/common-operator.h" 5 #include "src/compiler/common-operator.h"
6 #include "src/compiler/generic-node-inl.h" 6 #include "src/compiler/generic-node-inl.h"
7 #include "src/compiler/graph-inl.h"
7 #include "src/compiler/js-context-specialization.h" 8 #include "src/compiler/js-context-specialization.h"
8 #include "src/compiler/js-operator.h" 9 #include "src/compiler/js-operator.h"
9 #include "src/compiler/node-aux-data-inl.h" 10 #include "src/compiler/node-aux-data-inl.h"
10 #include "src/compiler/node-matchers.h" 11 #include "src/compiler/node-matchers.h"
11 #include "src/compiler/node-properties-inl.h" 12 #include "src/compiler/node-properties-inl.h"
12 13
13 namespace v8 { 14 namespace v8 {
14 namespace internal { 15 namespace internal {
15 namespace compiler { 16 namespace compiler {
16 17
17 // TODO(titzer): factor this out to a common routine with js-typed-lowering. 18 // TODO(titzer): factor this out to a common routine with js-typed-lowering.
18 static void ReplaceEffectfulWithValue(Node* node, Node* value) { 19 static void ReplaceEffectfulWithValue(Node* node, Node* value) {
19 Node* effect = NodeProperties::GetEffectInput(node); 20 Node* effect = NULL;
21 if (NodeProperties::HasEffectInput(node)) {
22 effect = NodeProperties::GetEffectInput(node);
23 }
20 24
21 // Requires distinguishing between value and effect edges. 25 // Requires distinguishing between value and effect edges.
22 UseIter iter = node->uses().begin(); 26 UseIter iter = node->uses().begin();
23 while (iter != node->uses().end()) { 27 while (iter != node->uses().end()) {
24 if (NodeProperties::IsEffectEdge(iter.edge())) { 28 if (NodeProperties::IsEffectEdge(iter.edge())) {
29 DCHECK_NE(NULL, effect);
25 iter = iter.UpdateToAndIncrement(effect); 30 iter = iter.UpdateToAndIncrement(effect);
26 } else { 31 } else {
27 iter = iter.UpdateToAndIncrement(value); 32 iter = iter.UpdateToAndIncrement(value);
28 } 33 }
29 } 34 }
30 } 35 }
31 36
32 37
38 class ContextSpecializationVisitor : public NullNodeVisitor {
39 public:
40 explicit ContextSpecializationVisitor(JSContextSpecializer* spec)
41 : spec_(spec) {}
42
43 GenericGraphVisit::Control Post(Node* node) {
44 switch (node->opcode()) {
45 case IrOpcode::kJSLoadContext: {
46 Reduction r = spec_->ReduceJSLoadContext(node);
47 if (r.Changed() && r.replacement() != node) {
48 ReplaceEffectfulWithValue(node, r.replacement());
49 }
50 break;
51 }
52 case IrOpcode::kJSStoreContext: {
53 Reduction r = spec_->ReduceJSStoreContext(node);
54 if (r.Changed() && r.replacement() != node) {
55 ReplaceEffectfulWithValue(node, r.replacement());
56 }
57 break;
58 }
59 default:
60 break;
61 }
62 return GenericGraphVisit::CONTINUE;
63 }
64
65 private:
66 JSContextSpecializer* spec_;
67 };
68
69
33 void JSContextSpecializer::SpecializeToContext() { 70 void JSContextSpecializer::SpecializeToContext() {
34 ValueMatcher<Handle<Context> > match(context_); 71 ReplaceEffectfulWithValue(context_, jsgraph_->Constant(info_->context()));
35 72
36 // Iterate over all uses of the context and try to replace {LoadContext} 73 ContextSpecializationVisitor visitor(this);
37 // nodes with their values from the constant context. 74 jsgraph_->graph()->VisitNodeInputsFromEnd(&visitor);
38 UseIter iter = match.node()->uses().begin();
39 while (iter != match.node()->uses().end()) {
40 Node* use = *iter;
41 if (use->opcode() == IrOpcode::kJSLoadContext) {
42 Reduction r = ReduceJSLoadContext(use);
43 if (r.Changed() && r.replacement() != use) {
44 ReplaceEffectfulWithValue(use, r.replacement());
45 }
46 }
47 ++iter;
48 }
49 } 75 }
50 76
51 77
52 Reduction JSContextSpecializer::ReduceJSLoadContext(Node* node) { 78 Reduction JSContextSpecializer::ReduceJSLoadContext(Node* node) {
53 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); 79 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
54 80
81 ValueMatcher<Handle<Context> > match(NodeProperties::GetValueInput(node, 0));
82 // If the context is not constant, no reduction can occur.
83 if (!match.HasValue()) {
84 return Reducer::NoChange();
85 }
86
55 ContextAccess access = 87 ContextAccess access =
56 static_cast<Operator1<ContextAccess>*>(node->op())->parameter(); 88 static_cast<Operator1<ContextAccess>*>(node->op())->parameter();
Michael Starzinger 2014/08/08 10:00:17 nit: I know this wasn't changed by your CL, but th
sigurds 2014/08/08 11:00:12 Done.
57 89
58 // Find the right parent context. 90 // Find the right parent context.
59 Context* context = *info_->context(); 91 Context* context = *match.Value();
60 for (int i = access.depth(); i > 0; --i) { 92 for (int i = access.depth(); i > 0; --i) {
61 context = context->previous(); 93 context = context->previous();
62 } 94 }
63 95
64 // If the access itself is mutable, only fold-in the parent. 96 // If the access itself is mutable, only fold-in the parent.
65 if (!access.immutable()) { 97 if (!access.immutable()) {
66 // The access does not have to look up a parent, nothing to fold. 98 // The access does not have to look up a parent, nothing to fold.
67 if (access.depth() == 0) { 99 if (access.depth() == 0) {
68 return Reducer::NoChange(); 100 return Reducer::NoChange();
69 } 101 }
70 Operator* op = jsgraph_->javascript()->LoadContext(0, access.index(), 102 Operator* op = jsgraph_->javascript()->LoadContext(0, access.index(),
71 access.immutable()); 103 access.immutable());
72 node->set_op(op); 104 node->set_op(op);
73 Handle<Object> context_handle = Handle<Object>(context, info_->isolate()); 105 Handle<Object> context_handle = Handle<Object>(context, info_->isolate());
74 node->ReplaceInput(0, jsgraph_->Constant(context_handle)); 106 node->ReplaceInput(0, jsgraph_->Constant(context_handle));
75 return Reducer::Changed(node); 107 return Reducer::Changed(node);
76 } 108 }
77 Handle<Object> value = 109 Handle<Object> value =
78 Handle<Object>(context->get(access.index()), info_->isolate()); 110 Handle<Object>(context->get(access.index()), info_->isolate());
79 111
80 // Even though the context slot is immutable, the context might have escaped 112 // Even though the context slot is immutable, the context might have escaped
81 // before the function to which it belongs has initialized the slot. 113 // before the function to which it belongs has initialized the slot.
82 // We must be conservative and check if the value in the slot is currently the 114 // We must be conservative and check if the value in the slot is currently the
83 // hole or undefined. If it is neither of these, then it must be initialized. 115 // hole or undefined. If it is neither of these, then it must be initialized.
84 if (value->IsUndefined() || value->IsTheHole()) return Reducer::NoChange(); 116 if (value->IsUndefined() || value->IsTheHole()) {
117 return Reducer::NoChange();
118 }
85 119
86 // Success. The context load can be replaced with the constant. 120 // Success. The context load can be replaced with the constant.
87 // TODO(titzer): record the specialization for sharing code across multiple 121 // TODO(titzer): record the specialization for sharing code across multiple
88 // contexts that have the same value in the corresponding context slot. 122 // contexts that have the same value in the corresponding context slot.
89 return Reducer::Replace(jsgraph_->Constant(value)); 123 return Reducer::Replace(jsgraph_->Constant(value));
90 } 124 }
125
126
127 Reduction JSContextSpecializer::ReduceJSStoreContext(Node* node) {
128 DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
129
130 ValueMatcher<Handle<Context> > match(NodeProperties::GetValueInput(node, 0));
131 // If the context is not constant, no reduction can occur.
132 if (!match.HasValue()) {
133 return Reducer::NoChange();
134 }
135
136 ContextAccess access =
137 static_cast<Operator1<ContextAccess>*>(node->op())->parameter();
Michael Starzinger 2014/08/08 10:00:17 nit: Likewise.
sigurds 2014/08/08 11:00:12 Done.
138
139 // The access does not have to look up a parent, nothing to fold.
140 if (access.depth() == 0) {
141 return Reducer::NoChange();
142 }
143
144 // Find the right parent context.
145 Context* context = *match.Value();
146 for (int i = access.depth(); i > 0; --i) {
147 context = context->previous();
148 }
149
150 Operator* op = jsgraph_->javascript()->StoreContext(0, access.index());
151 node->set_op(op);
152 Handle<Object> new_context_handle = Handle<Object>(context, info_->isolate());
153 node->ReplaceInput(0, jsgraph_->Constant(new_context_handle));
154
155 return Reducer::Changed(node);
156 }
91 } 157 }
92 } 158 }
93 } // namespace v8::internal::compiler 159 } // namespace v8::internal::compiler
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698