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

Side by Side Diff: src/compiler/js-inlining.cc

Issue 562543002: Revert "Switch inlining to use simplified instead of machine loads.", "Fix size_t to int conversion… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 3 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
« no previous file with comments | « src/compiler/js-graph.h ('k') | src/compiler/machine-operator-reducer-unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/access-builder.h"
6 #include "src/compiler/ast-graph-builder.h" 5 #include "src/compiler/ast-graph-builder.h"
7 #include "src/compiler/common-operator.h" 6 #include "src/compiler/common-operator.h"
8 #include "src/compiler/generic-node-inl.h" 7 #include "src/compiler/generic-node-inl.h"
9 #include "src/compiler/graph-inl.h" 8 #include "src/compiler/graph-inl.h"
10 #include "src/compiler/graph-visualizer.h" 9 #include "src/compiler/graph-visualizer.h"
11 #include "src/compiler/js-inlining.h" 10 #include "src/compiler/js-inlining.h"
12 #include "src/compiler/js-operator.h" 11 #include "src/compiler/js-operator.h"
13 #include "src/compiler/node-aux-data-inl.h" 12 #include "src/compiler/node-aux-data-inl.h"
14 #include "src/compiler/node-matchers.h" 13 #include "src/compiler/node-matchers.h"
15 #include "src/compiler/node-properties-inl.h" 14 #include "src/compiler/node-properties-inl.h"
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 CHECK(Scope::Analyze(info)); 60 CHECK(Scope::Analyze(info));
62 CHECK_NE(NULL, info->scope()); 61 CHECK_NE(NULL, info->scope());
63 Handle<ScopeInfo> scope_info = ScopeInfo::Create(info->scope(), info->zone()); 62 Handle<ScopeInfo> scope_info = ScopeInfo::Create(info->scope(), info->zone());
64 info->shared_info()->set_scope_info(*scope_info); 63 info->shared_info()->set_scope_info(*scope_info);
65 } 64 }
66 65
67 66
68 // A facade on a JSFunction's graph to facilitate inlining. It assumes the 67 // A facade on a JSFunction's graph to facilitate inlining. It assumes the
69 // that the function graph has only one return statement, and provides 68 // that the function graph has only one return statement, and provides
70 // {UnifyReturn} to convert a function graph to that end. 69 // {UnifyReturn} to convert a function graph to that end.
70 // InlineAtCall will create some new nodes using {graph}'s builders (and hence
71 // those nodes will live in {graph}'s zone.
71 class Inlinee { 72 class Inlinee {
72 public: 73 public:
73 Inlinee(Node* start, Node* end) : start_(start), end_(end) {} 74 explicit Inlinee(JSGraph* graph) : jsgraph_(graph) {}
75
76 Graph* graph() { return jsgraph_->graph(); }
77 JSGraph* jsgraph() { return jsgraph_; }
74 78
75 // Returns the last regular control node, that is 79 // Returns the last regular control node, that is
76 // the last control node before the end node. 80 // the last control node before the end node.
77 Node* end_block() { return NodeProperties::GetControlInput(unique_return()); } 81 Node* end_block() { return NodeProperties::GetControlInput(unique_return()); }
78 82
79 // Return the effect output of the graph, 83 // Return the effect output of the graph,
80 // that is the effect input of the return statement of the inlinee. 84 // that is the effect input of the return statement of the inlinee.
81 Node* effect_output() { 85 Node* effect_output() {
82 return NodeProperties::GetEffectInput(unique_return()); 86 return NodeProperties::GetEffectInput(unique_return());
83 } 87 }
84 // Return the value output of the graph, 88 // Return the value output of the graph,
85 // that is the value input of the return statement of the inlinee. 89 // that is the value input of the return statement of the inlinee.
86 Node* value_output() { 90 Node* value_output() {
87 return NodeProperties::GetValueInput(unique_return(), 0); 91 return NodeProperties::GetValueInput(unique_return(), 0);
88 } 92 }
89 // Return the unique return statement of the graph. 93 // Return the unique return statement of the graph.
90 Node* unique_return() { 94 Node* unique_return() {
91 Node* unique_return = NodeProperties::GetControlInput(end_); 95 Node* unique_return =
96 NodeProperties::GetControlInput(jsgraph_->graph()->end());
92 DCHECK_EQ(IrOpcode::kReturn, unique_return->opcode()); 97 DCHECK_EQ(IrOpcode::kReturn, unique_return->opcode());
93 return unique_return; 98 return unique_return;
94 } 99 }
95 // Inline this graph at {call}, use {jsgraph} and its zone to create 100 // Inline this graph at {call}, use {jsgraph} and its zone to create
96 // any new nodes. 101 // any new nodes.
97 void InlineAtCall(JSGraph* jsgraph, Node* call); 102 void InlineAtCall(JSGraph* jsgraph, Node* call);
98
99 // Ensure that only a single return reaches the end node. 103 // Ensure that only a single return reaches the end node.
100 static void UnifyReturn(JSGraph* jsgraph); 104 void UnifyReturn();
101 105
102 private: 106 private:
103 Node* start_; 107 JSGraph* jsgraph_;
104 Node* end_;
105 }; 108 };
106 109
107 110
108 void Inlinee::UnifyReturn(JSGraph* jsgraph) { 111 void Inlinee::UnifyReturn() {
109 Graph* graph = jsgraph->graph(); 112 Graph* graph = jsgraph_->graph();
110 113
111 Node* final_merge = NodeProperties::GetControlInput(graph->end(), 0); 114 Node* final_merge = NodeProperties::GetControlInput(graph->end(), 0);
112 if (final_merge->opcode() == IrOpcode::kReturn) { 115 if (final_merge->opcode() == IrOpcode::kReturn) {
113 // nothing to do 116 // nothing to do
114 return; 117 return;
115 } 118 }
116 DCHECK_EQ(IrOpcode::kMerge, final_merge->opcode()); 119 DCHECK_EQ(IrOpcode::kMerge, final_merge->opcode());
117 120
118 int predecessors = 121 int predecessors =
119 OperatorProperties::GetControlInputCount(final_merge->op()); 122 OperatorProperties::GetControlInputCount(final_merge->op());
120 Operator* op_phi = jsgraph->common()->Phi(kMachAnyTagged, predecessors); 123 Operator* op_phi = jsgraph_->common()->Phi(kMachAnyTagged, predecessors);
121 Operator* op_ephi = jsgraph->common()->EffectPhi(predecessors); 124 Operator* op_ephi = jsgraph_->common()->EffectPhi(predecessors);
122 125
123 NodeVector values(jsgraph->zone()); 126 NodeVector values(jsgraph_->zone());
124 NodeVector effects(jsgraph->zone()); 127 NodeVector effects(jsgraph_->zone());
125 // Iterate over all control flow predecessors, 128 // Iterate over all control flow predecessors,
126 // which must be return statements. 129 // which must be return statements.
127 InputIter iter = final_merge->inputs().begin(); 130 InputIter iter = final_merge->inputs().begin();
128 while (iter != final_merge->inputs().end()) { 131 while (iter != final_merge->inputs().end()) {
129 Node* input = *iter; 132 Node* input = *iter;
130 switch (input->opcode()) { 133 switch (input->opcode()) {
131 case IrOpcode::kReturn: 134 case IrOpcode::kReturn:
132 values.push_back(NodeProperties::GetValueInput(input, 0)); 135 values.push_back(NodeProperties::GetValueInput(input, 0));
133 effects.push_back(NodeProperties::GetEffectInput(input)); 136 effects.push_back(NodeProperties::GetEffectInput(input));
134 iter.UpdateToAndIncrement(NodeProperties::GetControlInput(input)); 137 iter.UpdateToAndIncrement(NodeProperties::GetControlInput(input));
135 input->RemoveAllInputs(); 138 input->RemoveAllInputs();
136 break; 139 break;
137 default: 140 default:
138 UNREACHABLE(); 141 UNREACHABLE();
139 ++iter; 142 ++iter;
140 break; 143 break;
141 } 144 }
142 } 145 }
143 values.push_back(final_merge); 146 values.push_back(final_merge);
144 effects.push_back(final_merge); 147 effects.push_back(final_merge);
145 Node* phi = 148 Node* phi =
146 graph->NewNode(op_phi, static_cast<int>(values.size()), &values.front()); 149 graph->NewNode(op_phi, static_cast<int>(values.size()), &values.front());
147 Node* ephi = graph->NewNode(op_ephi, static_cast<int>(effects.size()), 150 Node* ephi = graph->NewNode(op_ephi, static_cast<int>(effects.size()),
148 &effects.front()); 151 &effects.front());
149 Node* new_return = 152 Node* new_return =
150 graph->NewNode(jsgraph->common()->Return(), phi, ephi, final_merge); 153 graph->NewNode(jsgraph_->common()->Return(), phi, ephi, final_merge);
151 graph->end()->ReplaceInput(0, new_return); 154 graph->end()->ReplaceInput(0, new_return);
152 } 155 }
153 156
154 157
155 class CopyVisitor : public NullNodeVisitor { 158 void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
156 public: 159 MachineOperatorBuilder machine(jsgraph->zone());
157 CopyVisitor(Graph* source_graph, Graph* target_graph, Zone* temp_zone)
158 : copies_(source_graph->NodeCount(), NULL, temp_zone),
159 sentinels_(source_graph->NodeCount(), NULL, temp_zone),
160 source_graph_(source_graph),
161 target_graph_(target_graph),
162 temp_zone_(temp_zone),
163 sentinel_op_(IrOpcode::kDead, Operator::kNoProperties, 0, 0,
164 "sentinel") {}
165 160
166 GenericGraphVisit::Control Post(Node* original) {
167 NodeVector inputs(temp_zone_);
168 for (InputIter it = original->inputs().begin();
169 it != original->inputs().end(); ++it) {
170 inputs.push_back(GetCopy(*it));
171 }
172
173 // Reuse the operator in the copy. This assumes that op lives in a zone
174 // that lives longer than graph()'s zone.
175 Node* copy = target_graph_->NewNode(
176 original->op(), static_cast<int>(inputs.size()), &inputs.front());
177 copies_[original->id()] = copy;
178 return GenericGraphVisit::CONTINUE;
179 }
180
181 Node* GetCopy(Node* original) {
182 Node* copy = copies_[original->id()];
183 if (copy == NULL) {
184 copy = GetSentinel(original);
185 }
186 return copy;
187 }
188
189 void CopyGraph() {
190 source_graph_->VisitNodeInputsFromEnd(this);
191 ReplaceSentinels();
192 }
193
194 const NodeVector& copies() { return copies_; }
195
196 private:
197 void ReplaceSentinels() {
198 for (int id = 0; id < source_graph_->NodeCount(); ++id) {
199 Node* sentinel = sentinels_[id];
200 if (sentinel == NULL) continue;
201 Node* copy = copies_[id];
202 DCHECK_NE(NULL, copy);
203 sentinel->ReplaceUses(copy);
204 }
205 }
206
207 Node* GetSentinel(Node* original) {
208 Node* sentinel = sentinels_[original->id()];
209 if (sentinel == NULL) {
210 sentinel = target_graph_->NewNode(&sentinel_op_);
211 }
212 return sentinel;
213 }
214
215 NodeVector copies_;
216 NodeVector sentinels_;
217 Graph* source_graph_;
218 Graph* target_graph_;
219 Zone* temp_zone_;
220 SimpleOperator sentinel_op_;
221 };
222
223
224 void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
225 // The scheduler is smart enough to place our code; we just ensure {control} 161 // The scheduler is smart enough to place our code; we just ensure {control}
226 // becomes the control input of the start of the inlinee. 162 // becomes the control input of the start of the inlinee.
227 Node* control = NodeProperties::GetControlInput(call); 163 Node* control = NodeProperties::GetControlInput(call);
228 164
229 // The inlinee uses the context from the JSFunction object. This will 165 // The inlinee uses the context from the JSFunction object. This will
230 // also be the effect dependency for the inlinee as it produces an effect. 166 // also be the effect dependency for the inlinee as it produces an effect.
231 SimplifiedOperatorBuilder simplified(jsgraph->zone()); 167 // TODO(sigurds) Use simplified load once it is ready.
232 Node* context = jsgraph->graph()->NewNode( 168 Node* context = jsgraph->graph()->NewNode(
233 simplified.LoadField(AccessBuilder::ForJSFunctionContext()), 169 machine.Load(kMachAnyTagged), NodeProperties::GetValueInput(call, 0),
234 NodeProperties::GetValueInput(call, 0), 170 jsgraph->Int32Constant(JSFunction::kContextOffset - kHeapObjectTag),
235 NodeProperties::GetEffectInput(call)); 171 NodeProperties::GetEffectInput(call));
236 172
237 // {inlinee_inputs} counts JSFunction, Receiver, arguments, context, 173 // {inlinee_inputs} counts JSFunction, Receiver, arguments, context,
238 // but not effect, control. 174 // but not effect, control.
239 int inlinee_inputs = start_->op()->OutputCount(); 175 int inlinee_inputs = graph()->start()->op()->OutputCount();
240 // Context is last argument. 176 // Context is last argument.
241 int inlinee_context_index = inlinee_inputs - 1; 177 int inlinee_context_index = inlinee_inputs - 1;
242 // {inliner_inputs} counts JSFunction, Receiver, arguments, but not 178 // {inliner_inputs} counts JSFunction, Receiver, arguments, but not
243 // context, effect, control. 179 // context, effect, control.
244 int inliner_inputs = OperatorProperties::GetValueInputCount(call->op()); 180 int inliner_inputs = OperatorProperties::GetValueInputCount(call->op());
245 // Iterate over all uses of the start node. 181 // Iterate over all uses of the start node.
246 UseIter iter = start_->uses().begin(); 182 UseIter iter = graph()->start()->uses().begin();
247 while (iter != start_->uses().end()) { 183 while (iter != graph()->start()->uses().end()) {
248 Node* use = *iter; 184 Node* use = *iter;
249 switch (use->opcode()) { 185 switch (use->opcode()) {
250 case IrOpcode::kParameter: { 186 case IrOpcode::kParameter: {
251 int index = 1 + OpParameter<int>(use->op()); 187 int index = 1 + OpParameter<int>(use->op());
252 if (index < inliner_inputs && index < inlinee_context_index) { 188 if (index < inliner_inputs && index < inlinee_context_index) {
253 // There is an input from the call, and the index is a value 189 // There is an input from the call, and the index is a value
254 // projection but not the context, so rewire the input. 190 // projection but not the context, so rewire the input.
255 NodeProperties::ReplaceWithValue(*iter, call->InputAt(index)); 191 NodeProperties::ReplaceWithValue(*iter, call->InputAt(index));
256 } else if (index == inlinee_context_index) { 192 } else if (index == inlinee_context_index) {
257 // This is the context projection, rewire it to the context from the 193 // This is the context projection, rewire it to the context from the
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 iter.UpdateToAndIncrement(value_output()); 227 iter.UpdateToAndIncrement(value_output());
292 } 228 }
293 } 229 }
294 call->RemoveAllInputs(); 230 call->RemoveAllInputs();
295 DCHECK_EQ(0, call->UseCount()); 231 DCHECK_EQ(0, call->UseCount());
296 // TODO(sigurds) Remove this once we copy. 232 // TODO(sigurds) Remove this once we copy.
297 unique_return()->RemoveAllInputs(); 233 unique_return()->RemoveAllInputs();
298 } 234 }
299 235
300 236
301 void JSInliner::TryInlineCall(Node* call) { 237 void JSInliner::TryInlineCall(Node* node) {
302 DCHECK_EQ(IrOpcode::kJSCallFunction, call->opcode()); 238 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
303 239
304 HeapObjectMatcher<JSFunction> match(call->InputAt(0)); 240 HeapObjectMatcher<JSFunction> match(node->InputAt(0));
305 if (!match.HasValue()) { 241 if (!match.HasValue()) {
306 return; 242 return;
307 } 243 }
308 244
309 Handle<JSFunction> function = match.Value().handle(); 245 Handle<JSFunction> function = match.Value().handle();
310 246
311 if (function->shared()->native()) { 247 if (function->shared()->native()) {
312 if (FLAG_trace_turbo_inlining) { 248 if (FLAG_trace_turbo_inlining) {
313 SmartArrayPointer<char> name = 249 SmartArrayPointer<char> name =
314 function->shared()->DebugName()->ToCString(); 250 function->shared()->DebugName()->ToCString();
(...skipping 17 matching lines...) Expand all
332 } 268 }
333 return; 269 return;
334 } 270 }
335 271
336 if (FLAG_trace_turbo_inlining) { 272 if (FLAG_trace_turbo_inlining) {
337 SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString(); 273 SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString();
338 PrintF("Inlining %s into %s\n", name.get(), 274 PrintF("Inlining %s into %s\n", name.get(),
339 info_->shared_info()->DebugName()->ToCString().get()); 275 info_->shared_info()->DebugName()->ToCString().get());
340 } 276 }
341 277
342 Graph graph(info.zone()); 278 Graph graph(info_->zone());
343 Typer typer(info.zone()); 279 graph.SetNextNodeId(jsgraph_->graph()->NextNodeID());
344 JSGraph jsgraph(&graph, jsgraph_->common(), jsgraph_->javascript(), &typer, 280
345 jsgraph_->machine()); 281 Typer typer(info_->zone());
282 CommonOperatorBuilder common(info_->zone());
283 JSGraph jsgraph(&graph, &common, &typer);
346 284
347 AstGraphBuilder graph_builder(&info, &jsgraph); 285 AstGraphBuilder graph_builder(&info, &jsgraph);
348 graph_builder.CreateGraph(); 286 graph_builder.CreateGraph();
349 Inlinee::UnifyReturn(&jsgraph);
350 287
351 CopyVisitor visitor(&graph, jsgraph_->graph(), info.zone()); 288 Inlinee inlinee(&jsgraph);
352 visitor.CopyGraph(); 289 inlinee.UnifyReturn();
290 inlinee.InlineAtCall(jsgraph_, node);
353 291
354 Inlinee inlinee(visitor.GetCopy(graph.start()), visitor.GetCopy(graph.end())); 292 jsgraph_->graph()->SetNextNodeId(inlinee.graph()->NextNodeID());
355 inlinee.InlineAtCall(jsgraph_, call);
356 } 293 }
357 } 294 }
358 } 295 }
359 } // namespace v8::internal::compiler 296 } // namespace v8::internal::compiler
OLDNEW
« no previous file with comments | « src/compiler/js-graph.h ('k') | src/compiler/machine-operator-reducer-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698