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

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

Issue 612043003: Add inlining for intrinsics. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Move decls. Created 6 years, 2 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-inlining.h ('k') | src/compiler/js-intrinsic-builder.h » ('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" 5 #include "src/compiler/access-builder.h"
6 #include "src/compiler/ast-graph-builder.h" 6 #include "src/compiler/ast-graph-builder.h"
7 #include "src/compiler/common-operator.h" 7 #include "src/compiler/common-operator.h"
8 #include "src/compiler/generic-node-inl.h" 8 #include "src/compiler/generic-node-inl.h"
9 #include "src/compiler/graph-inl.h" 9 #include "src/compiler/graph-inl.h"
10 #include "src/compiler/graph-visualizer.h" 10 #include "src/compiler/graph-visualizer.h"
11 #include "src/compiler/js-inlining.h" 11 #include "src/compiler/js-inlining.h"
12 #include "src/compiler/js-intrinsic-builder.h"
12 #include "src/compiler/js-operator.h" 13 #include "src/compiler/js-operator.h"
13 #include "src/compiler/node-aux-data-inl.h" 14 #include "src/compiler/node-aux-data-inl.h"
14 #include "src/compiler/node-matchers.h" 15 #include "src/compiler/node-matchers.h"
15 #include "src/compiler/node-properties-inl.h" 16 #include "src/compiler/node-properties-inl.h"
16 #include "src/compiler/simplified-operator.h" 17 #include "src/compiler/simplified-operator.h"
17 #include "src/compiler/typer.h" 18 #include "src/compiler/typer.h"
18 #include "src/full-codegen.h" 19 #include "src/full-codegen.h"
19 #include "src/parser.h" 20 #include "src/parser.h"
20 #include "src/rewriter.h" 21 #include "src/rewriter.h"
21 #include "src/scopes.h" 22 #include "src/scopes.h"
22 23
23 24
24 namespace v8 { 25 namespace v8 {
25 namespace internal { 26 namespace internal {
26 namespace compiler { 27 namespace compiler {
27 28
28 class InlinerVisitor : public NullNodeVisitor { 29 class InlinerVisitor : public NullNodeVisitor {
29 public: 30 public:
30 explicit InlinerVisitor(JSInliner* inliner) : inliner_(inliner) {} 31 explicit InlinerVisitor(JSInliner* inliner) : inliner_(inliner) {}
31 32
32 GenericGraphVisit::Control Post(Node* node) { 33 GenericGraphVisit::Control Post(Node* node) {
33 switch (node->opcode()) { 34 switch (node->opcode()) {
34 case IrOpcode::kJSCallFunction: 35 case IrOpcode::kJSCallFunction:
35 inliner_->TryInlineCall(node); 36 inliner_->TryInlineJSCall(node);
37 break;
38 case IrOpcode::kJSCallRuntime:
39 if (FLAG_turbo_inlining_intrinsics) {
40 inliner_->TryInlineRuntimeCall(node);
41 }
36 break; 42 break;
37 default: 43 default:
38 break; 44 break;
39 } 45 }
40 return GenericGraphVisit::CONTINUE; 46 return GenericGraphVisit::CONTINUE;
41 } 47 }
42 48
43 private: 49 private:
44 JSInliner* inliner_; 50 JSInliner* inliner_;
45 }; 51 };
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 iter.UpdateToAndIncrement(context); 284 iter.UpdateToAndIncrement(context);
279 } else if (NodeProperties::IsControlEdge(iter.edge())) { 285 } else if (NodeProperties::IsControlEdge(iter.edge())) {
280 iter.UpdateToAndIncrement(control); 286 iter.UpdateToAndIncrement(control);
281 } else { 287 } else {
282 UNREACHABLE(); 288 UNREACHABLE();
283 } 289 }
284 break; 290 break;
285 } 291 }
286 } 292 }
287 293
288 // Iterate over all uses of the call node. 294 NodeProperties::ReplaceWithValue(call, value_output(), effect_output());
289 iter = call->uses().begin();
290 while (iter != call->uses().end()) {
291 if (NodeProperties::IsEffectEdge(iter.edge())) {
292 iter.UpdateToAndIncrement(effect_output());
293 } else if (NodeProperties::IsControlEdge(iter.edge())) {
294 UNREACHABLE();
295 } else {
296 DCHECK(NodeProperties::IsValueEdge(iter.edge()));
297 iter.UpdateToAndIncrement(value_output());
298 }
299 }
300 call->RemoveAllInputs(); 295 call->RemoveAllInputs();
301 DCHECK_EQ(0, call->UseCount()); 296 DCHECK_EQ(0, call->UseCount());
302 // TODO(sigurds) Remove this once we copy.
303 unique_return()->RemoveAllInputs();
304 } 297 }
305 298
306 299
307 // TODO(turbofan) Provide such accessors for every node, possibly even 300 // TODO(turbofan) Provide such accessors for every node, possibly even
308 // generate them. 301 // generate them.
309 class JSCallFunctionAccessor { 302 class JSCallFunctionAccessor {
310 public: 303 public:
311 explicit JSCallFunctionAccessor(Node* call) : call_(call) { 304 explicit JSCallFunctionAccessor(Node* call) : call_(call) {
312 DCHECK_EQ(IrOpcode::kJSCallFunction, call->opcode()); 305 DCHECK_EQ(IrOpcode::kJSCallFunction, call->opcode());
313 } 306 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 const Operator* op_param = 354 const Operator* op_param =
362 jsgraph_->common()->StateValues(static_cast<int>(params.size())); 355 jsgraph_->common()->StateValues(static_cast<int>(params.size()));
363 Node* params_node = jsgraph_->graph()->NewNode( 356 Node* params_node = jsgraph_->graph()->NewNode(
364 op_param, static_cast<int>(params.size()), &params.front()); 357 op_param, static_cast<int>(params.size()), &params.front());
365 return jsgraph_->graph()->NewNode(op, params_node, node0, node0, 358 return jsgraph_->graph()->NewNode(op, params_node, node0, node0,
366 jsgraph_->UndefinedConstant(), 359 jsgraph_->UndefinedConstant(),
367 call->frame_state()); 360 call->frame_state());
368 } 361 }
369 362
370 363
371 void JSInliner::TryInlineCall(Node* call_node) { 364 void JSInliner::TryInlineJSCall(Node* call_node) {
372 JSCallFunctionAccessor call(call_node); 365 JSCallFunctionAccessor call(call_node);
373 366
374 HeapObjectMatcher<JSFunction> match(call.jsfunction()); 367 HeapObjectMatcher<JSFunction> match(call.jsfunction());
375 if (!match.HasValue()) { 368 if (!match.HasValue()) {
376 return; 369 return;
377 } 370 }
378 371
379 Handle<JSFunction> function = match.Value().handle(); 372 Handle<JSFunction> function = match.Value().handle();
380 373
381 if (function->shared()->native()) { 374 if (function->shared()->native()) {
382 if (FLAG_trace_turbo_inlining) { 375 if (FLAG_trace_turbo_inlining) {
383 SmartArrayPointer<char> name = 376 SmartArrayPointer<char> name =
384 function->shared()->DebugName()->ToCString(); 377 function->shared()->DebugName()->ToCString();
385 PrintF("Not Inlining %s into %s because inlinee is native\n", name.get(), 378 PrintF("Not Inlining %s into %s because inlinee is native\n", name.get(),
386 info_->shared_info()->DebugName()->ToCString().get()); 379 info_->shared_info()->DebugName()->ToCString().get());
387 } 380 }
388 return; 381 return;
389 } 382 }
390 383
391 CompilationInfoWithZone info(function); 384 CompilationInfoWithZone info(function);
392 Parse(function, &info); 385 Parse(function, &info);
393 386
394 if (info.scope()->arguments() != NULL) { 387 if (info.scope()->arguments() != NULL && info.strict_mode() != STRICT) {
395 // For now do not inline functions that use their arguments array. 388 // For now do not inline functions that use their arguments array.
396 SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString(); 389 SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString();
397 if (FLAG_trace_turbo_inlining) { 390 if (FLAG_trace_turbo_inlining) {
398 PrintF( 391 PrintF(
399 "Not Inlining %s into %s because inlinee uses arguments " 392 "Not Inlining %s into %s because inlinee uses arguments "
400 "array\n", 393 "array\n",
401 name.get(), info_->shared_info()->DebugName()->ToCString().get()); 394 name.get(), info_->shared_info()->DebugName()->ToCString().get());
402 } 395 }
403 return; 396 return;
404 } 397 }
(...skipping 28 matching lines...) Expand all
433 it != visitor.copies().end(); ++it) { 426 it != visitor.copies().end(); ++it) {
434 Node* node = *it; 427 Node* node = *it;
435 if (node != NULL && node->opcode() == IrOpcode::kFrameState) { 428 if (node != NULL && node->opcode() == IrOpcode::kFrameState) {
436 AddClosureToFrameState(node, function); 429 AddClosureToFrameState(node, function);
437 NodeProperties::ReplaceFrameStateInput(node, outer_frame_state); 430 NodeProperties::ReplaceFrameStateInput(node, outer_frame_state);
438 } 431 }
439 } 432 }
440 433
441 inlinee.InlineAtCall(jsgraph_, call_node); 434 inlinee.InlineAtCall(jsgraph_, call_node);
442 } 435 }
436
437
438 class JSCallRuntimeAccessor {
439 public:
440 explicit JSCallRuntimeAccessor(Node* call) : call_(call) {
441 DCHECK_EQ(IrOpcode::kJSCallRuntime, call->opcode());
442 }
443
444 Node* formal_argument(size_t index) {
445 DCHECK(index < formal_arguments());
446 return call_->InputAt(static_cast<int>(index));
447 }
448
449 size_t formal_arguments() {
450 size_t value_inputs = OperatorProperties::GetValueInputCount(call_->op());
451 return value_inputs;
452 }
453
454 Node* frame_state() const {
455 return NodeProperties::GetFrameStateInput(call_);
456 }
457 Node* context() const { return NodeProperties::GetContextInput(call_); }
458 Node* control() const { return NodeProperties::GetControlInput(call_); }
459 Node* effect() const { return NodeProperties::GetEffectInput(call_); }
460
461 const Runtime::Function* function() const {
462 return Runtime::FunctionForId(OpParameter<Runtime::FunctionId>(call_));
463 }
464
465 NodeVector inputs(Zone* zone) const {
466 NodeVector inputs(zone);
467 for (InputIter it = call_->inputs().begin(); it != call_->inputs().end();
468 ++it) {
469 inputs.push_back(*it);
470 }
471 return inputs;
472 }
473
474 private:
475 Node* call_;
476 };
477
478
479 void JSInliner::TryInlineRuntimeCall(Node* call_node) {
480 JSCallRuntimeAccessor call(call_node);
481 const Runtime::Function* f = call.function();
482
483 if (f->intrinsic_type != Runtime::IntrinsicType::INLINE) {
484 return;
485 }
486
487 JSIntrinsicBuilder intrinsic_builder(jsgraph_);
488
489 ResultAndEffect r = intrinsic_builder.BuildGraphFor(
490 f->function_id, call.inputs(jsgraph_->zone()));
491
492 if (r.first != NULL) {
493 if (FLAG_trace_turbo_inlining) {
494 PrintF("Inlining %s into %s\n", f->name,
495 info_->shared_info()->DebugName()->ToCString().get());
496 }
497 NodeProperties::ReplaceWithValue(call_node, r.first, r.second);
498 call_node->RemoveAllInputs();
499 DCHECK_EQ(0, call_node->UseCount());
500 }
501 }
443 } 502 }
444 } 503 }
445 } // namespace v8::internal::compiler 504 } // namespace v8::internal::compiler
OLDNEW
« no previous file with comments | « src/compiler/js-inlining.h ('k') | src/compiler/js-intrinsic-builder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698