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

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

Issue 2662263002: [turbo] Rename CallConstruct* operators to Construct*. (Closed)
Patch Set: Created 3 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-generic-lowering.cc ('k') | src/compiler/js-inlining-heuristic.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" 5 #include "src/compiler/js-inlining.h"
6 6
7 #include "src/ast/ast.h" 7 #include "src/ast/ast.h"
8 #include "src/compilation-info.h" 8 #include "src/compilation-info.h"
9 #include "src/compiler.h" 9 #include "src/compiler.h"
10 #include "src/compiler/all-nodes.h" 10 #include "src/compiler/all-nodes.h"
(...skipping 13 matching lines...) Expand all
24 namespace internal { 24 namespace internal {
25 namespace compiler { 25 namespace compiler {
26 26
27 #define TRACE(...) \ 27 #define TRACE(...) \
28 do { \ 28 do { \
29 if (FLAG_trace_turbo_inlining) PrintF(__VA_ARGS__); \ 29 if (FLAG_trace_turbo_inlining) PrintF(__VA_ARGS__); \
30 } while (false) 30 } while (false)
31 31
32 32
33 // Provides convenience accessors for the common layout of nodes having either 33 // Provides convenience accessors for the common layout of nodes having either
34 // the {JSCallFunction} or the {JSCallConstruct} operator. 34 // the {JSCallFunction} or the {JSConstruct} operator.
35 class JSCallAccessor { 35 class JSCallAccessor {
36 public: 36 public:
37 explicit JSCallAccessor(Node* call) : call_(call) { 37 explicit JSCallAccessor(Node* call) : call_(call) {
38 DCHECK(call->opcode() == IrOpcode::kJSCallFunction || 38 DCHECK(call->opcode() == IrOpcode::kJSCallFunction ||
39 call->opcode() == IrOpcode::kJSCallConstruct); 39 call->opcode() == IrOpcode::kJSConstruct);
40 } 40 }
41 41
42 Node* target() { 42 Node* target() {
43 // Both, {JSCallFunction} and {JSCallConstruct}, have same layout here. 43 // Both, {JSCallFunction} and {JSConstruct}, have same layout here.
44 return call_->InputAt(0); 44 return call_->InputAt(0);
45 } 45 }
46 46
47 Node* receiver() { 47 Node* receiver() {
48 DCHECK_EQ(IrOpcode::kJSCallFunction, call_->opcode()); 48 DCHECK_EQ(IrOpcode::kJSCallFunction, call_->opcode());
49 return call_->InputAt(1); 49 return call_->InputAt(1);
50 } 50 }
51 51
52 Node* new_target() { 52 Node* new_target() {
53 DCHECK_EQ(IrOpcode::kJSCallConstruct, call_->opcode()); 53 DCHECK_EQ(IrOpcode::kJSConstruct, call_->opcode());
54 return call_->InputAt(formal_arguments() + 1); 54 return call_->InputAt(formal_arguments() + 1);
55 } 55 }
56 56
57 Node* frame_state() { 57 Node* frame_state() {
58 // Both, {JSCallFunction} and {JSCallConstruct}, have frame state. 58 // Both, {JSCallFunction} and {JSConstruct}, have frame state.
59 return NodeProperties::GetFrameStateInput(call_); 59 return NodeProperties::GetFrameStateInput(call_);
60 } 60 }
61 61
62 int formal_arguments() { 62 int formal_arguments() {
63 // Both, {JSCallFunction} and {JSCallConstruct}, have two extra inputs: 63 // Both, {JSCallFunction} and {JSConstruct}, have two extra inputs:
64 // - JSCallConstruct: Includes target function and new target. 64 // - JSConstruct: Includes target function and new target.
65 // - JSCallFunction: Includes target function and receiver. 65 // - JSCallFunction: Includes target function and receiver.
66 return call_->op()->ValueInputCount() - 2; 66 return call_->op()->ValueInputCount() - 2;
67 } 67 }
68 68
69 float frequency() const { 69 float frequency() const {
70 return (call_->opcode() == IrOpcode::kJSCallFunction) 70 return (call_->opcode() == IrOpcode::kJSCallFunction)
71 ? CallFunctionParametersOf(call_->op()).frequency() 71 ? CallFunctionParametersOf(call_->op()).frequency()
72 : CallConstructParametersOf(call_->op()).frequency(); 72 : ConstructParametersOf(call_->op()).frequency();
73 } 73 }
74 74
75 private: 75 private:
76 Node* call_; 76 Node* call_;
77 }; 77 };
78 78
79 Reduction JSInliner::InlineCall(Node* call, Node* new_target, Node* context, 79 Reduction JSInliner::InlineCall(Node* call, Node* new_target, Node* context,
80 Node* frame_state, Node* start, Node* end, 80 Node* frame_state, Node* start, Node* end,
81 Node* exception_target, 81 Node* exception_target,
82 const NodeVector& uncaught_subcalls) { 82 const NodeVector& uncaught_subcalls) {
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 347
348 } // namespace 348 } // namespace
349 349
350 350
351 Reduction JSInliner::Reduce(Node* node) { 351 Reduction JSInliner::Reduce(Node* node) {
352 if (!IrOpcode::IsInlineeOpcode(node->opcode())) return NoChange(); 352 if (!IrOpcode::IsInlineeOpcode(node->opcode())) return NoChange();
353 353
354 // This reducer can handle both normal function calls as well a constructor 354 // This reducer can handle both normal function calls as well a constructor
355 // calls whenever the target is a constant function object, as follows: 355 // calls whenever the target is a constant function object, as follows:
356 // - JSCallFunction(target:constant, receiver, args...) 356 // - JSCallFunction(target:constant, receiver, args...)
357 // - JSCallConstruct(target:constant, args..., new.target) 357 // - JSConstruct(target:constant, args..., new.target)
358 HeapObjectMatcher match(node->InputAt(0)); 358 HeapObjectMatcher match(node->InputAt(0));
359 if (!match.HasValue() || !match.Value()->IsJSFunction()) return NoChange(); 359 if (!match.HasValue() || !match.Value()->IsJSFunction()) return NoChange();
360 Handle<JSFunction> function = Handle<JSFunction>::cast(match.Value()); 360 Handle<JSFunction> function = Handle<JSFunction>::cast(match.Value());
361 361
362 return ReduceJSCall(node, function); 362 return ReduceJSCall(node, function);
363 } 363 }
364 364
365 Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) { 365 Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
366 DCHECK(IrOpcode::IsInlineeOpcode(node->opcode())); 366 DCHECK(IrOpcode::IsInlineeOpcode(node->opcode()));
367 JSCallAccessor call(node); 367 JSCallAccessor call(node);
368 Handle<SharedFunctionInfo> shared_info(function->shared()); 368 Handle<SharedFunctionInfo> shared_info(function->shared());
369 369
370 // Inlining is only supported in the bytecode pipeline. 370 // Inlining is only supported in the bytecode pipeline.
371 if (!info_->is_optimizing_from_bytecode()) { 371 if (!info_->is_optimizing_from_bytecode()) {
372 TRACE("Inlining %s into %s is not supported in the deprecated pipeline\n", 372 TRACE("Inlining %s into %s is not supported in the deprecated pipeline\n",
373 shared_info->DebugName()->ToCString().get(), 373 shared_info->DebugName()->ToCString().get(),
374 info_->shared_info()->DebugName()->ToCString().get()); 374 info_->shared_info()->DebugName()->ToCString().get());
375 return NoChange(); 375 return NoChange();
376 } 376 }
377 377
378 // Function must be inlineable. 378 // Function must be inlineable.
379 if (!shared_info->IsInlineable()) { 379 if (!shared_info->IsInlineable()) {
380 TRACE("Not inlining %s into %s because callee is not inlineable\n", 380 TRACE("Not inlining %s into %s because callee is not inlineable\n",
381 shared_info->DebugName()->ToCString().get(), 381 shared_info->DebugName()->ToCString().get(),
382 info_->shared_info()->DebugName()->ToCString().get()); 382 info_->shared_info()->DebugName()->ToCString().get());
383 return NoChange(); 383 return NoChange();
384 } 384 }
385 385
386 // Constructor must be constructable. 386 // Constructor must be constructable.
387 if (node->opcode() == IrOpcode::kJSCallConstruct && 387 if (node->opcode() == IrOpcode::kJSConstruct &&
388 IsNonConstructible(shared_info)) { 388 IsNonConstructible(shared_info)) {
389 TRACE("Not inlining %s into %s because constructor is not constructable.\n", 389 TRACE("Not inlining %s into %s because constructor is not constructable.\n",
390 shared_info->DebugName()->ToCString().get(), 390 shared_info->DebugName()->ToCString().get(),
391 info_->shared_info()->DebugName()->ToCString().get()); 391 info_->shared_info()->DebugName()->ToCString().get());
392 return NoChange(); 392 return NoChange();
393 } 393 }
394 394
395 // Class constructors are callable, but [[Call]] will raise an exception. 395 // Class constructors are callable, but [[Call]] will raise an exception.
396 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ). 396 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
397 if (node->opcode() == IrOpcode::kJSCallFunction && 397 if (node->opcode() == IrOpcode::kJSCallFunction &&
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 if (!hasIfException) { 543 if (!hasIfException) {
544 DCHECK_EQ(2, subnode->op()->ControlOutputCount()); 544 DCHECK_EQ(2, subnode->op()->ControlOutputCount());
545 uncaught_subcalls.push_back(subnode); 545 uncaught_subcalls.push_back(subnode);
546 } 546 }
547 } 547 }
548 } 548 }
549 549
550 Node* frame_state = call.frame_state(); 550 Node* frame_state = call.frame_state();
551 Node* new_target = jsgraph()->UndefinedConstant(); 551 Node* new_target = jsgraph()->UndefinedConstant();
552 552
553 // Inline {JSCallConstruct} requires some additional magic. 553 // Inline {JSConstruct} requires some additional magic.
554 if (node->opcode() == IrOpcode::kJSCallConstruct) { 554 if (node->opcode() == IrOpcode::kJSConstruct) {
555 // Insert nodes around the call that model the behavior required for a 555 // Insert nodes around the call that model the behavior required for a
556 // constructor dispatch (allocate implicit receiver and check return value). 556 // constructor dispatch (allocate implicit receiver and check return value).
557 // This models the behavior usually accomplished by our {JSConstructStub}. 557 // This models the behavior usually accomplished by our {JSConstructStub}.
558 // Note that the context has to be the callers context (input to call node). 558 // Note that the context has to be the callers context (input to call node).
559 Node* receiver = jsgraph()->TheHoleConstant(); // Implicit receiver. 559 Node* receiver = jsgraph()->TheHoleConstant(); // Implicit receiver.
560 if (NeedsImplicitReceiver(shared_info)) { 560 if (NeedsImplicitReceiver(shared_info)) {
561 Node* frame_state_before = NodeProperties::FindFrameStateBefore(node); 561 Node* frame_state_before = NodeProperties::FindFrameStateBefore(node);
562 Node* effect = NodeProperties::GetEffectInput(node); 562 Node* effect = NodeProperties::GetEffectInput(node);
563 Node* context = NodeProperties::GetContextInput(node); 563 Node* context = NodeProperties::GetContextInput(node);
564 Node* create = graph()->NewNode(javascript()->Create(), call.target(), 564 Node* create = graph()->NewNode(javascript()->Create(), call.target(),
565 call.new_target(), context, 565 call.new_target(), context,
566 frame_state_before, effect); 566 frame_state_before, effect);
567 NodeProperties::ReplaceEffectInput(node, create); 567 NodeProperties::ReplaceEffectInput(node, create);
568 // Insert a check of the return value to determine whether the return 568 // Insert a check of the return value to determine whether the return
569 // value or the implicit receiver should be selected as a result of the 569 // value or the implicit receiver should be selected as a result of the
570 // call. 570 // call.
571 Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), node); 571 Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), node);
572 Node* select = 572 Node* select =
573 graph()->NewNode(common()->Select(MachineRepresentation::kTagged), 573 graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
574 check, node, create); 574 check, node, create);
575 NodeProperties::ReplaceUses(node, select, node, node, node); 575 NodeProperties::ReplaceUses(node, select, node, node, node);
576 // Fix-up inputs that have been mangled by the {ReplaceUses} call above. 576 // Fix-up inputs that have been mangled by the {ReplaceUses} call above.
577 NodeProperties::ReplaceValueInput(select, node, 1); // Fix-up input. 577 NodeProperties::ReplaceValueInput(select, node, 1); // Fix-up input.
578 NodeProperties::ReplaceValueInput(check, node, 0); // Fix-up input. 578 NodeProperties::ReplaceValueInput(check, node, 0); // Fix-up input.
579 receiver = create; // The implicit receiver. 579 receiver = create; // The implicit receiver.
580 } 580 }
581 581
582 // Swizzle the inputs of the {JSCallConstruct} node to look like inputs to a 582 // Swizzle the inputs of the {JSConstruct} node to look like inputs to a
583 // normal {JSCallFunction} node so that the rest of the inlining machinery 583 // normal {JSCallFunction} node so that the rest of the inlining machinery
584 // behaves as if we were dealing with a regular function invocation. 584 // behaves as if we were dealing with a regular function invocation.
585 new_target = call.new_target(); // Retrieve new target value input. 585 new_target = call.new_target(); // Retrieve new target value input.
586 node->RemoveInput(call.formal_arguments() + 1); // Drop new target. 586 node->RemoveInput(call.formal_arguments() + 1); // Drop new target.
587 node->InsertInput(graph()->zone(), 1, receiver); 587 node->InsertInput(graph()->zone(), 1, receiver);
588 588
589 // Insert a construct stub frame into the chain of frame states. This will 589 // Insert a construct stub frame into the chain of frame states. This will
590 // reconstruct the proper frame when deoptimizing within the constructor. 590 // reconstruct the proper frame when deoptimizing within the constructor.
591 frame_state = CreateArtificialFrameState( 591 frame_state = CreateArtificialFrameState(
592 node, frame_state, call.formal_arguments(), 592 node, frame_state, call.formal_arguments(),
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 657
658 CommonOperatorBuilder* JSInliner::common() const { return jsgraph()->common(); } 658 CommonOperatorBuilder* JSInliner::common() const { return jsgraph()->common(); }
659 659
660 SimplifiedOperatorBuilder* JSInliner::simplified() const { 660 SimplifiedOperatorBuilder* JSInliner::simplified() const {
661 return jsgraph()->simplified(); 661 return jsgraph()->simplified();
662 } 662 }
663 663
664 } // namespace compiler 664 } // namespace compiler
665 } // namespace internal 665 } // namespace internal
666 } // namespace v8 666 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-generic-lowering.cc ('k') | src/compiler/js-inlining-heuristic.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698