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

Side by Side 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 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 | « no previous file | no next file » | 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.h" 7 #include "src/ast.h"
8 #include "src/ast-numbering.h" 8 #include "src/ast-numbering.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 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 const Operator* op_param = 257 const Operator* op_param =
258 jsgraph_->common()->StateValues(static_cast<int>(params.size())); 258 jsgraph_->common()->StateValues(static_cast<int>(params.size()));
259 Node* params_node = jsgraph_->graph()->NewNode( 259 Node* params_node = jsgraph_->graph()->NewNode(
260 op_param, static_cast<int>(params.size()), &params.front()); 260 op_param, static_cast<int>(params.size()), &params.front());
261 return jsgraph_->graph()->NewNode(op, params_node, node0, node0, 261 return jsgraph_->graph()->NewNode(op, params_node, node0, node0,
262 jsgraph_->UndefinedConstant(), 262 jsgraph_->UndefinedConstant(),
263 node->InputAt(0), outer_frame_state); 263 node->InputAt(0), outer_frame_state);
264 } 264 }
265 265
266 266
267 namespace {
268
269 // TODO(mstarzinger,verwaest): Move this predicate onto SharedFunctionInfo?
270 bool NeedsImplicitReceiver(Handle<JSFunction> function, Isolate* isolate) {
271 Code* construct_stub = function->shared()->construct_stub();
272 return construct_stub != *isolate->builtins()->JSBuiltinsConstructStub() &&
273 construct_stub != *isolate->builtins()->ConstructedNonConstructable();
274 }
275
276 } // namespace
277
278
267 Reduction JSInliner::Reduce(Node* node) { 279 Reduction JSInliner::Reduce(Node* node) {
268 if (!IrOpcode::IsInlineeOpcode(node->opcode())) return NoChange(); 280 if (!IrOpcode::IsInlineeOpcode(node->opcode())) return NoChange();
269 281
270 // This reducer can handle both normal function calls as well a constructor 282 // This reducer can handle both normal function calls as well a constructor
271 // calls whenever the target is a constant function object, as follows: 283 // calls whenever the target is a constant function object, as follows:
272 // - JSCallFunction(target:constant, receiver, args...) 284 // - JSCallFunction(target:constant, receiver, args...)
273 // - JSCallConstruct(target:constant, args..., new.target) 285 // - JSCallConstruct(target:constant, args..., new.target)
274 HeapObjectMatcher match(node->InputAt(0)); 286 HeapObjectMatcher match(node->InputAt(0));
275 if (!match.HasValue() || !match.Value()->IsJSFunction()) return NoChange(); 287 if (!match.HasValue() || !match.Value()->IsJSFunction()) return NoChange();
276 Handle<JSFunction> function = Handle<JSFunction>::cast(match.Value()); 288 Handle<JSFunction> function = Handle<JSFunction>::cast(match.Value());
277 289
278 return ReduceJSCall(node, function); 290 return ReduceJSCall(node, function);
279 } 291 }
280 292
281 293
282 Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) { 294 Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
283 DCHECK(IrOpcode::IsInlineeOpcode(node->opcode())); 295 DCHECK(IrOpcode::IsInlineeOpcode(node->opcode()));
284 JSCallAccessor call(node); 296 JSCallAccessor call(node);
285 297
298 // Function must be inlineable.
286 if (!function->shared()->IsInlineable()) { 299 if (!function->shared()->IsInlineable()) {
287 // Function must be inlineable.
288 TRACE("Not inlining %s into %s because callee is not inlineable\n", 300 TRACE("Not inlining %s into %s because callee is not inlineable\n",
289 function->shared()->DebugName()->ToCString().get(), 301 function->shared()->DebugName()->ToCString().get(),
290 info_->shared_info()->DebugName()->ToCString().get()); 302 info_->shared_info()->DebugName()->ToCString().get());
291 return NoChange(); 303 return NoChange();
292 } 304 }
293 305
306 // Constructor must be constructable.
294 if (node->opcode() == IrOpcode::kJSCallConstruct && 307 if (node->opcode() == IrOpcode::kJSCallConstruct &&
295 !function->IsConstructor()) { 308 !function->IsConstructor()) {
296 // Constructor must be constructable. 309 TRACE("Not inlining %s into %s because constructor is not constructable.\n",
297 TRACE("Not inlining %s into %s since constructor is not constructable.\n",
298 function->shared()->DebugName()->ToCString().get(), 310 function->shared()->DebugName()->ToCString().get(),
299 info_->shared_info()->DebugName()->ToCString().get()); 311 info_->shared_info()->DebugName()->ToCString().get());
300 return NoChange(); 312 return NoChange();
301 } 313 }
302 314
303 // Class constructors are callable, but [[Call]] will raise an exception. 315 // Class constructors are callable, but [[Call]] will raise an exception.
304 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ). 316 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
305 if (IsClassConstructor(function->shared()->kind())) { 317 if (node->opcode() == IrOpcode::kJSCallFunction &&
306 TRACE("Not inlining %s into %s because callee is classConstructor\n", 318 IsClassConstructor(function->shared()->kind())) {
319 TRACE("Not inlining %s into %s because callee is a class constructor.\n",
307 function->shared()->DebugName()->ToCString().get(), 320 function->shared()->DebugName()->ToCString().get(),
308 info_->shared_info()->DebugName()->ToCString().get()); 321 info_->shared_info()->DebugName()->ToCString().get());
309 return NoChange(); 322 return NoChange();
310 } 323 }
311 324
325 // Function contains break points.
312 if (function->shared()->HasDebugInfo()) { 326 if (function->shared()->HasDebugInfo()) {
313 // Function contains break points.
314 TRACE("Not inlining %s into %s because callee may contain break points\n", 327 TRACE("Not inlining %s into %s because callee may contain break points\n",
315 function->shared()->DebugName()->ToCString().get(), 328 function->shared()->DebugName()->ToCString().get(),
316 info_->shared_info()->DebugName()->ToCString().get()); 329 info_->shared_info()->DebugName()->ToCString().get());
317 return NoChange(); 330 return NoChange();
318 } 331 }
319 332
320 // Disallow cross native-context inlining for now. This means that all parts 333 // Disallow cross native-context inlining for now. This means that all parts
321 // of the resulting code will operate on the same global object. 334 // of the resulting code will operate on the same global object.
322 // This also prevents cross context leaks for asm.js code, where we could 335 // This also prevents cross context leaks for asm.js code, where we could
323 // inline functions from a different context and hold on to that context (and 336 // inline functions from a different context and hold on to that context (and
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 430
418 CopyVisitor visitor(&graph, jsgraph_->graph(), &zone); 431 CopyVisitor visitor(&graph, jsgraph_->graph(), &zone);
419 visitor.CopyGraph(); 432 visitor.CopyGraph();
420 433
421 Node* start = visitor.GetCopy(graph.start()); 434 Node* start = visitor.GetCopy(graph.start());
422 Node* end = visitor.GetCopy(graph.end()); 435 Node* end = visitor.GetCopy(graph.end());
423 Node* frame_state = call.frame_state_after(); 436 Node* frame_state = call.frame_state_after();
424 Node* new_target = jsgraph_->UndefinedConstant(); 437 Node* new_target = jsgraph_->UndefinedConstant();
425 438
426 // Insert nodes around the call that model the behavior required for a 439 // Insert nodes around the call that model the behavior required for a
427 // constructor dispatch and turn the constructor call into a regular call. 440 // constructor dispatch (allocate implicit receiver and check return value).
428 // This models the behavior usually accomplished by our {JSConstructStub}. 441 // This models the behavior usually accomplished by our {JSConstructStub}.
429 // Note that the context has to be the callers context (input to call node). 442 // Note that the context has to be the callers context (input to call node).
430 // TODO(4544): Once we support inlining builtins, make sure no implicit 443 Node* receiver = jsgraph_->UndefinedConstant(); // Implicit receiver.
431 // receiver is created for builtins that don't expect any. 444 if (node->opcode() == IrOpcode::kJSCallConstruct &&
432 if (node->opcode() == IrOpcode::kJSCallConstruct) { 445 NeedsImplicitReceiver(function, info_->isolate())) {
433 Node* effect = NodeProperties::GetEffectInput(node); 446 Node* effect = NodeProperties::GetEffectInput(node);
434 Node* context = NodeProperties::GetContextInput(node); 447 Node* context = NodeProperties::GetContextInput(node);
435 Node* create = jsgraph_->graph()->NewNode(jsgraph_->javascript()->Create(), 448 Node* create = jsgraph_->graph()->NewNode(jsgraph_->javascript()->Create(),
436 call.target(), call.new_target(), 449 call.target(), call.new_target(),
437 context, frame_state, effect); 450 context, frame_state, effect);
438 NodeProperties::ReplaceEffectInput(node, create); 451 NodeProperties::ReplaceEffectInput(node, create);
439 // TODO(4544): For derived constructors we should not allocate an implicit
440 // receiver and also the return value should not be checked afterwards.
441 CHECK(!IsClassConstructor(function->shared()->kind()));
442 // Swizzle the inputs of the {JSCallConstruct} node to look like inputs to
443 // any {JSCallFunction} node so that the rest of the inlining machinery
444 // behaves as if we were dealing with a regular function invocation.
445 new_target = call.new_target(); // Retrieve new target value input.
446 node->RemoveInput(call.formal_arguments() + 1); // Drop new target.
447 node->InsertInput(jsgraph_->graph()->zone(), 1, create);
448 // Insert a check of the return value to determine whether the return value 452 // Insert a check of the return value to determine whether the return value
449 // or the implicit receiver should be selected as a result of the call. 453 // or the implicit receiver should be selected as a result of the call.
450 Node* check = jsgraph_->graph()->NewNode( 454 Node* check = jsgraph_->graph()->NewNode(
451 jsgraph_->javascript()->CallRuntime(Runtime::kInlineIsSpecObject, 1), 455 jsgraph_->javascript()->CallRuntime(Runtime::kInlineIsSpecObject, 1),
452 node, context, node, start); 456 node, context, node, start);
453 Node* select = jsgraph_->graph()->NewNode( 457 Node* select = jsgraph_->graph()->NewNode(
454 jsgraph_->common()->Select(kMachAnyTagged), check, node, create); 458 jsgraph_->common()->Select(kMachAnyTagged), check, node, create);
455 NodeProperties::ReplaceUses(node, select, check, node, node); 459 NodeProperties::ReplaceUses(node, select, check, node, node);
456 NodeProperties::ReplaceValueInput(select, node, 1); 460 NodeProperties::ReplaceValueInput(select, node, 1);
457 NodeProperties::ReplaceValueInput(check, node, 0); 461 NodeProperties::ReplaceValueInput(check, node, 0);
458 NodeProperties::ReplaceEffectInput(check, node); 462 NodeProperties::ReplaceEffectInput(check, node);
463 receiver = create; // The implicit receiver.
464 }
465
466 // Swizzle the inputs of the {JSCallConstruct} node to look like inputs to a
467 // normal {JSCallFunction} node so that the rest of the inlining machinery
468 // behaves as if we were dealing with a regular function invocation.
469 if (node->opcode() == IrOpcode::kJSCallConstruct) {
470 new_target = call.new_target(); // Retrieve new target value input.
471 node->RemoveInput(call.formal_arguments() + 1); // Drop new target.
472 node->InsertInput(jsgraph_->graph()->zone(), 1, receiver);
459 // Insert a construct stub frame into the chain of frame states. This will 473 // Insert a construct stub frame into the chain of frame states. This will
460 // reconstruct the proper frame when deoptimizing within the constructor. 474 // reconstruct the proper frame when deoptimizing within the constructor.
461 frame_state = CreateArtificialFrameState( 475 frame_state = CreateArtificialFrameState(
462 node, frame_state, call.formal_arguments(), 476 node, frame_state, call.formal_arguments(),
463 FrameStateType::kConstructStub, info.shared_info()); 477 FrameStateType::kConstructStub, info.shared_info());
464 } 478 }
465 479
466 // The inlinee specializes to the context from the JSFunction object. 480 // The inlinee specializes to the context from the JSFunction object.
467 // TODO(turbofan): We might want to load the context from the JSFunction at 481 // TODO(turbofan): We might want to load the context from the JSFunction at
468 // runtime in case we only know the SharedFunctionInfo once we have dynamic 482 // runtime in case we only know the SharedFunctionInfo once we have dynamic
(...skipping 27 matching lines...) Expand all
496 node, frame_state, call.formal_arguments(), 510 node, frame_state, call.formal_arguments(),
497 FrameStateType::kArgumentsAdaptor, info.shared_info()); 511 FrameStateType::kArgumentsAdaptor, info.shared_info());
498 } 512 }
499 513
500 return InlineCall(node, new_target, context, frame_state, start, end); 514 return InlineCall(node, new_target, context, frame_state, start, end);
501 } 515 }
502 516
503 } // namespace compiler 517 } // namespace compiler
504 } // namespace internal 518 } // namespace internal
505 } // namespace v8 519 } // namespace v8
OLDNEW
« 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