| 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 |