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 #include <memory> | 8 #include <memory> |
9 | 9 |
10 #include "src/asmjs/asm-js.h" | 10 #include "src/asmjs/asm-js.h" |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
253 os << "]" << std::endl; | 253 os << "]" << std::endl; |
254 } | 254 } |
255 | 255 |
256 // Delegate to the underlying implementation. | 256 // Delegate to the underlying implementation. |
257 DCHECK(state() == State::kReadyToPrepare); | 257 DCHECK(state() == State::kReadyToPrepare); |
258 ScopedTimer t(&time_taken_to_prepare_); | 258 ScopedTimer t(&time_taken_to_prepare_); |
259 return UpdateState(PrepareJobImpl(), State::kReadyToExecute); | 259 return UpdateState(PrepareJobImpl(), State::kReadyToExecute); |
260 } | 260 } |
261 | 261 |
262 CompilationJob::Status CompilationJob::ExecuteJob() { | 262 CompilationJob::Status CompilationJob::ExecuteJob() { |
263 DisallowHeapAllocation no_allocation; | 263 std::unique_ptr<DisallowHeapAllocation> no_allocation; |
264 DisallowHandleAllocation no_handles; | 264 std::unique_ptr<DisallowHandleAllocation> no_handles; |
265 DisallowHandleDereference no_deref; | 265 std::unique_ptr<DisallowHandleDereference> no_deref; |
266 DisallowCodeDependencyChange no_dependency_change; | 266 std::unique_ptr<DisallowCodeDependencyChange> no_dependency_change; |
267 if (can_execute_on_background_thread()) { | |
268 no_allocation.reset(new DisallowHeapAllocation()); | |
269 no_handles.reset(new DisallowHandleAllocation()); | |
270 no_deref.reset(new DisallowHandleDereference()); | |
271 no_dependency_change.reset(new DisallowCodeDependencyChange()); | |
272 } else { | |
273 DCHECK(ThreadId::Current().Equals(info()->isolate()->thread_id())); | |
274 } | |
267 | 275 |
268 // Delegate to the underlying implementation. | 276 // Delegate to the underlying implementation. |
269 DCHECK(state() == State::kReadyToExecute); | 277 DCHECK(state() == State::kReadyToExecute); |
270 ScopedTimer t(&time_taken_to_execute_); | 278 ScopedTimer t(&time_taken_to_execute_); |
271 return UpdateState(ExecuteJobImpl(), State::kReadyToFinalize); | 279 return UpdateState(ExecuteJobImpl(), State::kReadyToFinalize); |
272 } | 280 } |
273 | 281 |
274 CompilationJob::Status CompilationJob::FinalizeJob() { | 282 CompilationJob::Status CompilationJob::FinalizeJob() { |
275 DCHECK(ThreadId::Current().Equals(info()->isolate()->thread_id())); | 283 DCHECK(ThreadId::Current().Equals(info()->isolate()->thread_id())); |
276 DisallowCodeDependencyChange no_dependency_change; | 284 DisallowCodeDependencyChange no_dependency_change; |
277 DisallowJavascriptExecution no_js(isolate()); | 285 DisallowJavascriptExecution no_js(isolate()); |
278 DCHECK(!info()->dependencies()->HasAborted()); | 286 DCHECK(!info()->dependencies()->HasAborted()); |
279 | 287 |
280 // Delegate to the underlying implementation. | 288 // Delegate to the underlying implementation. |
281 DCHECK(state() == State::kReadyToFinalize); | 289 DCHECK(state() == State::kReadyToFinalize); |
282 ScopedTimer t(&time_taken_to_finalize_); | 290 ScopedTimer t(&time_taken_to_finalize_); |
283 return UpdateState(FinalizeJobImpl(), State::kSucceeded); | 291 return UpdateState(FinalizeJobImpl(), State::kSucceeded); |
284 } | 292 } |
285 | 293 |
294 void CompilationJob::RecordUnoptimizedCompilationStats() const { | |
295 DCHECK(!info()->IsOptimizing()); | |
296 | |
297 int code_size; | |
298 if (info()->has_bytecode_array()) { | |
299 code_size = info()->bytecode_array()->SizeIncludingMetadata(); | |
300 } else { | |
301 code_size = info()->code()->SizeIncludingMetadata(); | |
302 } | |
303 | |
304 Counters* counters = isolate()->counters(); | |
305 // TODO(4280): Rename counters from "baseline" to "unoptimized" eventually. | |
306 counters->total_baseline_code_size()->Increment(code_size); | |
307 counters->total_baseline_compile_count()->Increment(1); | |
308 | |
309 // TODO(5203): Add timers for each phase of compilation. | |
310 } | |
311 | |
312 void CompilationJob::RecordOptimizedCompilationStats() const { | |
313 DCHECK(info()->IsOptimizing()); | |
314 Handle<JSFunction> function = info()->closure(); | |
315 if (!function->IsOptimized()) { | |
316 // Concurrent recompilation and OSR may race. Increment only once. | |
317 int opt_count = function->shared()->opt_count(); | |
318 function->shared()->set_opt_count(opt_count + 1); | |
319 } | |
320 double ms_creategraph = time_taken_to_prepare_.InMillisecondsF(); | |
321 double ms_optimize = time_taken_to_execute_.InMillisecondsF(); | |
322 double ms_codegen = time_taken_to_finalize_.InMillisecondsF(); | |
323 if (FLAG_trace_opt) { | |
324 PrintF("[optimizing "); | |
325 function->ShortPrint(); | |
326 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize, | |
327 ms_codegen); | |
328 } | |
329 if (FLAG_trace_opt_stats) { | |
330 static double compilation_time = 0.0; | |
331 static int compiled_functions = 0; | |
332 static int code_size = 0; | |
333 | |
334 compilation_time += (ms_creategraph + ms_optimize + ms_codegen); | |
335 compiled_functions++; | |
336 code_size += function->shared()->SourceSize(); | |
337 PrintF("Compiled: %d functions with %d byte source size in %fms.\n", | |
338 compiled_functions, code_size, compilation_time); | |
339 } | |
340 if (FLAG_hydrogen_stats) { | |
341 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_prepare_, | |
342 time_taken_to_execute_, | |
343 time_taken_to_finalize_); | |
344 } | |
345 } | |
346 | |
286 namespace { | 347 namespace { |
287 | 348 |
288 void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object, | 349 void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object, |
289 Handle<Code> code) { | 350 Handle<Code> code) { |
290 Handle<WeakCell> cell = Code::WeakCellFor(code); | 351 Handle<WeakCell> cell = Code::WeakCellFor(code); |
291 Heap* heap = isolate->heap(); | 352 Heap* heap = isolate->heap(); |
292 if (heap->InNewSpace(*object)) { | 353 if (heap->InNewSpace(*object)) { |
293 heap->AddWeakNewSpaceObjectToCodeDependency(object, cell); | 354 heap->AddWeakNewSpaceObjectToCodeDependency(object, cell); |
294 } else { | 355 } else { |
295 Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object)); | 356 Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object)); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
334 isolate->heap()->AddRetainedMap(map); | 395 isolate->heap()->AddRetainedMap(map); |
335 } | 396 } |
336 Map::AddDependentCode(map, DependentCode::kWeakCodeGroup, code); | 397 Map::AddDependentCode(map, DependentCode::kWeakCodeGroup, code); |
337 } | 398 } |
338 for (Handle<HeapObject> object : objects) { | 399 for (Handle<HeapObject> object : objects) { |
339 AddWeakObjectToCodeDependency(isolate, object, code); | 400 AddWeakObjectToCodeDependency(isolate, object, code); |
340 } | 401 } |
341 code->set_can_have_weak_objects(true); | 402 code->set_can_have_weak_objects(true); |
342 } | 403 } |
343 | 404 |
344 void CompilationJob::RecordOptimizationStats() { | |
345 DCHECK(info()->IsOptimizing()); | |
346 Handle<JSFunction> function = info()->closure(); | |
347 if (!function->IsOptimized()) { | |
348 // Concurrent recompilation and OSR may race. Increment only once. | |
349 int opt_count = function->shared()->opt_count(); | |
350 function->shared()->set_opt_count(opt_count + 1); | |
351 } | |
352 double ms_creategraph = time_taken_to_prepare_.InMillisecondsF(); | |
353 double ms_optimize = time_taken_to_execute_.InMillisecondsF(); | |
354 double ms_codegen = time_taken_to_finalize_.InMillisecondsF(); | |
355 if (FLAG_trace_opt) { | |
356 PrintF("[optimizing "); | |
357 function->ShortPrint(); | |
358 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize, | |
359 ms_codegen); | |
360 } | |
361 if (FLAG_trace_opt_stats) { | |
362 static double compilation_time = 0.0; | |
363 static int compiled_functions = 0; | |
364 static int code_size = 0; | |
365 | |
366 compilation_time += (ms_creategraph + ms_optimize + ms_codegen); | |
367 compiled_functions++; | |
368 code_size += function->shared()->SourceSize(); | |
369 PrintF("Compiled: %d functions with %d byte source size in %fms.\n", | |
370 compiled_functions, code_size, compilation_time); | |
371 } | |
372 if (FLAG_hydrogen_stats) { | |
373 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_prepare_, | |
374 time_taken_to_execute_, | |
375 time_taken_to_finalize_); | |
376 } | |
377 } | |
378 | |
379 // ---------------------------------------------------------------------------- | 405 // ---------------------------------------------------------------------------- |
380 // Local helper methods that make up the compilation pipeline. | 406 // Local helper methods that make up the compilation pipeline. |
381 | 407 |
382 namespace { | 408 namespace { |
383 | 409 |
384 bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) { | 410 bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) { |
385 return shared->is_toplevel() && shared->script()->IsScript() && | 411 return shared->is_toplevel() && shared->script()->IsScript() && |
386 Script::cast(shared->script())->compilation_type() == | 412 Script::cast(shared->script())->compilation_type() == |
387 Script::COMPILATION_TYPE_EVAL; | 413 Script::COMPILATION_TYPE_EVAL; |
388 } | 414 } |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
459 // Checks whether top level functions should be passed by the filter. | 485 // Checks whether top level functions should be passed by the filter. |
460 if (info->shared_info()->is_toplevel()) { | 486 if (info->shared_info()->is_toplevel()) { |
461 Vector<const char> filter = CStrVector(FLAG_ignition_filter); | 487 Vector<const char> filter = CStrVector(FLAG_ignition_filter); |
462 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*'); | 488 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*'); |
463 } | 489 } |
464 | 490 |
465 // Finally respect the filter. | 491 // Finally respect the filter. |
466 return info->shared_info()->PassesFilter(FLAG_ignition_filter); | 492 return info->shared_info()->PassesFilter(FLAG_ignition_filter); |
467 } | 493 } |
468 | 494 |
469 int CodeAndMetadataSize(CompilationInfo* info) { | 495 CompilationJob* GetUnoptimizedCompilationJob(CompilationInfo* info) { |
470 if (info->has_bytecode_array()) { | 496 // Function should have been parsed and analyzed before creating a compilation |
471 return info->bytecode_array()->SizeIncludingMetadata(); | 497 // job. |
498 DCHECK_NOT_NULL(info->literal()); | |
499 DCHECK_NOT_NULL(info->scope()); | |
500 | |
501 EnsureFeedbackMetadata(info); | |
502 if (ShouldUseIgnition(info)) { | |
503 return interpreter::Interpreter::NewCompilationJob(info); | |
504 } else { | |
505 return FullCodeGenerator::NewCompilationJob(info); | |
472 } | 506 } |
473 return info->code()->SizeIncludingMetadata(); | |
474 } | 507 } |
475 | 508 |
476 bool GenerateUnoptimizedCode(CompilationInfo* info) { | 509 bool GenerateUnoptimizedCode(CompilationInfo* info) { |
477 bool success; | |
478 EnsureFeedbackMetadata(info); | |
479 if (FLAG_validate_asm && info->scope()->asm_module() && | 510 if (FLAG_validate_asm && info->scope()->asm_module() && |
480 !info->shared_info()->is_asm_wasm_broken()) { | 511 !info->shared_info()->is_asm_wasm_broken()) { |
512 EnsureFeedbackMetadata(info); | |
481 MaybeHandle<FixedArray> wasm_data; | 513 MaybeHandle<FixedArray> wasm_data; |
482 wasm_data = AsmJs::ConvertAsmToWasm(info->parse_info()); | 514 wasm_data = AsmJs::ConvertAsmToWasm(info->parse_info()); |
483 if (!wasm_data.is_null()) { | 515 if (!wasm_data.is_null()) { |
484 info->shared_info()->set_asm_wasm_data(*wasm_data.ToHandleChecked()); | 516 info->shared_info()->set_asm_wasm_data(*wasm_data.ToHandleChecked()); |
485 info->SetCode(info->isolate()->builtins()->InstantiateAsmJs()); | 517 info->SetCode(info->isolate()->builtins()->InstantiateAsmJs()); |
486 return true; | 518 return true; |
487 } | 519 } |
488 } | 520 } |
489 if (ShouldUseIgnition(info)) { | 521 |
490 success = interpreter::Interpreter::MakeBytecode(info); | 522 std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info)); |
491 } else { | 523 if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false; |
492 success = FullCodeGenerator::MakeCode(info); | 524 if (job->ExecuteJob() != CompilationJob::SUCCEEDED) return false; |
493 } | 525 if (job->FinalizeJob() != CompilationJob::SUCCEEDED) return false; |
494 if (success) { | 526 job->RecordCompilationStats(); |
495 Isolate* isolate = info->isolate(); | 527 return true; |
496 Counters* counters = isolate->counters(); | |
497 // TODO(4280): Rename counters from "baseline" to "unoptimized" eventually. | |
498 counters->total_baseline_code_size()->Increment(CodeAndMetadataSize(info)); | |
499 counters->total_baseline_compile_count()->Increment(1); | |
500 } | |
501 return success; | |
502 } | 528 } |
503 | 529 |
504 bool CompileUnoptimizedCode(CompilationInfo* info) { | 530 bool CompileUnoptimizedCode(CompilationInfo* info) { |
505 DCHECK(AllowCompilation::IsAllowed(info->isolate())); | 531 DCHECK(AllowCompilation::IsAllowed(info->isolate())); |
506 if (!Compiler::Analyze(info->parse_info()) || | 532 if (!Compiler::Analyze(info->parse_info()) || |
507 !GenerateUnoptimizedCode(info)) { | 533 !GenerateUnoptimizedCode(info)) { |
508 Isolate* isolate = info->isolate(); | 534 Isolate* isolate = info->isolate(); |
509 if (!isolate->has_pending_exception()) isolate->StackOverflow(); | 535 if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
510 return false; | 536 return false; |
511 } | 537 } |
(...skipping 15 matching lines...) Expand all Loading... | |
527 shared->ClearBytecodeArray(); | 553 shared->ClearBytecodeArray(); |
528 } | 554 } |
529 DCHECK(!info->code().is_null()); | 555 DCHECK(!info->code().is_null()); |
530 shared->ReplaceCode(*info->code()); | 556 shared->ReplaceCode(*info->code()); |
531 if (info->has_bytecode_array()) { | 557 if (info->has_bytecode_array()) { |
532 DCHECK(!shared->HasBytecodeArray()); // Only compiled once. | 558 DCHECK(!shared->HasBytecodeArray()); // Only compiled once. |
533 shared->set_bytecode_array(*info->bytecode_array()); | 559 shared->set_bytecode_array(*info->bytecode_array()); |
534 } | 560 } |
535 } | 561 } |
536 | 562 |
563 void InstallUnoptimizedCode(CompilationInfo* info) { | |
564 Handle<SharedFunctionInfo> shared = info->shared_info(); | |
565 | |
566 // Update the shared function info with the scope info. | |
567 InstallSharedScopeInfo(info, shared); | |
568 | |
569 // Install compilation result on the shared function info | |
570 InstallSharedCompilationResult(info, shared); | |
571 | |
572 // Record the function compilation event. | |
573 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); | |
574 } | |
575 | |
537 MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode(CompilationInfo* info) { | 576 MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode(CompilationInfo* info) { |
538 VMState<COMPILER> state(info->isolate()); | 577 VMState<COMPILER> state(info->isolate()); |
539 PostponeInterruptsScope postpone(info->isolate()); | 578 PostponeInterruptsScope postpone(info->isolate()); |
540 | 579 |
541 // Create a canonical handle scope before internalizing parsed values if | 580 // Create a canonical handle scope before internalizing parsed values if |
542 // compiling bytecode. This is required for off-thread bytecode generation. | 581 // compiling bytecode. This is required for off-thread bytecode generation. |
543 std::unique_ptr<CanonicalHandleScope> canonical; | 582 std::unique_ptr<CanonicalHandleScope> canonical; |
544 if (FLAG_ignition) canonical.reset(new CanonicalHandleScope(info->isolate())); | 583 if (FLAG_ignition) canonical.reset(new CanonicalHandleScope(info->isolate())); |
545 | 584 |
546 // Parse and update CompilationInfo with the results. | 585 // Parse and update CompilationInfo with the results. |
547 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>(); | 586 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>(); |
548 Handle<SharedFunctionInfo> shared = info->shared_info(); | 587 DCHECK_EQ(info->shared_info()->language_mode(), |
549 DCHECK_EQ(shared->language_mode(), info->literal()->language_mode()); | 588 info->literal()->language_mode()); |
550 | 589 |
551 // Compile either unoptimized code or bytecode for the interpreter. | 590 // Compile either unoptimized code or bytecode for the interpreter. |
552 if (!CompileUnoptimizedCode(info)) return MaybeHandle<Code>(); | 591 if (!CompileUnoptimizedCode(info)) return MaybeHandle<Code>(); |
553 | 592 |
554 // Update the shared function info with the scope info. | 593 InstallUnoptimizedCode(info); |
555 InstallSharedScopeInfo(info, shared); | |
556 | |
557 // Install compilation result on the shared function info | |
558 InstallSharedCompilationResult(info, shared); | |
559 | |
560 // Record the function compilation event. | |
561 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); | |
562 | 594 |
563 return info->code(); | 595 return info->code(); |
564 } | 596 } |
565 | 597 |
598 CompilationJob::Status FinalizeUnoptimizedCompilationJob(CompilationJob* job) { | |
599 CompilationJob::Status status = job->FinalizeJob(); | |
600 if (status == CompilationJob::SUCCEEDED) { | |
601 InstallUnoptimizedCode(job->info()); | |
Michael Starzinger
2016/08/24 07:29:32
This will eventually cause an implicit tier-down o
rmcilroy
2016/08/24 09:26:58
Yes good point. We should make sure the compile di
| |
602 } | |
603 return status; | |
604 } | |
605 | |
566 MUST_USE_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeMap( | 606 MUST_USE_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeMap( |
567 Handle<JSFunction> function, BailoutId osr_ast_id) { | 607 Handle<JSFunction> function, BailoutId osr_ast_id) { |
568 Handle<SharedFunctionInfo> shared(function->shared()); | 608 Handle<SharedFunctionInfo> shared(function->shared()); |
569 DisallowHeapAllocation no_gc; | 609 DisallowHeapAllocation no_gc; |
570 CodeAndLiterals cached = shared->SearchOptimizedCodeMap( | 610 CodeAndLiterals cached = shared->SearchOptimizedCodeMap( |
571 function->context()->native_context(), osr_ast_id); | 611 function->context()->native_context(), osr_ast_id); |
572 if (cached.code != nullptr) { | 612 if (cached.code != nullptr) { |
573 // Caching of optimized code enabled and optimized code found. | 613 // Caching of optimized code enabled and optimized code found. |
574 if (cached.literals != nullptr) function->set_literals(cached.literals); | 614 if (cached.literals != nullptr) function->set_literals(cached.literals); |
575 DCHECK(!cached.code->marked_for_deoptimization()); | 615 DCHECK(!cached.code->marked_for_deoptimization()); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
677 job->FinalizeJob() != CompilationJob::SUCCEEDED) { | 717 job->FinalizeJob() != CompilationJob::SUCCEEDED) { |
678 if (FLAG_trace_opt) { | 718 if (FLAG_trace_opt) { |
679 PrintF("[aborted optimizing "); | 719 PrintF("[aborted optimizing "); |
680 info->closure()->ShortPrint(); | 720 info->closure()->ShortPrint(); |
681 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); | 721 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); |
682 } | 722 } |
683 return false; | 723 return false; |
684 } | 724 } |
685 | 725 |
686 // Success! | 726 // Success! |
687 job->RecordOptimizationStats(); | 727 job->RecordCompilationStats(); |
688 DCHECK(!isolate->has_pending_exception()); | 728 DCHECK(!isolate->has_pending_exception()); |
689 InsertCodeIntoOptimizedCodeMap(info); | 729 InsertCodeIntoOptimizedCodeMap(info); |
690 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); | 730 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); |
691 return true; | 731 return true; |
692 } | 732 } |
693 | 733 |
694 bool GetOptimizedCodeLater(CompilationJob* job) { | 734 bool GetOptimizedCodeLater(CompilationJob* job) { |
695 CompilationInfo* info = job->info(); | 735 CompilationInfo* info = job->info(); |
696 Isolate* isolate = info->isolate(); | 736 Isolate* isolate = info->isolate(); |
697 | 737 |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
837 return isolate->builtins()->InOptimizationQueue(); | 877 return isolate->builtins()->InOptimizationQueue(); |
838 } | 878 } |
839 } else { | 879 } else { |
840 if (GetOptimizedCodeNow(job.get())) return info->code(); | 880 if (GetOptimizedCodeNow(job.get())) return info->code(); |
841 } | 881 } |
842 | 882 |
843 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); | 883 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); |
844 return MaybeHandle<Code>(); | 884 return MaybeHandle<Code>(); |
845 } | 885 } |
846 | 886 |
887 CompilationJob::Status FinalizeOptimizedCompilationJob(CompilationJob* job) { | |
888 CompilationInfo* info = job->info(); | |
889 Isolate* isolate = info->isolate(); | |
890 | |
891 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); | |
892 RuntimeCallTimerScope runtimeTimer(isolate, | |
893 &RuntimeCallStats::RecompileSynchronous); | |
894 TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_SCOPED( | |
895 isolate, &tracing::TraceEventStatsTable::RecompileSynchronous); | |
896 | |
897 Handle<SharedFunctionInfo> shared = info->shared_info(); | |
898 shared->code()->set_profiler_ticks(0); | |
899 | |
900 DCHECK(!shared->HasDebugInfo()); | |
901 | |
902 // 1) Optimization on the concurrent thread may have failed. | |
903 // 2) The function may have already been optimized by OSR. Simply continue. | |
904 // Except when OSR already disabled optimization for some reason. | |
905 // 3) The code may have already been invalidated due to dependency change. | |
906 // 4) Code generation may have failed. | |
907 if (job->state() == CompilationJob::State::kReadyToFinalize) { | |
908 if (shared->optimization_disabled()) { | |
909 job->RetryOptimization(kOptimizationDisabled); | |
910 } else if (info->dependencies()->HasAborted()) { | |
911 job->RetryOptimization(kBailedOutDueToDependencyChange); | |
912 } else if (job->FinalizeJob() == CompilationJob::SUCCEEDED) { | |
913 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); | |
914 if (shared | |
915 ->SearchOptimizedCodeMap(info->context()->native_context(), | |
916 info->osr_ast_id()) | |
917 .code == nullptr) { | |
918 InsertCodeIntoOptimizedCodeMap(info); | |
919 } | |
920 if (FLAG_trace_opt) { | |
921 PrintF("[completed optimizing "); | |
922 info->closure()->ShortPrint(); | |
923 PrintF("]\n"); | |
924 } | |
925 info->closure()->ReplaceCode(*info->code()); | |
926 return CompilationJob::SUCCEEDED; | |
927 } | |
928 } | |
929 | |
930 DCHECK(job->state() == CompilationJob::State::kFailed); | |
931 if (FLAG_trace_opt) { | |
932 PrintF("[aborted optimizing "); | |
933 info->closure()->ShortPrint(); | |
934 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); | |
935 } | |
936 info->closure()->ReplaceCode(shared->code()); | |
937 return CompilationJob::FAILED; | |
938 } | |
939 | |
847 class InterpreterActivationsFinder : public ThreadVisitor, | 940 class InterpreterActivationsFinder : public ThreadVisitor, |
848 public OptimizedFunctionVisitor { | 941 public OptimizedFunctionVisitor { |
849 public: | 942 public: |
850 explicit InterpreterActivationsFinder(SharedFunctionInfo* shared) | 943 explicit InterpreterActivationsFinder(SharedFunctionInfo* shared) |
851 : shared_(shared), has_activations_(false) {} | 944 : shared_(shared), has_activations_(false) {} |
852 | 945 |
853 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { | 946 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { |
854 Address* activation_pc_address = nullptr; | 947 Address* activation_pc_address = nullptr; |
855 JavaScriptFrameIterator it(isolate, top); | 948 JavaScriptFrameIterator it(isolate, top); |
856 for (; !it.done(); it.Advance()) { | 949 for (; !it.done(); it.Advance()) { |
(...skipping 1031 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1888 } | 1981 } |
1889 | 1982 |
1890 MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function, | 1983 MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function, |
1891 BailoutId osr_ast_id, | 1984 BailoutId osr_ast_id, |
1892 JavaScriptFrame* osr_frame) { | 1985 JavaScriptFrame* osr_frame) { |
1893 DCHECK(!osr_ast_id.IsNone()); | 1986 DCHECK(!osr_ast_id.IsNone()); |
1894 DCHECK_NOT_NULL(osr_frame); | 1987 DCHECK_NOT_NULL(osr_frame); |
1895 return GetOptimizedCode(function, NOT_CONCURRENT, osr_ast_id, osr_frame); | 1988 return GetOptimizedCode(function, NOT_CONCURRENT, osr_ast_id, osr_frame); |
1896 } | 1989 } |
1897 | 1990 |
1898 void Compiler::FinalizeCompilationJob(CompilationJob* raw_job) { | 1991 CompilationJob* Compiler::PrepareUnoptimizedCompilationJob( |
1992 CompilationInfo* info) { | |
1993 VMState<COMPILER> state(info->isolate()); | |
1994 std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info)); | |
1995 if (job->PrepareJob() != CompilationJob::SUCCEEDED) { | |
1996 return nullptr; | |
1997 } | |
1998 return job.release(); | |
1999 } | |
2000 | |
2001 bool Compiler::FinalizeCompilationJob(CompilationJob* raw_job) { | |
1899 // Take ownership of compilation job. Deleting job also tears down the zone. | 2002 // Take ownership of compilation job. Deleting job also tears down the zone. |
1900 std::unique_ptr<CompilationJob> job(raw_job); | 2003 std::unique_ptr<CompilationJob> job(raw_job); |
1901 CompilationInfo* info = job->info(); | |
1902 Isolate* isolate = info->isolate(); | |
1903 | 2004 |
1904 VMState<COMPILER> state(isolate); | 2005 VMState<COMPILER> state(job->info()->isolate()); |
1905 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); | 2006 CompilationJob::Status status; |
1906 RuntimeCallTimerScope runtimeTimer(isolate, | 2007 if (job->info()->IsOptimizing()) { |
1907 &RuntimeCallStats::RecompileSynchronous); | 2008 status = FinalizeOptimizedCompilationJob(job.get()); |
1908 TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_SCOPED( | 2009 } else { |
1909 isolate, &tracing::TraceEventStatsTable::RecompileSynchronous); | 2010 status = FinalizeUnoptimizedCompilationJob(job.get()); |
1910 | |
1911 Handle<SharedFunctionInfo> shared = info->shared_info(); | |
1912 shared->code()->set_profiler_ticks(0); | |
1913 | |
1914 DCHECK(!shared->HasDebugInfo()); | |
1915 | |
1916 // 1) Optimization on the concurrent thread may have failed. | |
1917 // 2) The function may have already been optimized by OSR. Simply continue. | |
1918 // Except when OSR already disabled optimization for some reason. | |
1919 // 3) The code may have already been invalidated due to dependency change. | |
1920 // 4) Code generation may have failed. | |
1921 if (job->state() == CompilationJob::State::kReadyToFinalize) { | |
1922 if (shared->optimization_disabled()) { | |
1923 job->RetryOptimization(kOptimizationDisabled); | |
1924 } else if (info->dependencies()->HasAborted()) { | |
1925 job->RetryOptimization(kBailedOutDueToDependencyChange); | |
1926 } else if (job->FinalizeJob() == CompilationJob::SUCCEEDED) { | |
1927 job->RecordOptimizationStats(); | |
1928 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); | |
1929 if (shared->SearchOptimizedCodeMap(info->context()->native_context(), | |
1930 info->osr_ast_id()).code == nullptr) { | |
1931 InsertCodeIntoOptimizedCodeMap(info); | |
1932 } | |
1933 if (FLAG_trace_opt) { | |
1934 PrintF("[completed optimizing "); | |
1935 info->closure()->ShortPrint(); | |
1936 PrintF("]\n"); | |
1937 } | |
1938 info->closure()->ReplaceCode(*info->code()); | |
1939 return; | |
1940 } | |
1941 } | 2011 } |
1942 | 2012 if (status == CompilationJob::SUCCEEDED) { |
1943 DCHECK(job->state() == CompilationJob::State::kFailed); | 2013 job->RecordCompilationStats(); |
1944 if (FLAG_trace_opt) { | |
1945 PrintF("[aborted optimizing "); | |
1946 info->closure()->ShortPrint(); | |
1947 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); | |
1948 } | 2014 } |
1949 info->closure()->ReplaceCode(shared->code()); | 2015 return status == CompilationJob::SUCCEEDED; |
1950 } | 2016 } |
1951 | 2017 |
1952 void Compiler::PostInstantiation(Handle<JSFunction> function, | 2018 void Compiler::PostInstantiation(Handle<JSFunction> function, |
1953 PretenureFlag pretenure) { | 2019 PretenureFlag pretenure) { |
1954 Handle<SharedFunctionInfo> shared(function->shared()); | 2020 Handle<SharedFunctionInfo> shared(function->shared()); |
1955 | 2021 |
1956 if (FLAG_always_opt && shared->allows_lazy_compilation()) { | 2022 if (FLAG_always_opt && shared->allows_lazy_compilation()) { |
1957 function->MarkForOptimization(); | 2023 function->MarkForOptimization(); |
1958 } | 2024 } |
1959 | 2025 |
(...skipping 10 matching lines...) Expand all Loading... | |
1970 DCHECK(shared->is_compiled()); | 2036 DCHECK(shared->is_compiled()); |
1971 function->set_literals(cached.literals); | 2037 function->set_literals(cached.literals); |
1972 } else if (shared->is_compiled()) { | 2038 } else if (shared->is_compiled()) { |
1973 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. | 2039 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. |
1974 JSFunction::EnsureLiterals(function); | 2040 JSFunction::EnsureLiterals(function); |
1975 } | 2041 } |
1976 } | 2042 } |
1977 | 2043 |
1978 } // namespace internal | 2044 } // namespace internal |
1979 } // namespace v8 | 2045 } // namespace v8 |
OLD | NEW |