| 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/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
| 8 | 8 |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 no_frame_ranges_ = isolate->cpu_profiler()->is_profiling() | 149 no_frame_ranges_ = isolate->cpu_profiler()->is_profiling() |
| 150 ? new List<OffsetRange>(2) : NULL; | 150 ? new List<OffsetRange>(2) : NULL; |
| 151 for (int i = 0; i < DependentCode::kGroupCount; i++) { | 151 for (int i = 0; i < DependentCode::kGroupCount; i++) { |
| 152 dependencies_[i] = NULL; | 152 dependencies_[i] = NULL; |
| 153 } | 153 } |
| 154 if (mode == STUB) { | 154 if (mode == STUB) { |
| 155 mode_ = STUB; | 155 mode_ = STUB; |
| 156 return; | 156 return; |
| 157 } | 157 } |
| 158 mode_ = mode; | 158 mode_ = mode; |
| 159 abort_due_to_dependency_ = false; | |
| 160 if (!script_.is_null() && script_->type()->value() == Script::TYPE_NATIVE) { | 159 if (!script_.is_null() && script_->type()->value() == Script::TYPE_NATIVE) { |
| 161 MarkAsNative(); | 160 MarkAsNative(); |
| 162 } | 161 } |
| 163 if (isolate_->debug()->is_active()) MarkAsDebug(); | 162 if (isolate_->debug()->is_active()) MarkAsDebug(); |
| 164 if (FLAG_context_specialization) MarkAsContextSpecializing(); | 163 if (FLAG_context_specialization) MarkAsContextSpecializing(); |
| 165 if (FLAG_turbo_inlining) MarkAsInliningEnabled(); | 164 if (FLAG_turbo_inlining) MarkAsInliningEnabled(); |
| 166 if (FLAG_turbo_types) MarkAsTypingEnabled(); | 165 if (FLAG_turbo_types) MarkAsTypingEnabled(); |
| 167 | 166 |
| 168 if (!shared_info_.is_null()) { | 167 if (!shared_info_.is_null()) { |
| 169 DCHECK(strict_mode() == SLOPPY); | 168 DCHECK(strict_mode() == SLOPPY); |
| 170 SetStrictMode(shared_info_->strict_mode()); | 169 SetStrictMode(shared_info_->strict_mode()); |
| 171 } | 170 } |
| 172 set_bailout_reason(kUnknown); | 171 bailout_reason_ = kUnknown; |
| 173 | 172 |
| 174 if (!shared_info().is_null() && shared_info()->is_compiled()) { | 173 if (!shared_info().is_null() && shared_info()->is_compiled()) { |
| 175 // We should initialize the CompilationInfo feedback vector from the | 174 // We should initialize the CompilationInfo feedback vector from the |
| 176 // passed in shared info, rather than creating a new one. | 175 // passed in shared info, rather than creating a new one. |
| 177 feedback_vector_ = | 176 feedback_vector_ = |
| 178 Handle<TypeFeedbackVector>(shared_info()->feedback_vector(), isolate); | 177 Handle<TypeFeedbackVector>(shared_info()->feedback_vector(), isolate); |
| 179 } | 178 } |
| 180 } | 179 } |
| 181 | 180 |
| 182 | 181 |
| 183 CompilationInfo::~CompilationInfo() { | 182 CompilationInfo::~CompilationInfo() { |
| 183 if (GetFlag(kDisableFutureOptimization)) { |
| 184 shared_info()->DisableOptimization(bailout_reason()); |
| 185 } |
| 184 delete deferred_handles_; | 186 delete deferred_handles_; |
| 185 delete no_frame_ranges_; | 187 delete no_frame_ranges_; |
| 186 if (ast_value_factory_owned_) delete ast_value_factory_; | 188 if (ast_value_factory_owned_) delete ast_value_factory_; |
| 187 #ifdef DEBUG | 189 #ifdef DEBUG |
| 188 // Check that no dependent maps have been added or added dependent maps have | 190 // Check that no dependent maps have been added or added dependent maps have |
| 189 // been rolled back or committed. | 191 // been rolled back or committed. |
| 190 for (int i = 0; i < DependentCode::kGroupCount; i++) { | 192 for (int i = 0; i < DependentCode::kGroupCount; i++) { |
| 191 DCHECK_EQ(NULL, dependencies_[i]); | 193 DCHECK_EQ(NULL, dependencies_[i]); |
| 192 } | 194 } |
| 193 #endif // DEBUG | 195 #endif // DEBUG |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 DCHECK(isolate()->use_crankshaft()); | 326 DCHECK(isolate()->use_crankshaft()); |
| 325 DCHECK(info()->IsOptimizing()); | 327 DCHECK(info()->IsOptimizing()); |
| 326 DCHECK(!info()->IsCompilingForDebugging()); | 328 DCHECK(!info()->IsCompilingForDebugging()); |
| 327 | 329 |
| 328 // We should never arrive here if optimization has been disabled on the | 330 // We should never arrive here if optimization has been disabled on the |
| 329 // shared function info. | 331 // shared function info. |
| 330 DCHECK(!info()->shared_info()->optimization_disabled()); | 332 DCHECK(!info()->shared_info()->optimization_disabled()); |
| 331 | 333 |
| 332 // Do not use crankshaft if we need to be able to set break points. | 334 // Do not use crankshaft if we need to be able to set break points. |
| 333 if (isolate()->DebuggerHasBreakPoints()) { | 335 if (isolate()->DebuggerHasBreakPoints()) { |
| 334 return AbortOptimization(kDebuggerHasBreakPoints); | 336 return RetryOptimization(kDebuggerHasBreakPoints); |
| 335 } | 337 } |
| 336 | 338 |
| 337 // Limit the number of times we re-compile a functions with | 339 // Limit the number of times we re-compile a functions with |
| 338 // the optimizing compiler. | 340 // the optimizing compiler. |
| 339 const int kMaxOptCount = | 341 const int kMaxOptCount = |
| 340 FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000; | 342 FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000; |
| 341 if (info()->opt_count() > kMaxOptCount) { | 343 if (info()->opt_count() > kMaxOptCount) { |
| 342 return AbortAndDisableOptimization(kOptimizedTooManyTimes); | 344 return AbortOptimization(kOptimizedTooManyTimes); |
| 343 } | 345 } |
| 344 | 346 |
| 345 // Due to an encoding limit on LUnallocated operands in the Lithium | 347 // Due to an encoding limit on LUnallocated operands in the Lithium |
| 346 // language, we cannot optimize functions with too many formal parameters | 348 // language, we cannot optimize functions with too many formal parameters |
| 347 // or perform on-stack replacement for function with too many | 349 // or perform on-stack replacement for function with too many |
| 348 // stack-allocated local variables. | 350 // stack-allocated local variables. |
| 349 // | 351 // |
| 350 // The encoding is as a signed value, with parameters and receiver using | 352 // The encoding is as a signed value, with parameters and receiver using |
| 351 // the negative indices and locals the non-negative ones. | 353 // the negative indices and locals the non-negative ones. |
| 352 const int parameter_limit = -LUnallocated::kMinFixedSlotIndex; | 354 const int parameter_limit = -LUnallocated::kMinFixedSlotIndex; |
| 353 Scope* scope = info()->scope(); | 355 Scope* scope = info()->scope(); |
| 354 if ((scope->num_parameters() + 1) > parameter_limit) { | 356 if ((scope->num_parameters() + 1) > parameter_limit) { |
| 355 return AbortAndDisableOptimization(kTooManyParameters); | 357 return AbortOptimization(kTooManyParameters); |
| 356 } | 358 } |
| 357 | 359 |
| 358 const int locals_limit = LUnallocated::kMaxFixedSlotIndex; | 360 const int locals_limit = LUnallocated::kMaxFixedSlotIndex; |
| 359 if (info()->is_osr() && | 361 if (info()->is_osr() && |
| 360 scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit) { | 362 scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit) { |
| 361 return AbortAndDisableOptimization(kTooManyParametersLocals); | 363 return AbortOptimization(kTooManyParametersLocals); |
| 362 } | 364 } |
| 363 | 365 |
| 364 if (scope->HasIllegalRedeclaration()) { | 366 if (scope->HasIllegalRedeclaration()) { |
| 365 return AbortAndDisableOptimization(kFunctionWithIllegalRedeclaration); | 367 return AbortOptimization(kFunctionWithIllegalRedeclaration); |
| 366 } | 368 } |
| 367 | 369 |
| 368 // Check the whitelist for Crankshaft. | 370 // Check the whitelist for Crankshaft. |
| 369 if (!info()->closure()->PassesFilter(FLAG_hydrogen_filter)) { | 371 if (!info()->closure()->PassesFilter(FLAG_hydrogen_filter)) { |
| 370 return AbortOptimization(kHydrogenFilter); | 372 return AbortOptimization(kHydrogenFilter); |
| 371 } | 373 } |
| 372 | 374 |
| 373 // Crankshaft requires a version of fullcode with deoptimization support. | 375 // Crankshaft requires a version of fullcode with deoptimization support. |
| 374 // Recompile the unoptimized version of the code if the current version | 376 // Recompile the unoptimized version of the code if the current version |
| 375 // doesn't have deoptimization support already. | 377 // doesn't have deoptimization support already. |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 : new(info()->zone()) HOptimizedGraphBuilder(info()); | 421 : new(info()->zone()) HOptimizedGraphBuilder(info()); |
| 420 | 422 |
| 421 Timer t(this, &time_taken_to_create_graph_); | 423 Timer t(this, &time_taken_to_create_graph_); |
| 422 info()->set_this_has_uses(false); | 424 info()->set_this_has_uses(false); |
| 423 graph_ = graph_builder_->CreateGraph(); | 425 graph_ = graph_builder_->CreateGraph(); |
| 424 | 426 |
| 425 if (isolate()->has_pending_exception()) { | 427 if (isolate()->has_pending_exception()) { |
| 426 return SetLastStatus(FAILED); | 428 return SetLastStatus(FAILED); |
| 427 } | 429 } |
| 428 | 430 |
| 429 // The function being compiled may have bailed out due to an inline | 431 if (graph_ == NULL) return SetLastStatus(BAILED_OUT); |
| 430 // candidate bailing out. In such a case, we don't disable | |
| 431 // optimization on the shared_info. | |
| 432 DCHECK(!graph_builder_->inline_bailout() || graph_ == NULL); | |
| 433 if (graph_ == NULL) { | |
| 434 if (graph_builder_->inline_bailout()) { | |
| 435 return AbortOptimization(); | |
| 436 } else { | |
| 437 return AbortAndDisableOptimization(); | |
| 438 } | |
| 439 } | |
| 440 | 432 |
| 441 if (info()->HasAbortedDueToDependencyChange()) { | 433 if (info()->HasAbortedDueToDependencyChange()) { |
| 442 return AbortOptimization(kBailedOutDueToDependencyChange); | 434 // Dependency has changed during graph creation. Let's try again later. |
| 435 return RetryOptimization(kBailedOutDueToDependencyChange); |
| 443 } | 436 } |
| 444 | 437 |
| 445 return SetLastStatus(SUCCEEDED); | 438 return SetLastStatus(SUCCEEDED); |
| 446 } | 439 } |
| 447 | 440 |
| 448 | 441 |
| 449 OptimizedCompileJob::Status OptimizedCompileJob::OptimizeGraph() { | 442 OptimizedCompileJob::Status OptimizedCompileJob::OptimizeGraph() { |
| 450 DisallowHeapAllocation no_allocation; | 443 DisallowHeapAllocation no_allocation; |
| 451 DisallowHandleAllocation no_handles; | 444 DisallowHandleAllocation no_handles; |
| 452 DisallowHandleDereference no_deref; | 445 DisallowHandleDereference no_deref; |
| 453 DisallowCodeDependencyChange no_dependency_change; | 446 DisallowCodeDependencyChange no_dependency_change; |
| 454 | 447 |
| 455 DCHECK(last_status() == SUCCEEDED); | 448 DCHECK(last_status() == SUCCEEDED); |
| 456 // TODO(turbofan): Currently everything is done in the first phase. | 449 // TODO(turbofan): Currently everything is done in the first phase. |
| 457 if (!info()->code().is_null()) { | 450 if (!info()->code().is_null()) { |
| 458 return last_status(); | 451 return last_status(); |
| 459 } | 452 } |
| 460 | 453 |
| 461 Timer t(this, &time_taken_to_optimize_); | 454 Timer t(this, &time_taken_to_optimize_); |
| 462 DCHECK(graph_ != NULL); | 455 DCHECK(graph_ != NULL); |
| 463 BailoutReason bailout_reason = kNoReason; | 456 BailoutReason bailout_reason = kNoReason; |
| 464 | 457 |
| 465 if (graph_->Optimize(&bailout_reason)) { | 458 if (graph_->Optimize(&bailout_reason)) { |
| 466 chunk_ = LChunk::NewChunk(graph_); | 459 chunk_ = LChunk::NewChunk(graph_); |
| 467 if (chunk_ != NULL) return SetLastStatus(SUCCEEDED); | 460 if (chunk_ != NULL) return SetLastStatus(SUCCEEDED); |
| 468 } else if (bailout_reason != kNoReason) { | 461 } else if (bailout_reason != kNoReason) { |
| 469 graph_builder_->Bailout(bailout_reason); | 462 graph_builder_->Bailout(bailout_reason); |
| 470 } | 463 } |
| 471 | 464 |
| 472 return AbortOptimization(); | 465 return SetLastStatus(BAILED_OUT); |
| 473 } | 466 } |
| 474 | 467 |
| 475 | 468 |
| 476 OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() { | 469 OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() { |
| 477 DCHECK(last_status() == SUCCEEDED); | 470 DCHECK(last_status() == SUCCEEDED); |
| 478 // TODO(turbofan): Currently everything is done in the first phase. | 471 // TODO(turbofan): Currently everything is done in the first phase. |
| 479 if (!info()->code().is_null()) { | 472 if (!info()->code().is_null()) { |
| 480 RecordOptimizationStats(); | 473 RecordOptimizationStats(); |
| 481 return last_status(); | 474 return last_status(); |
| 482 } | 475 } |
| 483 | 476 |
| 484 DCHECK(!info()->HasAbortedDueToDependencyChange()); | 477 DCHECK(!info()->HasAbortedDueToDependencyChange()); |
| 485 DisallowCodeDependencyChange no_dependency_change; | 478 DisallowCodeDependencyChange no_dependency_change; |
| 486 DisallowJavascriptExecution no_js(isolate()); | 479 DisallowJavascriptExecution no_js(isolate()); |
| 487 { // Scope for timer. | 480 { // Scope for timer. |
| 488 Timer timer(this, &time_taken_to_codegen_); | 481 Timer timer(this, &time_taken_to_codegen_); |
| 489 DCHECK(chunk_ != NULL); | 482 DCHECK(chunk_ != NULL); |
| 490 DCHECK(graph_ != NULL); | 483 DCHECK(graph_ != NULL); |
| 491 // Deferred handles reference objects that were accessible during | 484 // Deferred handles reference objects that were accessible during |
| 492 // graph creation. To make sure that we don't encounter inconsistencies | 485 // graph creation. To make sure that we don't encounter inconsistencies |
| 493 // between graph creation and code generation, we disallow accessing | 486 // between graph creation and code generation, we disallow accessing |
| 494 // objects through deferred handles during the latter, with exceptions. | 487 // objects through deferred handles during the latter, with exceptions. |
| 495 DisallowDeferredHandleDereference no_deferred_handle_deref; | 488 DisallowDeferredHandleDereference no_deferred_handle_deref; |
| 496 Handle<Code> optimized_code = chunk_->Codegen(); | 489 Handle<Code> optimized_code = chunk_->Codegen(); |
| 497 if (optimized_code.is_null()) { | 490 if (optimized_code.is_null()) { |
| 498 if (info()->bailout_reason() == kNoReason) { | 491 if (info()->bailout_reason() == kNoReason) { |
| 499 info_->set_bailout_reason(kCodeGenerationFailed); | 492 return AbortOptimization(kCodeGenerationFailed); |
| 500 } else if (info()->bailout_reason() == kMapBecameDeprecated) { | |
| 501 if (FLAG_trace_opt) { | |
| 502 PrintF("[aborted optimizing "); | |
| 503 info()->closure()->ShortPrint(); | |
| 504 PrintF(" because a map became deprecated]\n"); | |
| 505 } | |
| 506 return AbortOptimization(); | |
| 507 } else if (info()->bailout_reason() == kMapBecameUnstable) { | |
| 508 if (FLAG_trace_opt) { | |
| 509 PrintF("[aborted optimizing "); | |
| 510 info()->closure()->ShortPrint(); | |
| 511 PrintF(" because a map became unstable]\n"); | |
| 512 } | |
| 513 return AbortOptimization(); | |
| 514 } | 493 } |
| 515 return AbortAndDisableOptimization(); | 494 return SetLastStatus(BAILED_OUT); |
| 516 } | 495 } |
| 517 info()->SetCode(optimized_code); | 496 info()->SetCode(optimized_code); |
| 518 } | 497 } |
| 519 RecordOptimizationStats(); | 498 RecordOptimizationStats(); |
| 520 // Add to the weak list of optimized code objects. | 499 // Add to the weak list of optimized code objects. |
| 521 info()->context()->native_context()->AddOptimizedCode(*info()->code()); | 500 info()->context()->native_context()->AddOptimizedCode(*info()->code()); |
| 522 return SetLastStatus(SUCCEEDED); | 501 return SetLastStatus(SUCCEEDED); |
| 523 } | 502 } |
| 524 | 503 |
| 525 | 504 |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 757 return true; | 736 return true; |
| 758 } | 737 } |
| 759 | 738 |
| 760 | 739 |
| 761 static bool GetOptimizedCodeNow(CompilationInfo* info) { | 740 static bool GetOptimizedCodeNow(CompilationInfo* info) { |
| 762 if (!CompileOptimizedPrologue(info)) return false; | 741 if (!CompileOptimizedPrologue(info)) return false; |
| 763 | 742 |
| 764 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); | 743 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); |
| 765 | 744 |
| 766 OptimizedCompileJob job(info); | 745 OptimizedCompileJob job(info); |
| 767 if (job.CreateGraph() != OptimizedCompileJob::SUCCEEDED) return false; | 746 if (job.CreateGraph() != OptimizedCompileJob::SUCCEEDED || |
| 768 if (job.OptimizeGraph() != OptimizedCompileJob::SUCCEEDED) return false; | 747 job.OptimizeGraph() != OptimizedCompileJob::SUCCEEDED || |
| 769 if (job.GenerateCode() != OptimizedCompileJob::SUCCEEDED) return false; | 748 job.GenerateCode() != OptimizedCompileJob::SUCCEEDED) { |
| 749 if (FLAG_trace_opt) { |
| 750 PrintF("[aborted optimizing "); |
| 751 info->closure()->ShortPrint(); |
| 752 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); |
| 753 } |
| 754 return false; |
| 755 } |
| 770 | 756 |
| 771 // Success! | 757 // Success! |
| 772 DCHECK(!info->isolate()->has_pending_exception()); | 758 DCHECK(!info->isolate()->has_pending_exception()); |
| 773 InsertCodeIntoOptimizedCodeMap(info); | 759 InsertCodeIntoOptimizedCodeMap(info); |
| 774 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, | 760 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, |
| 775 info->shared_info()); | 761 info->shared_info()); |
| 762 if (FLAG_trace_opt) { |
| 763 PrintF("[completed optimizing "); |
| 764 info->closure()->ShortPrint(); |
| 765 PrintF("]\n"); |
| 766 } |
| 776 return true; | 767 return true; |
| 777 } | 768 } |
| 778 | 769 |
| 779 | 770 |
| 780 static bool GetOptimizedCodeLater(CompilationInfo* info) { | 771 static bool GetOptimizedCodeLater(CompilationInfo* info) { |
| 781 Isolate* isolate = info->isolate(); | 772 Isolate* isolate = info->isolate(); |
| 782 if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) { | 773 if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) { |
| 783 if (FLAG_trace_concurrent_recompilation) { | 774 if (FLAG_trace_concurrent_recompilation) { |
| 784 PrintF(" ** Compilation queue full, will retry optimizing "); | 775 PrintF(" ** Compilation queue full, will retry optimizing "); |
| 785 info->closure()->PrintName(); | 776 info->closure()->ShortPrint(); |
| 786 PrintF(" later.\n"); | 777 PrintF(" later.\n"); |
| 787 } | 778 } |
| 788 return false; | 779 return false; |
| 789 } | 780 } |
| 790 | 781 |
| 791 CompilationHandleScope handle_scope(info); | 782 CompilationHandleScope handle_scope(info); |
| 792 if (!CompileOptimizedPrologue(info)) return false; | 783 if (!CompileOptimizedPrologue(info)) return false; |
| 793 info->SaveHandles(); // Copy handles to the compilation handle scope. | 784 info->SaveHandles(); // Copy handles to the compilation handle scope. |
| 794 | 785 |
| 795 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); | 786 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); |
| 796 | 787 |
| 797 OptimizedCompileJob* job = new (info->zone()) OptimizedCompileJob(info); | 788 OptimizedCompileJob* job = new (info->zone()) OptimizedCompileJob(info); |
| 798 OptimizedCompileJob::Status status = job->CreateGraph(); | 789 OptimizedCompileJob::Status status = job->CreateGraph(); |
| 799 if (status != OptimizedCompileJob::SUCCEEDED) return false; | 790 if (status != OptimizedCompileJob::SUCCEEDED) return false; |
| 800 isolate->optimizing_compiler_thread()->QueueForOptimization(job); | 791 isolate->optimizing_compiler_thread()->QueueForOptimization(job); |
| 801 | 792 |
| 802 if (FLAG_trace_concurrent_recompilation) { | 793 if (FLAG_trace_concurrent_recompilation) { |
| 803 PrintF(" ** Queued "); | 794 PrintF(" ** Queued "); |
| 804 info->closure()->PrintName(); | 795 info->closure()->ShortPrint(); |
| 805 if (info->is_osr()) { | 796 if (info->is_osr()) { |
| 806 PrintF(" for concurrent OSR at %d.\n", info->osr_ast_id().ToInt()); | 797 PrintF(" for concurrent OSR at %d.\n", info->osr_ast_id().ToInt()); |
| 807 } else { | 798 } else { |
| 808 PrintF(" for concurrent optimization.\n"); | 799 PrintF(" for concurrent optimization.\n"); |
| 809 } | 800 } |
| 810 } | 801 } |
| 811 return true; | 802 return true; |
| 812 } | 803 } |
| 813 | 804 |
| 814 | 805 |
| (...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1340 | 1331 |
| 1341 if (mode == CONCURRENT) { | 1332 if (mode == CONCURRENT) { |
| 1342 if (GetOptimizedCodeLater(info.get())) { | 1333 if (GetOptimizedCodeLater(info.get())) { |
| 1343 info.Detach(); // The background recompile job owns this now. | 1334 info.Detach(); // The background recompile job owns this now. |
| 1344 return isolate->builtins()->InOptimizationQueue(); | 1335 return isolate->builtins()->InOptimizationQueue(); |
| 1345 } | 1336 } |
| 1346 } else { | 1337 } else { |
| 1347 if (GetOptimizedCodeNow(info.get())) return info->code(); | 1338 if (GetOptimizedCodeNow(info.get())) return info->code(); |
| 1348 } | 1339 } |
| 1349 | 1340 |
| 1350 // Failed. | |
| 1351 if (FLAG_trace_opt) { | |
| 1352 PrintF("[failed to optimize "); | |
| 1353 function->PrintName(); | |
| 1354 PrintF(": %s]\n", GetBailoutReason(info->bailout_reason())); | |
| 1355 } | |
| 1356 | |
| 1357 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); | 1341 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); |
| 1358 return MaybeHandle<Code>(); | 1342 return MaybeHandle<Code>(); |
| 1359 } | 1343 } |
| 1360 | 1344 |
| 1361 | 1345 |
| 1362 Handle<Code> Compiler::GetConcurrentlyOptimizedCode(OptimizedCompileJob* job) { | 1346 Handle<Code> Compiler::GetConcurrentlyOptimizedCode(OptimizedCompileJob* job) { |
| 1363 // Take ownership of compilation info. Deleting compilation info | 1347 // Take ownership of compilation info. Deleting compilation info |
| 1364 // also tears down the zone and the recompile job. | 1348 // also tears down the zone and the recompile job. |
| 1365 SmartPointer<CompilationInfo> info(job->info()); | 1349 SmartPointer<CompilationInfo> info(job->info()); |
| 1366 Isolate* isolate = info->isolate(); | 1350 Isolate* isolate = info->isolate(); |
| 1367 | 1351 |
| 1368 VMState<COMPILER> state(isolate); | 1352 VMState<COMPILER> state(isolate); |
| 1369 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); | 1353 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); |
| 1370 | 1354 |
| 1371 Handle<SharedFunctionInfo> shared = info->shared_info(); | 1355 Handle<SharedFunctionInfo> shared = info->shared_info(); |
| 1372 shared->code()->set_profiler_ticks(0); | 1356 shared->code()->set_profiler_ticks(0); |
| 1373 | 1357 |
| 1374 // 1) Optimization may have failed. | 1358 // 1) Optimization on the concurrent thread may have failed. |
| 1375 // 2) The function may have already been optimized by OSR. Simply continue. | 1359 // 2) The function may have already been optimized by OSR. Simply continue. |
| 1376 // Except when OSR already disabled optimization for some reason. | 1360 // Except when OSR already disabled optimization for some reason. |
| 1377 // 3) The code may have already been invalidated due to dependency change. | 1361 // 3) The code may have already been invalidated due to dependency change. |
| 1378 // 4) Debugger may have been activated. | 1362 // 4) Debugger may have been activated. |
| 1379 | 1363 // 5) Code generation may have failed. |
| 1380 if (job->last_status() != OptimizedCompileJob::SUCCEEDED || | 1364 if (job->last_status() == OptimizedCompileJob::SUCCEEDED) { |
| 1381 shared->optimization_disabled() || | 1365 if (shared->optimization_disabled()) { |
| 1382 info->HasAbortedDueToDependencyChange() || | 1366 job->RetryOptimization(kOptimizationDisabled); |
| 1383 isolate->DebuggerHasBreakPoints()) { | 1367 } else if (info->HasAbortedDueToDependencyChange()) { |
| 1384 return Handle<Code>::null(); | 1368 job->RetryOptimization(kBailedOutDueToDependencyChange); |
| 1369 } else if (isolate->DebuggerHasBreakPoints()) { |
| 1370 job->RetryOptimization(kDebuggerHasBreakPoints); |
| 1371 } else if (job->GenerateCode() == OptimizedCompileJob::SUCCEEDED) { |
| 1372 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info.get(), shared); |
| 1373 if (info->shared_info()->SearchOptimizedCodeMap( |
| 1374 info->context()->native_context(), info->osr_ast_id()) == -1) { |
| 1375 InsertCodeIntoOptimizedCodeMap(info.get()); |
| 1376 } |
| 1377 if (FLAG_trace_opt) { |
| 1378 PrintF("[completed optimizing "); |
| 1379 info->closure()->ShortPrint(); |
| 1380 PrintF("]\n"); |
| 1381 } |
| 1382 return Handle<Code>(*info->code()); |
| 1383 } |
| 1385 } | 1384 } |
| 1386 | 1385 |
| 1387 if (job->GenerateCode() != OptimizedCompileJob::SUCCEEDED) { | 1386 DCHECK(job->last_status() != OptimizedCompileJob::SUCCEEDED); |
| 1388 return Handle<Code>::null(); | 1387 if (FLAG_trace_opt) { |
| 1388 PrintF("[aborted optimizing "); |
| 1389 info->closure()->ShortPrint(); |
| 1390 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); |
| 1389 } | 1391 } |
| 1390 | 1392 return Handle<Code>::null(); |
| 1391 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info.get(), shared); | |
| 1392 if (info->shared_info()->SearchOptimizedCodeMap( | |
| 1393 info->context()->native_context(), info->osr_ast_id()) == -1) { | |
| 1394 InsertCodeIntoOptimizedCodeMap(info.get()); | |
| 1395 } | |
| 1396 | |
| 1397 if (FLAG_trace_concurrent_recompilation) { | |
| 1398 PrintF(" ** Optimized code for "); | |
| 1399 info->closure()->PrintName(); | |
| 1400 PrintF(" generated.\n"); | |
| 1401 } | |
| 1402 | |
| 1403 return Handle<Code>(*info->code()); | |
| 1404 } | 1393 } |
| 1405 | 1394 |
| 1406 | 1395 |
| 1407 bool Compiler::DebuggerWantsEagerCompilation(CompilationInfo* info, | 1396 bool Compiler::DebuggerWantsEagerCompilation(CompilationInfo* info, |
| 1408 bool allow_lazy_without_ctx) { | 1397 bool allow_lazy_without_ctx) { |
| 1409 return LiveEditFunctionTracker::IsActive(info->isolate()) || | 1398 return LiveEditFunctionTracker::IsActive(info->isolate()) || |
| 1410 (info->isolate()->DebuggerHasBreakPoints() && !allow_lazy_without_ctx); | 1399 (info->isolate()->DebuggerHasBreakPoints() && !allow_lazy_without_ctx); |
| 1411 } | 1400 } |
| 1412 | 1401 |
| 1413 | 1402 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1435 AllowHandleDereference allow_deref; | 1424 AllowHandleDereference allow_deref; |
| 1436 bool tracing_on = info()->IsStub() | 1425 bool tracing_on = info()->IsStub() |
| 1437 ? FLAG_trace_hydrogen_stubs | 1426 ? FLAG_trace_hydrogen_stubs |
| 1438 : (FLAG_trace_hydrogen && | 1427 : (FLAG_trace_hydrogen && |
| 1439 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); | 1428 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); |
| 1440 return (tracing_on && | 1429 return (tracing_on && |
| 1441 base::OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); | 1430 base::OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); |
| 1442 } | 1431 } |
| 1443 | 1432 |
| 1444 } } // namespace v8::internal | 1433 } } // namespace v8::internal |
| OLD | NEW |