OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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.h" | 5 #include "src/compiler.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "src/ast/ast-numbering.h" | 9 #include "src/ast/ast-numbering.h" |
10 #include "src/ast/prettyprinter.h" | 10 #include "src/ast/prettyprinter.h" |
11 #include "src/ast/scopeinfo.h" | 11 #include "src/ast/scopeinfo.h" |
12 #include "src/ast/scopes.h" | 12 #include "src/ast/scopes.h" |
13 #include "src/bootstrapper.h" | 13 #include "src/bootstrapper.h" |
14 #include "src/codegen.h" | 14 #include "src/codegen.h" |
15 #include "src/compilation-cache.h" | 15 #include "src/compilation-cache.h" |
16 #include "src/compiler/pipeline.h" | 16 #include "src/compiler/pipeline.h" |
17 #include "src/crankshaft/hydrogen.h" | 17 #include "src/crankshaft/hydrogen.h" |
18 #include "src/crankshaft/lithium.h" | |
19 #include "src/crankshaft/typing.h" | |
20 #include "src/debug/debug.h" | 18 #include "src/debug/debug.h" |
21 #include "src/debug/liveedit.h" | 19 #include "src/debug/liveedit.h" |
22 #include "src/deoptimizer.h" | 20 #include "src/deoptimizer.h" |
23 #include "src/full-codegen/full-codegen.h" | 21 #include "src/full-codegen/full-codegen.h" |
24 #include "src/gdb-jit.h" | |
25 #include "src/interpreter/interpreter.h" | 22 #include "src/interpreter/interpreter.h" |
26 #include "src/isolate-inl.h" | 23 #include "src/isolate-inl.h" |
27 #include "src/log-inl.h" | 24 #include "src/log-inl.h" |
28 #include "src/messages.h" | 25 #include "src/messages.h" |
29 #include "src/parsing/parser.h" | 26 #include "src/parsing/parser.h" |
30 #include "src/parsing/rewriter.h" | 27 #include "src/parsing/rewriter.h" |
31 #include "src/parsing/scanner-character-streams.h" | 28 #include "src/parsing/scanner-character-streams.h" |
32 #include "src/profiler/cpu-profiler.h" | 29 #include "src/profiler/cpu-profiler.h" |
33 #include "src/runtime-profiler.h" | 30 #include "src/runtime-profiler.h" |
34 #include "src/snapshot/code-serializer.h" | 31 #include "src/snapshot/code-serializer.h" |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 DisableFutureOptimization(); | 92 DisableFutureOptimization(); |
96 dependencies()->Rollback(); | 93 dependencies()->Rollback(); |
97 delete parse_info_; | 94 delete parse_info_; |
98 parse_info_ = nullptr; | 95 parse_info_ = nullptr; |
99 } | 96 } |
100 | 97 |
101 private: | 98 private: |
102 Zone zone_; | 99 Zone zone_; |
103 }; | 100 }; |
104 | 101 |
| 102 // Helper that times a scoped region and records the elapsed time. |
| 103 struct ScopedTimer { |
| 104 explicit ScopedTimer(base::TimeDelta* location) : location_(location) { |
| 105 DCHECK(location_ != NULL); |
| 106 timer_.Start(); |
| 107 } |
| 108 |
| 109 ~ScopedTimer() { *location_ += timer_.Elapsed(); } |
| 110 |
| 111 base::ElapsedTimer timer_; |
| 112 base::TimeDelta* location_; |
| 113 }; |
| 114 |
105 // ---------------------------------------------------------------------------- | 115 // ---------------------------------------------------------------------------- |
106 // Implementation of CompilationInfo | 116 // Implementation of CompilationInfo |
107 | 117 |
108 bool CompilationInfo::has_shared_info() const { | 118 bool CompilationInfo::has_shared_info() const { |
109 return parse_info_ && !parse_info_->shared_info().is_null(); | 119 return parse_info_ && !parse_info_->shared_info().is_null(); |
110 } | 120 } |
111 | 121 |
112 | 122 |
113 bool CompilationInfo::has_context() const { | 123 bool CompilationInfo::has_context() const { |
114 return parse_info_ && !parse_info_->context().is_null(); | 124 return parse_info_ && !parse_info_->context().is_null(); |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 #if DEBUG | 309 #if DEBUG |
300 void CompilationInfo::PrintAstForTesting() { | 310 void CompilationInfo::PrintAstForTesting() { |
301 PrintF("--- Source from AST ---\n%s\n", | 311 PrintF("--- Source from AST ---\n%s\n", |
302 PrettyPrinter(isolate()).PrintProgram(literal())); | 312 PrettyPrinter(isolate()).PrintProgram(literal())); |
303 } | 313 } |
304 #endif | 314 #endif |
305 | 315 |
306 // ---------------------------------------------------------------------------- | 316 // ---------------------------------------------------------------------------- |
307 // Implementation of OptimizedCompileJob | 317 // Implementation of OptimizedCompileJob |
308 | 318 |
309 class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder { | |
310 public: | |
311 explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info) | |
312 : HOptimizedGraphBuilder(info) { | |
313 } | |
314 | |
315 #define DEF_VISIT(type) \ | |
316 void Visit##type(type* node) override { \ | |
317 SourcePosition old_position = SourcePosition::Unknown(); \ | |
318 if (node->position() != RelocInfo::kNoPosition) { \ | |
319 old_position = source_position(); \ | |
320 SetSourcePosition(node->position()); \ | |
321 } \ | |
322 HOptimizedGraphBuilder::Visit##type(node); \ | |
323 if (!old_position.IsUnknown()) { \ | |
324 set_source_position(old_position); \ | |
325 } \ | |
326 } | |
327 EXPRESSION_NODE_LIST(DEF_VISIT) | |
328 #undef DEF_VISIT | |
329 | |
330 #define DEF_VISIT(type) \ | |
331 void Visit##type(type* node) override { \ | |
332 SourcePosition old_position = SourcePosition::Unknown(); \ | |
333 if (node->position() != RelocInfo::kNoPosition) { \ | |
334 old_position = source_position(); \ | |
335 SetSourcePosition(node->position()); \ | |
336 } \ | |
337 HOptimizedGraphBuilder::Visit##type(node); \ | |
338 if (!old_position.IsUnknown()) { \ | |
339 set_source_position(old_position); \ | |
340 } \ | |
341 } | |
342 STATEMENT_NODE_LIST(DEF_VISIT) | |
343 #undef DEF_VISIT | |
344 | |
345 #define DEF_VISIT(type) \ | |
346 void Visit##type(type* node) override { \ | |
347 HOptimizedGraphBuilder::Visit##type(node); \ | |
348 } | |
349 DECLARATION_NODE_LIST(DEF_VISIT) | |
350 #undef DEF_VISIT | |
351 }; | |
352 | |
353 | |
354 OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() { | 319 OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() { |
355 DCHECK(info()->IsOptimizing()); | 320 DCHECK(info()->IsOptimizing()); |
356 | 321 |
357 // Do not use Crankshaft/TurboFan if we need to be able to set break points. | 322 // Do not use Crankshaft/TurboFan if we need to be able to set break points. |
358 if (info()->shared_info()->HasDebugInfo()) { | 323 if (info()->shared_info()->HasDebugInfo()) { |
359 return AbortOptimization(kFunctionBeingDebugged); | 324 return AbortOptimization(kFunctionBeingDebugged); |
360 } | 325 } |
361 | 326 |
362 // Limit the number of times we try to optimize functions. | 327 // Limit the number of times we try to optimize functions. |
363 const int kMaxOptCount = | 328 const int kMaxOptCount = |
(...skipping 22 matching lines...) Expand all Loading... |
386 return SetLastStatus(FAILED); | 351 return SetLastStatus(FAILED); |
387 } | 352 } |
388 if (FLAG_hydrogen_stats) { | 353 if (FLAG_hydrogen_stats) { |
389 isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed()); | 354 isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed()); |
390 } | 355 } |
391 } | 356 } |
392 | 357 |
393 DCHECK(info()->shared_info()->has_deoptimization_support()); | 358 DCHECK(info()->shared_info()->has_deoptimization_support()); |
394 DCHECK(!info()->is_first_compile()); | 359 DCHECK(!info()->is_first_compile()); |
395 | 360 |
396 bool optimization_disabled = info()->shared_info()->optimization_disabled(); | 361 // Delegate to the underlying implementation. |
397 bool dont_crankshaft = info()->shared_info()->dont_crankshaft(); | 362 DCHECK_EQ(SUCCEEDED, last_status()); |
398 | 363 ScopedTimer t(&time_taken_to_create_graph_); |
399 // Check the enabling conditions for Turbofan. | 364 return SetLastStatus(CreateGraphImpl()); |
400 // 1. "use asm" code. | |
401 bool is_turbofanable_asm = FLAG_turbo_asm && | |
402 info()->shared_info()->asm_function() && | |
403 !optimization_disabled; | |
404 | |
405 // 2. Fallback for features unsupported by Crankshaft. | |
406 bool is_unsupported_by_crankshaft_but_turbofanable = | |
407 dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 && | |
408 !optimization_disabled; | |
409 | |
410 // 3. Explicitly enabled by the command-line filter. | |
411 bool passes_turbo_filter = | |
412 info()->shared_info()->PassesFilter(FLAG_turbo_filter); | |
413 | |
414 // If this is OSR request, OSR must be enabled by Turbofan. | |
415 bool passes_osr_test = FLAG_turbo_osr || !info()->is_osr(); | |
416 | |
417 if ((is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable || | |
418 passes_turbo_filter) && | |
419 passes_osr_test) { | |
420 // Use TurboFan for the compilation. | |
421 if (FLAG_trace_opt) { | |
422 OFStream os(stdout); | |
423 os << "[compiling method " << Brief(*info()->closure()) | |
424 << " using TurboFan"; | |
425 if (info()->is_osr()) os << " OSR"; | |
426 os << "]" << std::endl; | |
427 } | |
428 | |
429 if (info()->shared_info()->asm_function()) { | |
430 if (info()->osr_frame()) info()->MarkAsFrameSpecializing(); | |
431 info()->MarkAsFunctionContextSpecializing(); | |
432 } else { | |
433 if (!FLAG_always_opt) { | |
434 info()->MarkAsBailoutOnUninitialized(); | |
435 } | |
436 if (FLAG_native_context_specialization) { | |
437 info()->MarkAsNativeContextSpecializing(); | |
438 info()->MarkAsTypingEnabled(); | |
439 } | |
440 } | |
441 if (!info()->shared_info()->asm_function() || | |
442 FLAG_turbo_asm_deoptimization) { | |
443 info()->MarkAsDeoptimizationEnabled(); | |
444 } | |
445 | |
446 Timer t(this, &time_taken_to_create_graph_); | |
447 compiler::Pipeline pipeline(info()); | |
448 pipeline.GenerateCode(); | |
449 if (!info()->code().is_null()) { | |
450 return SetLastStatus(SUCCEEDED); | |
451 } | |
452 } | |
453 | |
454 if (!isolate()->use_crankshaft() || dont_crankshaft) { | |
455 // Crankshaft is entirely disabled. | |
456 return SetLastStatus(FAILED); | |
457 } | |
458 | |
459 Scope* scope = info()->scope(); | |
460 if (LUnallocated::TooManyParameters(scope->num_parameters())) { | |
461 // Crankshaft would require too many Lithium operands. | |
462 return AbortOptimization(kTooManyParameters); | |
463 } | |
464 | |
465 if (info()->is_osr() && | |
466 LUnallocated::TooManyParametersOrStackSlots(scope->num_parameters(), | |
467 scope->num_stack_slots())) { | |
468 // Crankshaft would require too many Lithium operands. | |
469 return AbortOptimization(kTooManyParametersLocals); | |
470 } | |
471 | |
472 if (FLAG_trace_opt) { | |
473 OFStream os(stdout); | |
474 os << "[compiling method " << Brief(*info()->closure()) | |
475 << " using Crankshaft"; | |
476 if (info()->is_osr()) os << " OSR"; | |
477 os << "]" << std::endl; | |
478 } | |
479 | |
480 if (FLAG_trace_hydrogen) { | |
481 isolate()->GetHTracer()->TraceCompilation(info()); | |
482 } | |
483 | |
484 // Type-check the function. | |
485 AstTyper(info()->isolate(), info()->zone(), info()->closure(), | |
486 info()->scope(), info()->osr_ast_id(), info()->literal()) | |
487 .Run(); | |
488 | |
489 // Optimization could have been disabled by the parser. Note that this check | |
490 // is only needed because the Hydrogen graph builder is missing some bailouts. | |
491 if (info()->shared_info()->optimization_disabled()) { | |
492 return AbortOptimization( | |
493 info()->shared_info()->disable_optimization_reason()); | |
494 } | |
495 | |
496 HOptimizedGraphBuilder* graph_builder = | |
497 (info()->is_tracking_positions() || FLAG_trace_ic) | |
498 ? new (info()->zone()) HOptimizedGraphBuilderWithPositions(info()) | |
499 : new (info()->zone()) HOptimizedGraphBuilder(info()); | |
500 | |
501 Timer t(this, &time_taken_to_create_graph_); | |
502 graph_ = graph_builder->CreateGraph(); | |
503 | |
504 if (isolate()->has_pending_exception()) { | |
505 return SetLastStatus(FAILED); | |
506 } | |
507 | |
508 if (graph_ == NULL) return SetLastStatus(BAILED_OUT); | |
509 | |
510 if (info()->dependencies()->HasAborted()) { | |
511 // Dependency has changed during graph creation. Let's try again later. | |
512 return RetryOptimization(kBailedOutDueToDependencyChange); | |
513 } | |
514 | |
515 return SetLastStatus(SUCCEEDED); | |
516 } | 365 } |
517 | 366 |
518 | 367 |
519 OptimizedCompileJob::Status OptimizedCompileJob::OptimizeGraph() { | 368 OptimizedCompileJob::Status OptimizedCompileJob::OptimizeGraph() { |
520 DisallowHeapAllocation no_allocation; | 369 DisallowHeapAllocation no_allocation; |
521 DisallowHandleAllocation no_handles; | 370 DisallowHandleAllocation no_handles; |
522 DisallowHandleDereference no_deref; | 371 DisallowHandleDereference no_deref; |
523 DisallowCodeDependencyChange no_dependency_change; | 372 DisallowCodeDependencyChange no_dependency_change; |
524 | 373 |
525 DCHECK(last_status() == SUCCEEDED); | 374 // Delegate to the underlying implementation. |
526 // TODO(turbofan): Currently everything is done in the first phase. | 375 DCHECK_EQ(SUCCEEDED, last_status()); |
527 if (!info()->code().is_null()) { | 376 ScopedTimer t(&time_taken_to_optimize_); |
528 return last_status(); | 377 return SetLastStatus(OptimizeGraphImpl()); |
529 } | 378 } |
530 | 379 |
531 Timer t(this, &time_taken_to_optimize_); | 380 OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() { |
532 DCHECK(graph_ != NULL); | 381 DisallowCodeDependencyChange no_dependency_change; |
533 BailoutReason bailout_reason = kNoReason; | 382 DisallowJavascriptExecution no_js(isolate()); |
| 383 DCHECK(!info()->dependencies()->HasAborted()); |
534 | 384 |
535 if (graph_->Optimize(&bailout_reason)) { | 385 // Delegate to the underlying implementation. |
536 chunk_ = LChunk::NewChunk(graph_); | 386 DCHECK_EQ(SUCCEEDED, last_status()); |
537 if (chunk_ != NULL) return SetLastStatus(SUCCEEDED); | 387 ScopedTimer t(&time_taken_to_codegen_); |
538 } else if (bailout_reason != kNoReason) { | 388 return SetLastStatus(GenerateCodeImpl()); |
539 info_->AbortOptimization(bailout_reason); | |
540 } | |
541 | |
542 return SetLastStatus(BAILED_OUT); | |
543 } | 389 } |
544 | 390 |
545 | 391 |
546 namespace { | 392 namespace { |
547 | 393 |
548 void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object, | 394 void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object, |
549 Handle<Code> code) { | 395 Handle<Code> code) { |
550 Handle<WeakCell> cell = Code::WeakCellFor(code); | 396 Handle<WeakCell> cell = Code::WeakCellFor(code); |
551 Heap* heap = isolate->heap(); | 397 Heap* heap = isolate->heap(); |
552 Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object)); | 398 Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object)); |
553 dep = DependentCode::InsertWeakCode(dep, DependentCode::kWeakCodeGroup, cell); | 399 dep = DependentCode::InsertWeakCode(dep, DependentCode::kWeakCodeGroup, cell); |
554 heap->AddWeakObjectToCodeDependency(object, dep); | 400 heap->AddWeakObjectToCodeDependency(object, dep); |
555 } | 401 } |
556 | 402 |
| 403 } // namespace |
557 | 404 |
558 void RegisterWeakObjectsInOptimizedCode(Handle<Code> code) { | 405 void OptimizedCompileJob::RegisterWeakObjectsInOptimizedCode( |
| 406 Handle<Code> code) { |
559 // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies. | 407 // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies. |
560 Isolate* const isolate = code->GetIsolate(); | 408 Isolate* const isolate = code->GetIsolate(); |
561 DCHECK(code->is_optimized_code()); | 409 DCHECK(code->is_optimized_code()); |
562 std::vector<Handle<Map>> maps; | 410 std::vector<Handle<Map>> maps; |
563 std::vector<Handle<HeapObject>> objects; | 411 std::vector<Handle<HeapObject>> objects; |
564 { | 412 { |
565 DisallowHeapAllocation no_gc; | 413 DisallowHeapAllocation no_gc; |
566 int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | | 414 int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | |
567 RelocInfo::ModeMask(RelocInfo::CELL); | 415 RelocInfo::ModeMask(RelocInfo::CELL); |
568 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { | 416 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { |
(...skipping 19 matching lines...) Expand all Loading... |
588 isolate->heap()->AddRetainedMap(map); | 436 isolate->heap()->AddRetainedMap(map); |
589 } | 437 } |
590 Map::AddDependentCode(map, DependentCode::kWeakCodeGroup, code); | 438 Map::AddDependentCode(map, DependentCode::kWeakCodeGroup, code); |
591 } | 439 } |
592 for (Handle<HeapObject> object : objects) { | 440 for (Handle<HeapObject> object : objects) { |
593 AddWeakObjectToCodeDependency(isolate, object, code); | 441 AddWeakObjectToCodeDependency(isolate, object, code); |
594 } | 442 } |
595 code->set_can_have_weak_objects(true); | 443 code->set_can_have_weak_objects(true); |
596 } | 444 } |
597 | 445 |
598 } // namespace | |
599 | |
600 | |
601 OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() { | |
602 DCHECK(last_status() == SUCCEEDED); | |
603 // TODO(turbofan): Currently everything is done in the first phase. | |
604 if (!info()->code().is_null()) { | |
605 info()->dependencies()->Commit(info()->code()); | |
606 if (info()->is_deoptimization_enabled()) { | |
607 info()->parse_info()->context()->native_context()->AddOptimizedCode( | |
608 *info()->code()); | |
609 RegisterWeakObjectsInOptimizedCode(info()->code()); | |
610 } | |
611 RecordOptimizationStats(); | |
612 return last_status(); | |
613 } | |
614 | |
615 DCHECK(!info()->dependencies()->HasAborted()); | |
616 DisallowCodeDependencyChange no_dependency_change; | |
617 DisallowJavascriptExecution no_js(isolate()); | |
618 { // Scope for timer. | |
619 Timer timer(this, &time_taken_to_codegen_); | |
620 DCHECK(chunk_ != NULL); | |
621 DCHECK(graph_ != NULL); | |
622 // Deferred handles reference objects that were accessible during | |
623 // graph creation. To make sure that we don't encounter inconsistencies | |
624 // between graph creation and code generation, we disallow accessing | |
625 // objects through deferred handles during the latter, with exceptions. | |
626 DisallowDeferredHandleDereference no_deferred_handle_deref; | |
627 Handle<Code> optimized_code = chunk_->Codegen(); | |
628 if (optimized_code.is_null()) { | |
629 if (info()->bailout_reason() == kNoReason) { | |
630 return AbortOptimization(kCodeGenerationFailed); | |
631 } | |
632 return SetLastStatus(BAILED_OUT); | |
633 } | |
634 RegisterWeakObjectsInOptimizedCode(optimized_code); | |
635 info()->SetCode(optimized_code); | |
636 } | |
637 RecordOptimizationStats(); | |
638 // Add to the weak list of optimized code objects. | |
639 info()->context()->native_context()->AddOptimizedCode(*info()->code()); | |
640 return SetLastStatus(SUCCEEDED); | |
641 } | |
642 | |
643 | 446 |
644 void OptimizedCompileJob::RecordOptimizationStats() { | 447 void OptimizedCompileJob::RecordOptimizationStats() { |
645 Handle<JSFunction> function = info()->closure(); | 448 Handle<JSFunction> function = info()->closure(); |
646 if (!function->IsOptimized()) { | 449 if (!function->IsOptimized()) { |
647 // Concurrent recompilation and OSR may race. Increment only once. | 450 // Concurrent recompilation and OSR may race. Increment only once. |
648 int opt_count = function->shared()->opt_count(); | 451 int opt_count = function->shared()->opt_count(); |
649 function->shared()->set_opt_count(opt_count + 1); | 452 function->shared()->set_opt_count(opt_count + 1); |
650 } | 453 } |
651 double ms_creategraph = time_taken_to_create_graph_.InMillisecondsF(); | 454 double ms_creategraph = time_taken_to_create_graph_.InMillisecondsF(); |
652 double ms_optimize = time_taken_to_optimize_.InMillisecondsF(); | 455 double ms_optimize = time_taken_to_optimize_.InMillisecondsF(); |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
930 FunctionLiteral* lit = parse_info->literal(); | 733 FunctionLiteral* lit = parse_info->literal(); |
931 shared_info->set_ast_node_count(lit->ast_node_count()); | 734 shared_info->set_ast_node_count(lit->ast_node_count()); |
932 MaybeDisableOptimization(shared_info, lit->dont_optimize_reason()); | 735 MaybeDisableOptimization(shared_info, lit->dont_optimize_reason()); |
933 shared_info->set_dont_crankshaft( | 736 shared_info->set_dont_crankshaft( |
934 shared_info->dont_crankshaft() || | 737 shared_info->dont_crankshaft() || |
935 (lit->flags() & AstProperties::kDontCrankshaft)); | 738 (lit->flags() & AstProperties::kDontCrankshaft)); |
936 } | 739 } |
937 return true; | 740 return true; |
938 } | 741 } |
939 | 742 |
| 743 bool UseTurboFan(CompilationInfo* info) { |
| 744 bool optimization_disabled = info->shared_info()->optimization_disabled(); |
| 745 bool dont_crankshaft = info->shared_info()->dont_crankshaft(); |
| 746 |
| 747 // Check the enabling conditions for Turbofan. |
| 748 // 1. "use asm" code. |
| 749 bool is_turbofanable_asm = FLAG_turbo_asm && |
| 750 info->shared_info()->asm_function() && |
| 751 !optimization_disabled; |
| 752 |
| 753 // 2. Fallback for features unsupported by Crankshaft. |
| 754 bool is_unsupported_by_crankshaft_but_turbofanable = |
| 755 dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 && |
| 756 !optimization_disabled; |
| 757 |
| 758 // 3. Explicitly enabled by the command-line filter. |
| 759 bool passes_turbo_filter = |
| 760 info->shared_info()->PassesFilter(FLAG_turbo_filter); |
| 761 |
| 762 // If this is OSR request, OSR must be enabled by Turbofan. |
| 763 bool passes_osr_test = FLAG_turbo_osr || !info->is_osr(); |
| 764 |
| 765 return (is_turbofanable_asm || |
| 766 is_unsupported_by_crankshaft_but_turbofanable || |
| 767 passes_turbo_filter) && |
| 768 passes_osr_test; |
| 769 } |
| 770 |
940 bool GetOptimizedCodeNow(CompilationInfo* info) { | 771 bool GetOptimizedCodeNow(CompilationInfo* info) { |
941 Isolate* isolate = info->isolate(); | 772 Isolate* isolate = info->isolate(); |
942 CanonicalHandleScope canonical(isolate); | 773 CanonicalHandleScope canonical(isolate); |
943 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate); | 774 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate); |
944 TRACE_EVENT0("v8", "V8.OptimizeCode"); | 775 TRACE_EVENT0("v8", "V8.OptimizeCode"); |
945 | 776 |
946 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; | 777 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; |
947 | 778 |
948 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate); | 779 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate); |
949 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); | 780 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); |
950 | 781 |
951 OptimizedCompileJob job(info); | 782 OptimizedCompileJob* job = UseTurboFan(info) |
952 if (job.CreateGraph() != OptimizedCompileJob::SUCCEEDED || | 783 ? compiler::Pipeline::NewCompilationJob(info) |
953 job.OptimizeGraph() != OptimizedCompileJob::SUCCEEDED || | 784 : new (info->zone()) HCompilationJob(info); |
954 job.GenerateCode() != OptimizedCompileJob::SUCCEEDED) { | 785 if (job->CreateGraph() != OptimizedCompileJob::SUCCEEDED || |
| 786 job->OptimizeGraph() != OptimizedCompileJob::SUCCEEDED || |
| 787 job->GenerateCode() != OptimizedCompileJob::SUCCEEDED) { |
955 if (FLAG_trace_opt) { | 788 if (FLAG_trace_opt) { |
956 PrintF("[aborted optimizing "); | 789 PrintF("[aborted optimizing "); |
957 info->closure()->ShortPrint(); | 790 info->closure()->ShortPrint(); |
958 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); | 791 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); |
959 } | 792 } |
960 return false; | 793 return false; |
961 } | 794 } |
962 | 795 |
963 // Success! | 796 // Success! |
| 797 job->RecordOptimizationStats(); |
964 DCHECK(!isolate->has_pending_exception()); | 798 DCHECK(!isolate->has_pending_exception()); |
965 InsertCodeIntoOptimizedCodeMap(info); | 799 InsertCodeIntoOptimizedCodeMap(info); |
966 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, | 800 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, |
967 info->shared_info()); | 801 info->shared_info()); |
968 return true; | 802 return true; |
969 } | 803 } |
970 | 804 |
971 bool GetOptimizedCodeLater(CompilationInfo* info) { | 805 bool GetOptimizedCodeLater(CompilationInfo* info) { |
972 Isolate* isolate = info->isolate(); | 806 Isolate* isolate = info->isolate(); |
973 CanonicalHandleScope canonical(isolate); | 807 CanonicalHandleScope canonical(isolate); |
(...skipping 12 matching lines...) Expand all Loading... |
986 CompilationHandleScope handle_scope(info); | 820 CompilationHandleScope handle_scope(info); |
987 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; | 821 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; |
988 | 822 |
989 // Reopen handles in the new CompilationHandleScope. | 823 // Reopen handles in the new CompilationHandleScope. |
990 info->ReopenHandlesInNewHandleScope(); | 824 info->ReopenHandlesInNewHandleScope(); |
991 info->parse_info()->ReopenHandlesInNewHandleScope(); | 825 info->parse_info()->ReopenHandlesInNewHandleScope(); |
992 | 826 |
993 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); | 827 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); |
994 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); | 828 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); |
995 | 829 |
996 OptimizedCompileJob* job = new (info->zone()) OptimizedCompileJob(info); | 830 OptimizedCompileJob* job = UseTurboFan(info) |
| 831 ? compiler::Pipeline::NewCompilationJob(info) |
| 832 : new (info->zone()) HCompilationJob(info); |
997 OptimizedCompileJob::Status status = job->CreateGraph(); | 833 OptimizedCompileJob::Status status = job->CreateGraph(); |
998 if (status != OptimizedCompileJob::SUCCEEDED) return false; | 834 if (status != OptimizedCompileJob::SUCCEEDED) return false; |
999 isolate->optimizing_compile_dispatcher()->QueueForOptimization(job); | 835 isolate->optimizing_compile_dispatcher()->QueueForOptimization(job); |
1000 | 836 |
1001 if (FLAG_trace_concurrent_recompilation) { | 837 if (FLAG_trace_concurrent_recompilation) { |
1002 PrintF(" ** Queued "); | 838 PrintF(" ** Queued "); |
1003 info->closure()->ShortPrint(); | 839 info->closure()->ShortPrint(); |
1004 if (info->is_osr()) { | 840 if (info->is_osr()) { |
1005 PrintF(" for concurrent OSR at %d.\n", info->osr_ast_id().ToInt()); | 841 PrintF(" for concurrent OSR at %d.\n", info->osr_ast_id().ToInt()); |
1006 } else { | 842 } else { |
(...skipping 829 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1836 // 2) The function may have already been optimized by OSR. Simply continue. | 1672 // 2) The function may have already been optimized by OSR. Simply continue. |
1837 // Except when OSR already disabled optimization for some reason. | 1673 // Except when OSR already disabled optimization for some reason. |
1838 // 3) The code may have already been invalidated due to dependency change. | 1674 // 3) The code may have already been invalidated due to dependency change. |
1839 // 4) Code generation may have failed. | 1675 // 4) Code generation may have failed. |
1840 if (job->last_status() == OptimizedCompileJob::SUCCEEDED) { | 1676 if (job->last_status() == OptimizedCompileJob::SUCCEEDED) { |
1841 if (shared->optimization_disabled()) { | 1677 if (shared->optimization_disabled()) { |
1842 job->RetryOptimization(kOptimizationDisabled); | 1678 job->RetryOptimization(kOptimizationDisabled); |
1843 } else if (info->dependencies()->HasAborted()) { | 1679 } else if (info->dependencies()->HasAborted()) { |
1844 job->RetryOptimization(kBailedOutDueToDependencyChange); | 1680 job->RetryOptimization(kBailedOutDueToDependencyChange); |
1845 } else if (job->GenerateCode() == OptimizedCompileJob::SUCCEEDED) { | 1681 } else if (job->GenerateCode() == OptimizedCompileJob::SUCCEEDED) { |
| 1682 job->RecordOptimizationStats(); |
1846 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info.get(), shared); | 1683 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info.get(), shared); |
1847 if (shared->SearchOptimizedCodeMap(info->context()->native_context(), | 1684 if (shared->SearchOptimizedCodeMap(info->context()->native_context(), |
1848 info->osr_ast_id()).code == nullptr) { | 1685 info->osr_ast_id()).code == nullptr) { |
1849 InsertCodeIntoOptimizedCodeMap(info.get()); | 1686 InsertCodeIntoOptimizedCodeMap(info.get()); |
1850 } | 1687 } |
1851 if (FLAG_trace_opt) { | 1688 if (FLAG_trace_opt) { |
1852 PrintF("[completed optimizing "); | 1689 PrintF("[completed optimizing "); |
1853 info->closure()->ShortPrint(); | 1690 info->closure()->ShortPrint(); |
1854 PrintF("]\n"); | 1691 PrintF("]\n"); |
1855 } | 1692 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1898 MaybeHandle<Code> code; | 1735 MaybeHandle<Code> code; |
1899 if (cached.code != nullptr) code = handle(cached.code); | 1736 if (cached.code != nullptr) code = handle(cached.code); |
1900 Handle<Context> native_context(function->context()->native_context()); | 1737 Handle<Context> native_context(function->context()->native_context()); |
1901 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, | 1738 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, |
1902 literals, BailoutId::None()); | 1739 literals, BailoutId::None()); |
1903 } | 1740 } |
1904 } | 1741 } |
1905 | 1742 |
1906 } // namespace internal | 1743 } // namespace internal |
1907 } // namespace v8 | 1744 } // namespace v8 |
OLD | NEW |