OLD | NEW |
---|---|
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-numbering.h" | 7 #include "src/ast/ast-numbering.h" |
8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
9 #include "src/ast/scopes.h" | 9 #include "src/ast/scopes.h" |
10 #include "src/compiler.h" | 10 #include "src/compiler.h" |
11 #include "src/compiler/ast-graph-builder.h" | 11 #include "src/compiler/ast-graph-builder.h" |
12 #include "src/compiler/ast-loop-assignment-analyzer.h" | 12 #include "src/compiler/ast-loop-assignment-analyzer.h" |
13 #include "src/compiler/bytecode-graph-builder.h" | |
13 #include "src/compiler/common-operator.h" | 14 #include "src/compiler/common-operator.h" |
14 #include "src/compiler/graph-reducer.h" | 15 #include "src/compiler/graph-reducer.h" |
15 #include "src/compiler/js-operator.h" | 16 #include "src/compiler/js-operator.h" |
16 #include "src/compiler/node-matchers.h" | 17 #include "src/compiler/node-matchers.h" |
17 #include "src/compiler/node-properties.h" | 18 #include "src/compiler/node-properties.h" |
18 #include "src/compiler/operator-properties.h" | 19 #include "src/compiler/operator-properties.h" |
19 #include "src/compiler/simplified-operator.h" | 20 #include "src/compiler/simplified-operator.h" |
20 #include "src/compiler/type-hint-analyzer.h" | 21 #include "src/compiler/type-hint-analyzer.h" |
21 #include "src/isolate-inl.h" | 22 #include "src/isolate-inl.h" |
22 #include "src/parsing/parse-info.h" | 23 #include "src/parsing/parse-info.h" |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
350 shared_info->DebugName()->ToCString().get(), | 351 shared_info->DebugName()->ToCString().get(), |
351 info_->shared_info()->DebugName()->ToCString().get()); | 352 info_->shared_info()->DebugName()->ToCString().get()); |
352 return NoChange(); | 353 return NoChange(); |
353 } | 354 } |
354 | 355 |
355 Zone zone(info_->isolate()->allocator()); | 356 Zone zone(info_->isolate()->allocator()); |
356 ParseInfo parse_info(&zone, function); | 357 ParseInfo parse_info(&zone, function); |
357 CompilationInfo info(&parse_info, function); | 358 CompilationInfo info(&parse_info, function); |
358 if (info_->is_deoptimization_enabled()) info.MarkAsDeoptimizationEnabled(); | 359 if (info_->is_deoptimization_enabled()) info.MarkAsDeoptimizationEnabled(); |
359 if (info_->is_type_feedback_enabled()) info.MarkAsTypeFeedbackEnabled(); | 360 if (info_->is_type_feedback_enabled()) info.MarkAsTypeFeedbackEnabled(); |
361 if (info_->is_optimizing_from_bytecode()) info.MarkAsOptimizeFromBytecode(); | |
360 | 362 |
361 if (!Compiler::ParseAndAnalyze(info.parse_info())) { | 363 if (info.is_optimizing_from_bytecode() && !Compiler::EnsureBytecode(&info)) { |
364 TRACE("Not inlining %s into %s because bytecode generation failed\n", | |
365 shared_info->DebugName()->ToCString().get(), | |
366 info_->shared_info()->DebugName()->ToCString().get()); | |
367 DCHECK(!info_->isolate()->has_pending_exception()); | |
368 return NoChange(); | |
369 } | |
370 | |
371 if (!info.is_optimizing_from_bytecode() && | |
372 !Compiler::ParseAndAnalyze(info.parse_info())) { | |
362 TRACE("Not inlining %s into %s because parsing failed\n", | 373 TRACE("Not inlining %s into %s because parsing failed\n", |
363 shared_info->DebugName()->ToCString().get(), | 374 shared_info->DebugName()->ToCString().get(), |
364 info_->shared_info()->DebugName()->ToCString().get()); | 375 info_->shared_info()->DebugName()->ToCString().get()); |
365 if (info_->isolate()->has_pending_exception()) { | 376 if (info_->isolate()->has_pending_exception()) { |
366 info_->isolate()->clear_pending_exception(); | 377 info_->isolate()->clear_pending_exception(); |
367 } | 378 } |
368 return NoChange(); | 379 return NoChange(); |
369 } | 380 } |
370 | 381 |
371 if (!Compiler::EnsureDeoptimizationSupport(&info)) { | 382 if (!info.is_optimizing_from_bytecode() && |
383 !Compiler::EnsureDeoptimizationSupport(&info)) { | |
372 TRACE("Not inlining %s into %s because deoptimization support failed\n", | 384 TRACE("Not inlining %s into %s because deoptimization support failed\n", |
373 shared_info->DebugName()->ToCString().get(), | 385 shared_info->DebugName()->ToCString().get(), |
374 info_->shared_info()->DebugName()->ToCString().get()); | 386 info_->shared_info()->DebugName()->ToCString().get()); |
375 return NoChange(); | 387 return NoChange(); |
376 } | 388 } |
377 | 389 |
378 // Remember that we inlined this function. This needs to be called right | 390 // Remember that we inlined this function. This needs to be called right |
379 // after we ensure deoptimization support so that the code flusher | 391 // after we ensure deoptimization support so that the code flusher |
380 // does not remove the code with the deoptimization support. | 392 // does not remove the code with the deoptimization support. |
381 info_->AddInlinedFunction(shared_info); | 393 info_->AddInlinedFunction(shared_info); |
382 | 394 |
383 // ---------------------------------------------------------------- | 395 // ---------------------------------------------------------------- |
384 // After this point, we've made a decision to inline this function. | 396 // After this point, we've made a decision to inline this function. |
385 // We shall not bailout from inlining if we got here. | 397 // We shall not bailout from inlining if we got here. |
386 | 398 |
387 TRACE("Inlining %s into %s\n", | 399 TRACE("Inlining %s into %s\n", |
388 shared_info->DebugName()->ToCString().get(), | 400 shared_info->DebugName()->ToCString().get(), |
389 info_->shared_info()->DebugName()->ToCString().get()); | 401 info_->shared_info()->DebugName()->ToCString().get()); |
390 | 402 |
391 // If function was lazily compiled, it's literals array may not yet be set up. | 403 // If function was lazily compiled, it's literals array may not yet be set up. |
392 JSFunction::EnsureLiterals(function); | 404 JSFunction::EnsureLiterals(function); |
393 | 405 |
394 // Create the subgraph for the inlinee. | 406 // Create the subgraph for the inlinee. |
395 Node* start; | 407 Node* start; |
396 Node* end; | 408 Node* end; |
397 { | 409 if (info.is_optimizing_from_bytecode()) { |
410 // Run the BytecodeGraphBuilder to create the subgraph. | |
411 Graph::SubgraphScope scope(graph()); | |
412 BytecodeGraphBuilder graph_builder(&zone, &info, jsgraph()); | |
413 graph_builder.CreateGraph(); | |
414 | |
rmcilroy
2016/08/25 08:53:26
Do we want todos about the loop analysis and Tyler
Michael Starzinger
2016/08/25 09:01:26
The LoopAssignmentAnalyzer is an AST-based analysi
rmcilroy
2016/08/25 09:33:06
Makes sense, thanks for the explanation.
rmcilroy
2016/08/25 09:33:06
Makes sense, thanks for the explanation.
| |
415 // Extract the inlinee start/end nodes. | |
416 start = graph()->start(); | |
417 end = graph()->end(); | |
418 } else { | |
398 // Run the loop assignment analyzer on the inlinee. | 419 // Run the loop assignment analyzer on the inlinee. |
399 AstLoopAssignmentAnalyzer loop_assignment_analyzer(&zone, &info); | 420 AstLoopAssignmentAnalyzer loop_assignment_analyzer(&zone, &info); |
400 LoopAssignmentAnalysis* loop_assignment = | 421 LoopAssignmentAnalysis* loop_assignment = |
401 loop_assignment_analyzer.Analyze(); | 422 loop_assignment_analyzer.Analyze(); |
402 | 423 |
403 // Run the type hint analyzer on the inlinee. | 424 // Run the type hint analyzer on the inlinee. |
404 TypeHintAnalyzer type_hint_analyzer(&zone); | 425 TypeHintAnalyzer type_hint_analyzer(&zone); |
405 TypeHintAnalysis* type_hint_analysis = | 426 TypeHintAnalysis* type_hint_analysis = |
406 type_hint_analyzer.Analyze(handle(shared_info->code(), info.isolate())); | 427 type_hint_analyzer.Analyze(handle(shared_info->code(), info.isolate())); |
407 | 428 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
468 // type feedback in the compiler. | 489 // type feedback in the compiler. |
469 Node* context = jsgraph()->Constant(handle(function->context())); | 490 Node* context = jsgraph()->Constant(handle(function->context())); |
470 | 491 |
471 // Insert a JSConvertReceiver node for sloppy callees. Note that the context | 492 // Insert a JSConvertReceiver node for sloppy callees. Note that the context |
472 // passed into this node has to be the callees context (loaded above). Note | 493 // passed into this node has to be the callees context (loaded above). Note |
473 // that the frame state passed to the JSConvertReceiver must be the frame | 494 // that the frame state passed to the JSConvertReceiver must be the frame |
474 // state _before_ the call; it is not necessary to fiddle with the receiver | 495 // state _before_ the call; it is not necessary to fiddle with the receiver |
475 // in that frame state tho, as the conversion of the receiver can be repeated | 496 // in that frame state tho, as the conversion of the receiver can be repeated |
476 // any number of times, it's not observable. | 497 // any number of times, it's not observable. |
477 if (node->opcode() == IrOpcode::kJSCallFunction && | 498 if (node->opcode() == IrOpcode::kJSCallFunction && |
478 is_sloppy(parse_info.language_mode()) && !shared_info->native()) { | 499 is_sloppy(shared_info->language_mode()) && !shared_info->native()) { |
479 const CallFunctionParameters& p = CallFunctionParametersOf(node->op()); | 500 const CallFunctionParameters& p = CallFunctionParametersOf(node->op()); |
480 Node* frame_state_before = NodeProperties::FindFrameStateBefore(node); | 501 Node* frame_state_before = NodeProperties::FindFrameStateBefore(node); |
481 Node* effect = NodeProperties::GetEffectInput(node); | 502 Node* effect = NodeProperties::GetEffectInput(node); |
482 Node* convert = graph()->NewNode( | 503 Node* convert = graph()->NewNode( |
483 javascript()->ConvertReceiver(p.convert_mode()), call.receiver(), | 504 javascript()->ConvertReceiver(p.convert_mode()), call.receiver(), |
484 context, frame_state_before, effect, start); | 505 context, frame_state_before, effect, start); |
485 NodeProperties::ReplaceValueInput(node, convert, 1); | 506 NodeProperties::ReplaceValueInput(node, convert, 1); |
486 NodeProperties::ReplaceEffectInput(node, convert); | 507 NodeProperties::ReplaceEffectInput(node, convert); |
487 } | 508 } |
488 | 509 |
489 // If we are inlining a JS call at tail position then we have to pop current | 510 // If we are inlining a JS call at tail position then we have to pop current |
490 // frame state and its potential arguments adaptor frame state in order to | 511 // frame state and its potential arguments adaptor frame state in order to |
491 // make the call stack be consistent with non-inlining case. | 512 // make the call stack be consistent with non-inlining case. |
492 // After that we add a tail caller frame state which lets deoptimizer handle | 513 // After that we add a tail caller frame state which lets deoptimizer handle |
493 // the case when the outermost function inlines a tail call (it should remove | 514 // the case when the outermost function inlines a tail call (it should remove |
494 // potential arguments adaptor frame that belongs to outermost function when | 515 // potential arguments adaptor frame that belongs to outermost function when |
495 // deopt happens). | 516 // deopt happens). |
496 if (node->opcode() == IrOpcode::kJSCallFunction) { | 517 if (node->opcode() == IrOpcode::kJSCallFunction) { |
497 const CallFunctionParameters& p = CallFunctionParametersOf(node->op()); | 518 const CallFunctionParameters& p = CallFunctionParametersOf(node->op()); |
498 if (p.tail_call_mode() == TailCallMode::kAllow) { | 519 if (p.tail_call_mode() == TailCallMode::kAllow) { |
499 frame_state = CreateTailCallerFrameState(node, frame_state); | 520 frame_state = CreateTailCallerFrameState(node, frame_state); |
500 } | 521 } |
501 } | 522 } |
502 | 523 |
503 // Insert argument adaptor frame if required. The callees formal parameter | 524 // Insert argument adaptor frame if required. The callees formal parameter |
504 // count (i.e. value outputs of start node minus target, receiver, new target, | 525 // count (i.e. value outputs of start node minus target, receiver, new target, |
505 // arguments count and context) have to match the number of arguments passed | 526 // arguments count and context) have to match the number of arguments passed |
506 // to the call. | 527 // to the call. |
507 int parameter_count = info.literal()->parameter_count(); | 528 int parameter_count = shared_info->internal_formal_parameter_count(); |
508 DCHECK_EQ(parameter_count, start->op()->ValueOutputCount() - 5); | 529 DCHECK_EQ(parameter_count, start->op()->ValueOutputCount() - 5); |
509 if (call.formal_arguments() != parameter_count) { | 530 if (call.formal_arguments() != parameter_count) { |
510 frame_state = CreateArtificialFrameState( | 531 frame_state = CreateArtificialFrameState( |
511 node, frame_state, call.formal_arguments(), | 532 node, frame_state, call.formal_arguments(), |
512 FrameStateType::kArgumentsAdaptor, shared_info); | 533 FrameStateType::kArgumentsAdaptor, shared_info); |
513 } | 534 } |
514 | 535 |
515 return InlineCall(node, new_target, context, frame_state, start, end); | 536 return InlineCall(node, new_target, context, frame_state, start, end); |
516 } | 537 } |
517 | 538 |
518 Graph* JSInliner::graph() const { return jsgraph()->graph(); } | 539 Graph* JSInliner::graph() const { return jsgraph()->graph(); } |
519 | 540 |
520 JSOperatorBuilder* JSInliner::javascript() const { | 541 JSOperatorBuilder* JSInliner::javascript() const { |
521 return jsgraph()->javascript(); | 542 return jsgraph()->javascript(); |
522 } | 543 } |
523 | 544 |
524 CommonOperatorBuilder* JSInliner::common() const { return jsgraph()->common(); } | 545 CommonOperatorBuilder* JSInliner::common() const { return jsgraph()->common(); } |
525 | 546 |
526 SimplifiedOperatorBuilder* JSInliner::simplified() const { | 547 SimplifiedOperatorBuilder* JSInliner::simplified() const { |
527 return jsgraph()->simplified(); | 548 return jsgraph()->simplified(); |
528 } | 549 } |
529 | 550 |
530 } // namespace compiler | 551 } // namespace compiler |
531 } // namespace internal | 552 } // namespace internal |
532 } // namespace v8 | 553 } // namespace v8 |
OLD | NEW |