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

Unified Diff: src/compiler/js-inlining.cc

Issue 1476833002: [turbofan] Only allocate implict receiver when needed. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Redo correct change. Created 5 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/js-inlining.cc
diff --git a/src/compiler/js-inlining.cc b/src/compiler/js-inlining.cc
index 00c4933802ddf2aa8572cb9293bfc15646ee84c7..0d8b976f45171278768b13d5efe83f1baf8e8e4a 100644
--- a/src/compiler/js-inlining.cc
+++ b/src/compiler/js-inlining.cc
@@ -264,6 +264,18 @@ Node* JSInliner::CreateArtificialFrameState(Node* node, Node* outer_frame_state,
}
+namespace {
+
+// TODO(mstarzinger,verwaest): Move this predicate onto SharedFunctionInfo?
+bool NeedsImplicitReceiver(Handle<JSFunction> function, Isolate* isolate) {
+ Code* construct_stub = function->shared()->construct_stub();
+ return construct_stub != *isolate->builtins()->JSBuiltinsConstructStub() &&
+ construct_stub != *isolate->builtins()->ConstructedNonConstructable();
+}
+
+} // namespace
+
+
Reduction JSInliner::Reduce(Node* node) {
if (!IrOpcode::IsInlineeOpcode(node->opcode())) return NoChange();
@@ -283,18 +295,18 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
DCHECK(IrOpcode::IsInlineeOpcode(node->opcode()));
JSCallAccessor call(node);
+ // Function must be inlineable.
if (!function->shared()->IsInlineable()) {
- // Function must be inlineable.
TRACE("Not inlining %s into %s because callee is not inlineable\n",
function->shared()->DebugName()->ToCString().get(),
info_->shared_info()->DebugName()->ToCString().get());
return NoChange();
}
+ // Constructor must be constructable.
if (node->opcode() == IrOpcode::kJSCallConstruct &&
!function->IsConstructor()) {
- // Constructor must be constructable.
- TRACE("Not inlining %s into %s since constructor is not constructable.\n",
+ TRACE("Not inlining %s into %s because constructor is not constructable.\n",
function->shared()->DebugName()->ToCString().get(),
info_->shared_info()->DebugName()->ToCString().get());
return NoChange();
@@ -302,15 +314,16 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
// Class constructors are callable, but [[Call]] will raise an exception.
// See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
- if (IsClassConstructor(function->shared()->kind())) {
- TRACE("Not inlining %s into %s because callee is classConstructor\n",
+ if (node->opcode() == IrOpcode::kJSCallFunction &&
+ IsClassConstructor(function->shared()->kind())) {
+ TRACE("Not inlining %s into %s because callee is a class constructor.\n",
function->shared()->DebugName()->ToCString().get(),
info_->shared_info()->DebugName()->ToCString().get());
return NoChange();
}
+ // Function contains break points.
if (function->shared()->HasDebugInfo()) {
- // Function contains break points.
TRACE("Not inlining %s into %s because callee may contain break points\n",
function->shared()->DebugName()->ToCString().get(),
info_->shared_info()->DebugName()->ToCString().get());
@@ -424,27 +437,18 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
Node* new_target = jsgraph_->UndefinedConstant();
// Insert nodes around the call that model the behavior required for a
- // constructor dispatch and turn the constructor call into a regular call.
+ // constructor dispatch (allocate implicit receiver and check return value).
// This models the behavior usually accomplished by our {JSConstructStub}.
// Note that the context has to be the callers context (input to call node).
- // TODO(4544): Once we support inlining builtins, make sure no implicit
- // receiver is created for builtins that don't expect any.
- if (node->opcode() == IrOpcode::kJSCallConstruct) {
+ Node* receiver = jsgraph_->UndefinedConstant(); // Implicit receiver.
+ if (node->opcode() == IrOpcode::kJSCallConstruct &&
+ NeedsImplicitReceiver(function, info_->isolate())) {
Node* effect = NodeProperties::GetEffectInput(node);
Node* context = NodeProperties::GetContextInput(node);
Node* create = jsgraph_->graph()->NewNode(jsgraph_->javascript()->Create(),
call.target(), call.new_target(),
context, frame_state, effect);
NodeProperties::ReplaceEffectInput(node, create);
- // TODO(4544): For derived constructors we should not allocate an implicit
- // receiver and also the return value should not be checked afterwards.
- CHECK(!IsClassConstructor(function->shared()->kind()));
- // Swizzle the inputs of the {JSCallConstruct} node to look like inputs to
- // any {JSCallFunction} node so that the rest of the inlining machinery
- // behaves as if we were dealing with a regular function invocation.
- new_target = call.new_target(); // Retrieve new target value input.
- node->RemoveInput(call.formal_arguments() + 1); // Drop new target.
- node->InsertInput(jsgraph_->graph()->zone(), 1, create);
// Insert a check of the return value to determine whether the return value
// or the implicit receiver should be selected as a result of the call.
Node* check = jsgraph_->graph()->NewNode(
@@ -456,6 +460,16 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
NodeProperties::ReplaceValueInput(select, node, 1);
NodeProperties::ReplaceValueInput(check, node, 0);
NodeProperties::ReplaceEffectInput(check, node);
+ receiver = create; // The implicit receiver.
+ }
+
+ // Swizzle the inputs of the {JSCallConstruct} node to look like inputs to a
+ // normal {JSCallFunction} node so that the rest of the inlining machinery
+ // behaves as if we were dealing with a regular function invocation.
+ if (node->opcode() == IrOpcode::kJSCallConstruct) {
+ new_target = call.new_target(); // Retrieve new target value input.
+ node->RemoveInput(call.formal_arguments() + 1); // Drop new target.
+ node->InsertInput(jsgraph_->graph()->zone(), 1, receiver);
// Insert a construct stub frame into the chain of frame states. This will
// reconstruct the proper frame when deoptimizing within the constructor.
frame_state = CreateArtificialFrameState(
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698