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 |