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

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

Issue 941963003: Revert of [turbofan] Finally get rid of the generic algorithm. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 10 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
« no previous file with comments | « src/compiler/js-inlining.h ('k') | test/cctest/compiler/test-control-reducer.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/js-inlining.h"
6
7 #include "src/ast.h" 5 #include "src/ast.h"
8 #include "src/ast-numbering.h" 6 #include "src/ast-numbering.h"
9 #include "src/compiler/access-builder.h" 7 #include "src/compiler/access-builder.h"
10 #include "src/compiler/all-nodes.h"
11 #include "src/compiler/ast-graph-builder.h" 8 #include "src/compiler/ast-graph-builder.h"
12 #include "src/compiler/common-operator.h" 9 #include "src/compiler/common-operator.h"
10 #include "src/compiler/graph-inl.h"
13 #include "src/compiler/graph-visualizer.h" 11 #include "src/compiler/graph-visualizer.h"
12 #include "src/compiler/js-inlining.h"
14 #include "src/compiler/js-operator.h" 13 #include "src/compiler/js-operator.h"
15 #include "src/compiler/node-matchers.h" 14 #include "src/compiler/node-matchers.h"
16 #include "src/compiler/node-properties.h" 15 #include "src/compiler/node-properties.h"
17 #include "src/compiler/simplified-operator.h" 16 #include "src/compiler/simplified-operator.h"
18 #include "src/compiler/typer.h" 17 #include "src/compiler/typer.h"
19 #include "src/full-codegen.h" 18 #include "src/full-codegen.h"
20 #include "src/parser.h" 19 #include "src/parser.h"
21 #include "src/rewriter.h" 20 #include "src/rewriter.h"
22 #include "src/scopes.h" 21 #include "src/scopes.h"
23 22
23
24 namespace v8 { 24 namespace v8 {
25 namespace internal { 25 namespace internal {
26 namespace compiler { 26 namespace compiler {
27 27
28 28
29 // Provides convenience accessors for calls to JS functions. 29 // Provides convenience accessors for calls to JS functions.
30 class JSCallFunctionAccessor { 30 class JSCallFunctionAccessor {
31 public: 31 public:
32 explicit JSCallFunctionAccessor(Node* call) : call_(call) { 32 explicit JSCallFunctionAccessor(Node* call) : call_(call) {
33 DCHECK_EQ(IrOpcode::kJSCallFunction, call->opcode()); 33 DCHECK_EQ(IrOpcode::kJSCallFunction, call->opcode());
(...skipping 15 matching lines...) Expand all
49 return value_inputs - 2; 49 return value_inputs - 2;
50 } 50 }
51 51
52 Node* frame_state() { return NodeProperties::GetFrameStateInput(call_); } 52 Node* frame_state() { return NodeProperties::GetFrameStateInput(call_); }
53 53
54 private: 54 private:
55 Node* call_; 55 Node* call_;
56 }; 56 };
57 57
58 58
59 namespace { 59 Reduction JSInliner::Reduce(Node* node) {
60 if (node->opcode() != IrOpcode::kJSCallFunction) return NoChange();
61
62 JSCallFunctionAccessor call(node);
63 HeapObjectMatcher<JSFunction> match(call.jsfunction());
64 if (!match.HasValue()) return NoChange();
65
66 Handle<JSFunction> jsfunction = match.Value().handle();
67
68 if (jsfunction->shared()->native()) {
69 if (FLAG_trace_turbo_inlining) {
70 SmartArrayPointer<char> name =
71 jsfunction->shared()->DebugName()->ToCString();
72 PrintF("Not Inlining %s into %s because inlinee is native\n", name.get(),
73 info_->shared_info()->DebugName()->ToCString().get());
74 }
75 return NoChange();
76 }
77
78 return TryInlineJSCall(node, jsfunction);
79 }
80
60 81
61 // A facade on a JSFunction's graph to facilitate inlining. It assumes the 82 // A facade on a JSFunction's graph to facilitate inlining. It assumes the
62 // that the function graph has only one return statement, and provides 83 // that the function graph has only one return statement, and provides
63 // {UnifyReturn} to convert a function graph to that end. 84 // {UnifyReturn} to convert a function graph to that end.
64 class Inlinee { 85 class Inlinee {
65 public: 86 public:
66 Inlinee(Node* start, Node* end) : start_(start), end_(end) {} 87 Inlinee(Node* start, Node* end) : start_(start), end_(end) {}
67 88
68 // Returns the last regular control node, that is 89 // Returns the last regular control node, that is
69 // the last control node before the end node. 90 // the last control node before the end node.
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 Node* phi = 167 Node* phi =
147 graph->NewNode(op_phi, static_cast<int>(values.size()), &values.front()); 168 graph->NewNode(op_phi, static_cast<int>(values.size()), &values.front());
148 Node* ephi = graph->NewNode(op_ephi, static_cast<int>(effects.size()), 169 Node* ephi = graph->NewNode(op_ephi, static_cast<int>(effects.size()),
149 &effects.front()); 170 &effects.front());
150 Node* new_return = 171 Node* new_return =
151 graph->NewNode(jsgraph->common()->Return(), phi, ephi, final_merge); 172 graph->NewNode(jsgraph->common()->Return(), phi, ephi, final_merge);
152 graph->end()->ReplaceInput(0, new_return); 173 graph->end()->ReplaceInput(0, new_return);
153 } 174 }
154 175
155 176
156 class CopyVisitor { 177 class CopyVisitor : public NullNodeVisitor {
157 public: 178 public:
158 CopyVisitor(Graph* source_graph, Graph* target_graph, Zone* temp_zone) 179 CopyVisitor(Graph* source_graph, Graph* target_graph, Zone* temp_zone)
159 : sentinel_op_(IrOpcode::kDead, Operator::kNoProperties, "Sentinel", 0, 0, 180 : copies_(source_graph->NodeCount(), NULL, temp_zone),
160 0, 0, 0, 0), 181 sentinels_(source_graph->NodeCount(), NULL, temp_zone),
161 sentinel_(target_graph->NewNode(&sentinel_op_)),
162 copies_(source_graph->NodeCount(), sentinel_, temp_zone),
163 source_graph_(source_graph), 182 source_graph_(source_graph),
164 target_graph_(target_graph), 183 target_graph_(target_graph),
165 temp_zone_(temp_zone) {} 184 temp_zone_(temp_zone),
185 sentinel_op_(IrOpcode::kDead, Operator::kNoProperties, "sentinel", 0, 0,
186 0, 0, 0, 0) {}
166 187
167 Node* GetCopy(Node* orig) { return copies_[orig->id()]; } 188 void Post(Node* original) {
189 NodeVector inputs(temp_zone_);
190 for (Node* const node : original->inputs()) {
191 inputs.push_back(GetCopy(node));
192 }
193
194 // Reuse the operator in the copy. This assumes that op lives in a zone
195 // that lives longer than graph()'s zone.
196 Node* copy =
197 target_graph_->NewNode(original->op(), static_cast<int>(inputs.size()),
198 (inputs.empty() ? NULL : &inputs.front()));
199 copies_[original->id()] = copy;
200 }
201
202 Node* GetCopy(Node* original) {
203 Node* copy = copies_[original->id()];
204 if (copy == NULL) {
205 copy = GetSentinel(original);
206 }
207 DCHECK(copy);
208 return copy;
209 }
168 210
169 void CopyGraph() { 211 void CopyGraph() {
170 NodeVector inputs(temp_zone_); 212 source_graph_->VisitNodeInputsFromEnd(this);
171 // TODO(bmeurer): AllNodes should be turned into something like 213 ReplaceSentinels();
172 // Graph::CollectNodesReachableFromEnd() and the gray set stuff should be 214 }
173 // removed since it's only needed by the visualizer. 215
174 AllNodes all(temp_zone_, source_graph_); 216 const NodeVector& copies() { return copies_; }
175 // Copy all nodes reachable from end. 217
176 for (Node* orig : all.live) { 218 private:
177 Node* copy = GetCopy(orig); 219 void ReplaceSentinels() {
178 if (copy != sentinel_) { 220 for (NodeId id = 0; id < source_graph_->NodeCount(); ++id) {
179 // Mapping already exists. 221 Node* sentinel = sentinels_[id];
180 continue; 222 if (sentinel == NULL) continue;
181 } 223 Node* copy = copies_[id];
182 // Copy the node. 224 DCHECK(copy);
183 inputs.clear(); 225 sentinel->ReplaceUses(copy);
184 for (Node* input : orig->inputs()) inputs.push_back(copies_[input->id()]);
185 copy = target_graph_->NewNode(orig->op(), orig->InputCount(), &inputs[0]);
186 copies_[orig->id()] = copy;
187 }
188 // For missing inputs.
189 for (Node* orig : all.live) {
190 Node* copy = copies_[orig->id()];
191 for (int i = 0; i < copy->InputCount(); ++i) {
192 Node* input = copy->InputAt(i);
193 if (input == sentinel_) {
194 copy->ReplaceInput(i, GetCopy(orig->InputAt(i)));
195 }
196 }
197 } 226 }
198 } 227 }
199 228
200 const NodeVector& copies() const { return copies_; } 229 Node* GetSentinel(Node* original) {
230 if (sentinels_[original->id()] == NULL) {
231 sentinels_[original->id()] = target_graph_->NewNode(&sentinel_op_);
232 }
233 return sentinels_[original->id()];
234 }
201 235
202 private:
203 Operator const sentinel_op_;
204 Node* const sentinel_;
205 NodeVector copies_; 236 NodeVector copies_;
206 Graph* const source_graph_; 237 NodeVector sentinels_;
207 Graph* const target_graph_; 238 Graph* source_graph_;
208 Zone* const temp_zone_; 239 Graph* target_graph_;
240 Zone* temp_zone_;
241 Operator sentinel_op_;
209 }; 242 };
210 243
211 244
212 Reduction Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) { 245 Reduction Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
213 // The scheduler is smart enough to place our code; we just ensure {control} 246 // The scheduler is smart enough to place our code; we just ensure {control}
214 // becomes the control input of the start of the inlinee. 247 // becomes the control input of the start of the inlinee.
215 Node* control = NodeProperties::GetControlInput(call); 248 Node* control = NodeProperties::GetControlInput(call);
216 249
217 // The inlinee uses the context from the JSFunction object. This will 250 // The inlinee uses the context from the JSFunction object. This will
218 // also be the effect dependency for the inlinee as it produces an effect. 251 // also be the effect dependency for the inlinee as it produces an effect.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 UNREACHABLE(); 292 UNREACHABLE();
260 } 293 }
261 break; 294 break;
262 } 295 }
263 } 296 }
264 297
265 NodeProperties::ReplaceWithValue(call, value_output(), effect_output()); 298 NodeProperties::ReplaceWithValue(call, value_output(), effect_output());
266 return Reducer::Replace(value_output()); 299 return Reducer::Replace(value_output());
267 } 300 }
268 301
269 } // namespace
270
271 302
272 void JSInliner::AddClosureToFrameState(Node* frame_state, 303 void JSInliner::AddClosureToFrameState(Node* frame_state,
273 Handle<JSFunction> jsfunction) { 304 Handle<JSFunction> jsfunction) {
274 FrameStateCallInfo call_info = OpParameter<FrameStateCallInfo>(frame_state); 305 FrameStateCallInfo call_info = OpParameter<FrameStateCallInfo>(frame_state);
275 const Operator* op = jsgraph_->common()->FrameState( 306 const Operator* op = jsgraph_->common()->FrameState(
276 FrameStateType::JS_FRAME, call_info.bailout_id(), 307 FrameStateType::JS_FRAME, call_info.bailout_id(),
277 call_info.state_combine(), jsfunction); 308 call_info.state_combine(), jsfunction);
278 frame_state->set_op(op); 309 frame_state->set_op(op);
279 } 310 }
280 311
(...skipping 14 matching lines...) Expand all
295 const Operator* op_param = 326 const Operator* op_param =
296 jsgraph_->common()->StateValues(static_cast<int>(params.size())); 327 jsgraph_->common()->StateValues(static_cast<int>(params.size()));
297 Node* params_node = jsgraph_->graph()->NewNode( 328 Node* params_node = jsgraph_->graph()->NewNode(
298 op_param, static_cast<int>(params.size()), &params.front()); 329 op_param, static_cast<int>(params.size()), &params.front());
299 return jsgraph_->graph()->NewNode(op, params_node, node0, node0, 330 return jsgraph_->graph()->NewNode(op, params_node, node0, node0,
300 jsgraph_->UndefinedConstant(), 331 jsgraph_->UndefinedConstant(),
301 call->frame_state()); 332 call->frame_state());
302 } 333 }
303 334
304 335
305 Reduction JSInliner::Reduce(Node* node) { 336 Reduction JSInliner::TryInlineJSCall(Node* call_node,
306 if (node->opcode() != IrOpcode::kJSCallFunction) return NoChange(); 337 Handle<JSFunction> function) {
307 338 JSCallFunctionAccessor call(call_node);
308 JSCallFunctionAccessor call(node);
309 HeapObjectMatcher<JSFunction> match(call.jsfunction());
310 if (!match.HasValue()) return NoChange();
311
312 Handle<JSFunction> function = match.Value().handle();
313
314 if (function->shared()->native()) {
315 if (FLAG_trace_turbo_inlining) {
316 SmartArrayPointer<char> name =
317 function->shared()->DebugName()->ToCString();
318 PrintF("Not Inlining %s into %s because inlinee is native\n", name.get(),
319 info_->shared_info()->DebugName()->ToCString().get());
320 }
321 return NoChange();
322 }
323
324 CompilationInfoWithZone info(function); 339 CompilationInfoWithZone info(function);
325 340
326 if (!Compiler::ParseAndAnalyze(&info)) return NoChange(); 341 if (!Compiler::ParseAndAnalyze(&info)) return NoChange();
327 if (!Compiler::EnsureDeoptimizationSupport(&info)) return NoChange(); 342 if (!Compiler::EnsureDeoptimizationSupport(&info)) return NoChange();
328 343
329 if (info.scope()->arguments() != NULL && is_sloppy(info.language_mode())) { 344 if (info.scope()->arguments() != NULL && is_sloppy(info.language_mode())) {
330 // For now do not inline functions that use their arguments array. 345 // For now do not inline functions that use their arguments array.
331 SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString(); 346 SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString();
332 if (FLAG_trace_turbo_inlining) { 347 if (FLAG_trace_turbo_inlining) {
333 PrintF( 348 PrintF(
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 } 381 }
367 382
368 for (Node* node : visitor.copies()) { 383 for (Node* node : visitor.copies()) {
369 if (node && node->opcode() == IrOpcode::kFrameState) { 384 if (node && node->opcode() == IrOpcode::kFrameState) {
370 AddClosureToFrameState(node, function); 385 AddClosureToFrameState(node, function);
371 NodeProperties::ReplaceFrameStateInput(node, outer_frame_state); 386 NodeProperties::ReplaceFrameStateInput(node, outer_frame_state);
372 } 387 }
373 } 388 }
374 } 389 }
375 390
376 return inlinee.InlineAtCall(jsgraph_, node); 391 return inlinee.InlineAtCall(jsgraph_, call_node);
377 } 392 }
378 393
379 } // namespace compiler 394 } // namespace compiler
380 } // namespace internal 395 } // namespace internal
381 } // namespace v8 396 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-inlining.h ('k') | test/cctest/compiler/test-control-reducer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698