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 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 : SourcePositionTableBuilder::RECORD_SOURCE_POSITIONS; | 233 : SourcePositionTableBuilder::RECORD_SOURCE_POSITIONS; |
234 } | 234 } |
235 | 235 |
236 bool CompilationInfo::ExpectsJSReceiverAsReceiver() { | 236 bool CompilationInfo::ExpectsJSReceiverAsReceiver() { |
237 return is_sloppy(parse_info()->language_mode()) && !parse_info()->is_native(); | 237 return is_sloppy(parse_info()->language_mode()) && !parse_info()->is_native(); |
238 } | 238 } |
239 | 239 |
240 // ---------------------------------------------------------------------------- | 240 // ---------------------------------------------------------------------------- |
241 // Implementation of CompilationJob | 241 // Implementation of CompilationJob |
242 | 242 |
243 CompilationJob::Status CompilationJob::PrepareJob() { | 243 CompilationJob::Status CompilationJob::CreateGraph() { |
244 DCHECK(ThreadId::Current().Equals(info()->isolate()->thread_id())); | |
245 DisallowJavascriptExecution no_js(isolate()); | 244 DisallowJavascriptExecution no_js(isolate()); |
| 245 DCHECK(info()->IsOptimizing()); |
246 | 246 |
247 if (FLAG_trace_opt && info()->IsOptimizing()) { | 247 if (FLAG_trace_opt) { |
248 OFStream os(stdout); | 248 OFStream os(stdout); |
249 os << "[compiling method " << Brief(*info()->closure()) << " using " | 249 os << "[compiling method " << Brief(*info()->closure()) << " using " |
250 << compiler_name_; | 250 << compiler_name_; |
251 if (info()->is_osr()) os << " OSR"; | 251 if (info()->is_osr()) os << " OSR"; |
252 os << "]" << std::endl; | 252 os << "]" << std::endl; |
253 } | 253 } |
254 | 254 |
255 // Delegate to the underlying implementation. | 255 // Delegate to the underlying implementation. |
256 DCHECK(state() == State::kReadyToPrepare); | 256 DCHECK_EQ(SUCCEEDED, last_status()); |
257 ScopedTimer t(&time_taken_to_prepare_); | 257 ScopedTimer t(&time_taken_to_create_graph_); |
258 return UpdateState(PrepareJobImpl(), State::kReadyToExecute); | 258 return SetLastStatus(CreateGraphImpl()); |
259 } | 259 } |
260 | 260 |
261 CompilationJob::Status CompilationJob::ExecuteJob() { | 261 CompilationJob::Status CompilationJob::OptimizeGraph() { |
262 DisallowHeapAllocation no_allocation; | 262 DisallowHeapAllocation no_allocation; |
263 DisallowHandleAllocation no_handles; | 263 DisallowHandleAllocation no_handles; |
264 DisallowHandleDereference no_deref; | 264 DisallowHandleDereference no_deref; |
265 DisallowCodeDependencyChange no_dependency_change; | 265 DisallowCodeDependencyChange no_dependency_change; |
266 | 266 |
267 // Delegate to the underlying implementation. | 267 // Delegate to the underlying implementation. |
268 DCHECK(state() == State::kReadyToExecute); | 268 DCHECK_EQ(SUCCEEDED, last_status()); |
269 ScopedTimer t(&time_taken_to_execute_); | 269 ScopedTimer t(&time_taken_to_optimize_); |
270 return UpdateState(ExecuteJobImpl(), State::kReadyToFinalize); | 270 return SetLastStatus(OptimizeGraphImpl()); |
271 } | 271 } |
272 | 272 |
273 CompilationJob::Status CompilationJob::FinalizeJob() { | 273 CompilationJob::Status CompilationJob::GenerateCode() { |
274 DCHECK(ThreadId::Current().Equals(info()->isolate()->thread_id())); | |
275 DisallowCodeDependencyChange no_dependency_change; | 274 DisallowCodeDependencyChange no_dependency_change; |
276 DisallowJavascriptExecution no_js(isolate()); | 275 DisallowJavascriptExecution no_js(isolate()); |
277 DCHECK(!info()->dependencies()->HasAborted()); | 276 DCHECK(!info()->dependencies()->HasAborted()); |
278 | 277 |
279 // Delegate to the underlying implementation. | 278 // Delegate to the underlying implementation. |
280 DCHECK(state() == State::kReadyToFinalize); | 279 DCHECK_EQ(SUCCEEDED, last_status()); |
281 ScopedTimer t(&time_taken_to_finalize_); | 280 ScopedTimer t(&time_taken_to_codegen_); |
282 return UpdateState(FinalizeJobImpl(), State::kSucceeded); | 281 return SetLastStatus(GenerateCodeImpl()); |
283 } | 282 } |
284 | 283 |
| 284 |
285 namespace { | 285 namespace { |
286 | 286 |
287 void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object, | 287 void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object, |
288 Handle<Code> code) { | 288 Handle<Code> code) { |
289 Handle<WeakCell> cell = Code::WeakCellFor(code); | 289 Handle<WeakCell> cell = Code::WeakCellFor(code); |
290 Heap* heap = isolate->heap(); | 290 Heap* heap = isolate->heap(); |
291 if (heap->InNewSpace(*object)) { | 291 if (heap->InNewSpace(*object)) { |
292 heap->AddWeakNewSpaceObjectToCodeDependency(object, cell); | 292 heap->AddWeakNewSpaceObjectToCodeDependency(object, cell); |
293 } else { | 293 } else { |
294 Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object)); | 294 Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object)); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 } | 334 } |
335 Map::AddDependentCode(map, DependentCode::kWeakCodeGroup, code); | 335 Map::AddDependentCode(map, DependentCode::kWeakCodeGroup, code); |
336 } | 336 } |
337 for (Handle<HeapObject> object : objects) { | 337 for (Handle<HeapObject> object : objects) { |
338 AddWeakObjectToCodeDependency(isolate, object, code); | 338 AddWeakObjectToCodeDependency(isolate, object, code); |
339 } | 339 } |
340 code->set_can_have_weak_objects(true); | 340 code->set_can_have_weak_objects(true); |
341 } | 341 } |
342 | 342 |
343 void CompilationJob::RecordOptimizationStats() { | 343 void CompilationJob::RecordOptimizationStats() { |
344 DCHECK(info()->IsOptimizing()); | |
345 Handle<JSFunction> function = info()->closure(); | 344 Handle<JSFunction> function = info()->closure(); |
346 if (!function->IsOptimized()) { | 345 if (!function->IsOptimized()) { |
347 // Concurrent recompilation and OSR may race. Increment only once. | 346 // Concurrent recompilation and OSR may race. Increment only once. |
348 int opt_count = function->shared()->opt_count(); | 347 int opt_count = function->shared()->opt_count(); |
349 function->shared()->set_opt_count(opt_count + 1); | 348 function->shared()->set_opt_count(opt_count + 1); |
350 } | 349 } |
351 double ms_creategraph = time_taken_to_prepare_.InMillisecondsF(); | 350 double ms_creategraph = time_taken_to_create_graph_.InMillisecondsF(); |
352 double ms_optimize = time_taken_to_execute_.InMillisecondsF(); | 351 double ms_optimize = time_taken_to_optimize_.InMillisecondsF(); |
353 double ms_codegen = time_taken_to_finalize_.InMillisecondsF(); | 352 double ms_codegen = time_taken_to_codegen_.InMillisecondsF(); |
354 if (FLAG_trace_opt) { | 353 if (FLAG_trace_opt) { |
355 PrintF("[optimizing "); | 354 PrintF("[optimizing "); |
356 function->ShortPrint(); | 355 function->ShortPrint(); |
357 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize, | 356 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize, |
358 ms_codegen); | 357 ms_codegen); |
359 } | 358 } |
360 if (FLAG_trace_opt_stats) { | 359 if (FLAG_trace_opt_stats) { |
361 static double compilation_time = 0.0; | 360 static double compilation_time = 0.0; |
362 static int compiled_functions = 0; | 361 static int compiled_functions = 0; |
363 static int code_size = 0; | 362 static int code_size = 0; |
364 | 363 |
365 compilation_time += (ms_creategraph + ms_optimize + ms_codegen); | 364 compilation_time += (ms_creategraph + ms_optimize + ms_codegen); |
366 compiled_functions++; | 365 compiled_functions++; |
367 code_size += function->shared()->SourceSize(); | 366 code_size += function->shared()->SourceSize(); |
368 PrintF("Compiled: %d functions with %d byte source size in %fms.\n", | 367 PrintF("Compiled: %d functions with %d byte source size in %fms.\n", |
369 compiled_functions, code_size, compilation_time); | 368 compiled_functions, |
| 369 code_size, |
| 370 compilation_time); |
370 } | 371 } |
371 if (FLAG_hydrogen_stats) { | 372 if (FLAG_hydrogen_stats) { |
372 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_prepare_, | 373 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_, |
373 time_taken_to_execute_, | 374 time_taken_to_optimize_, |
374 time_taken_to_finalize_); | 375 time_taken_to_codegen_); |
375 } | 376 } |
376 } | 377 } |
377 | 378 |
378 // ---------------------------------------------------------------------------- | 379 // ---------------------------------------------------------------------------- |
379 // Local helper methods that make up the compilation pipeline. | 380 // Local helper methods that make up the compilation pipeline. |
380 | 381 |
381 namespace { | 382 namespace { |
382 | 383 |
383 bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) { | 384 bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) { |
384 return shared->is_toplevel() && shared->script()->IsScript() && | 385 return shared->is_toplevel() && shared->script()->IsScript() && |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
665 } | 666 } |
666 | 667 |
667 JSFunction::EnsureLiterals(info->closure()); | 668 JSFunction::EnsureLiterals(info->closure()); |
668 | 669 |
669 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate); | 670 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate); |
670 RuntimeCallTimerScope runtimeTimer(isolate, | 671 RuntimeCallTimerScope runtimeTimer(isolate, |
671 &RuntimeCallStats::RecompileSynchronous); | 672 &RuntimeCallStats::RecompileSynchronous); |
672 TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_SCOPED( | 673 TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_SCOPED( |
673 isolate, &tracing::TraceEventStatsTable::RecompileSynchronous); | 674 isolate, &tracing::TraceEventStatsTable::RecompileSynchronous); |
674 | 675 |
675 if (job->PrepareJob() != CompilationJob::SUCCEEDED || | 676 if (job->CreateGraph() != CompilationJob::SUCCEEDED || |
676 job->ExecuteJob() != CompilationJob::SUCCEEDED || | 677 job->OptimizeGraph() != CompilationJob::SUCCEEDED || |
677 job->FinalizeJob() != CompilationJob::SUCCEEDED) { | 678 job->GenerateCode() != CompilationJob::SUCCEEDED) { |
678 if (FLAG_trace_opt) { | 679 if (FLAG_trace_opt) { |
679 PrintF("[aborted optimizing "); | 680 PrintF("[aborted optimizing "); |
680 info->closure()->ShortPrint(); | 681 info->closure()->ShortPrint(); |
681 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); | 682 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); |
682 } | 683 } |
683 return false; | 684 return false; |
684 } | 685 } |
685 | 686 |
686 // Success! | 687 // Success! |
687 job->RecordOptimizationStats(); | 688 job->RecordOptimizationStats(); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
728 // Reopen handles in the new CompilationHandleScope. | 729 // Reopen handles in the new CompilationHandleScope. |
729 info->ReopenHandlesInNewHandleScope(); | 730 info->ReopenHandlesInNewHandleScope(); |
730 info->parse_info()->ReopenHandlesInNewHandleScope(); | 731 info->parse_info()->ReopenHandlesInNewHandleScope(); |
731 | 732 |
732 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); | 733 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); |
733 RuntimeCallTimerScope runtimeTimer(info->isolate(), | 734 RuntimeCallTimerScope runtimeTimer(info->isolate(), |
734 &RuntimeCallStats::RecompileSynchronous); | 735 &RuntimeCallStats::RecompileSynchronous); |
735 TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_SCOPED( | 736 TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_SCOPED( |
736 isolate, &tracing::TraceEventStatsTable::RecompileSynchronous); | 737 isolate, &tracing::TraceEventStatsTable::RecompileSynchronous); |
737 | 738 |
738 if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false; | 739 if (job->CreateGraph() != CompilationJob::SUCCEEDED) return false; |
739 isolate->optimizing_compile_dispatcher()->QueueForOptimization(job); | 740 isolate->optimizing_compile_dispatcher()->QueueForOptimization(job); |
740 | 741 |
741 if (FLAG_trace_concurrent_recompilation) { | 742 if (FLAG_trace_concurrent_recompilation) { |
742 PrintF(" ** Queued "); | 743 PrintF(" ** Queued "); |
743 info->closure()->ShortPrint(); | 744 info->closure()->ShortPrint(); |
744 PrintF(" for concurrent optimization.\n"); | 745 PrintF(" for concurrent optimization.\n"); |
745 } | 746 } |
746 return true; | 747 return true; |
747 } | 748 } |
748 | 749 |
(...skipping 1155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1904 Handle<SharedFunctionInfo> shared = info->shared_info(); | 1905 Handle<SharedFunctionInfo> shared = info->shared_info(); |
1905 shared->code()->set_profiler_ticks(0); | 1906 shared->code()->set_profiler_ticks(0); |
1906 | 1907 |
1907 DCHECK(!shared->HasDebugInfo()); | 1908 DCHECK(!shared->HasDebugInfo()); |
1908 | 1909 |
1909 // 1) Optimization on the concurrent thread may have failed. | 1910 // 1) Optimization on the concurrent thread may have failed. |
1910 // 2) The function may have already been optimized by OSR. Simply continue. | 1911 // 2) The function may have already been optimized by OSR. Simply continue. |
1911 // Except when OSR already disabled optimization for some reason. | 1912 // Except when OSR already disabled optimization for some reason. |
1912 // 3) The code may have already been invalidated due to dependency change. | 1913 // 3) The code may have already been invalidated due to dependency change. |
1913 // 4) Code generation may have failed. | 1914 // 4) Code generation may have failed. |
1914 if (job->state() == CompilationJob::State::kReadyToFinalize) { | 1915 if (job->last_status() == CompilationJob::SUCCEEDED) { |
1915 if (shared->optimization_disabled()) { | 1916 if (shared->optimization_disabled()) { |
1916 job->RetryOptimization(kOptimizationDisabled); | 1917 job->RetryOptimization(kOptimizationDisabled); |
1917 } else if (info->dependencies()->HasAborted()) { | 1918 } else if (info->dependencies()->HasAborted()) { |
1918 job->RetryOptimization(kBailedOutDueToDependencyChange); | 1919 job->RetryOptimization(kBailedOutDueToDependencyChange); |
1919 } else if (job->FinalizeJob() == CompilationJob::SUCCEEDED) { | 1920 } else if (job->GenerateCode() == CompilationJob::SUCCEEDED) { |
1920 job->RecordOptimizationStats(); | 1921 job->RecordOptimizationStats(); |
1921 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); | 1922 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); |
1922 if (shared->SearchOptimizedCodeMap(info->context()->native_context(), | 1923 if (shared->SearchOptimizedCodeMap(info->context()->native_context(), |
1923 info->osr_ast_id()).code == nullptr) { | 1924 info->osr_ast_id()).code == nullptr) { |
1924 InsertCodeIntoOptimizedCodeMap(info); | 1925 InsertCodeIntoOptimizedCodeMap(info); |
1925 } | 1926 } |
1926 if (FLAG_trace_opt) { | 1927 if (FLAG_trace_opt) { |
1927 PrintF("[completed optimizing "); | 1928 PrintF("[completed optimizing "); |
1928 info->closure()->ShortPrint(); | 1929 info->closure()->ShortPrint(); |
1929 PrintF("]\n"); | 1930 PrintF("]\n"); |
1930 } | 1931 } |
1931 info->closure()->ReplaceCode(*info->code()); | 1932 info->closure()->ReplaceCode(*info->code()); |
1932 return; | 1933 return; |
1933 } | 1934 } |
1934 } | 1935 } |
1935 | 1936 |
1936 DCHECK(job->state() == CompilationJob::State::kFailed); | 1937 DCHECK(job->last_status() != CompilationJob::SUCCEEDED); |
1937 if (FLAG_trace_opt) { | 1938 if (FLAG_trace_opt) { |
1938 PrintF("[aborted optimizing "); | 1939 PrintF("[aborted optimizing "); |
1939 info->closure()->ShortPrint(); | 1940 info->closure()->ShortPrint(); |
1940 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); | 1941 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); |
1941 } | 1942 } |
1942 info->closure()->ReplaceCode(shared->code()); | 1943 info->closure()->ReplaceCode(shared->code()); |
1943 } | 1944 } |
1944 | 1945 |
1945 void Compiler::PostInstantiation(Handle<JSFunction> function, | 1946 void Compiler::PostInstantiation(Handle<JSFunction> function, |
1946 PretenureFlag pretenure) { | 1947 PretenureFlag pretenure) { |
(...skipping 16 matching lines...) Expand all Loading... |
1963 DCHECK(shared->is_compiled()); | 1964 DCHECK(shared->is_compiled()); |
1964 function->set_literals(cached.literals); | 1965 function->set_literals(cached.literals); |
1965 } else if (shared->is_compiled()) { | 1966 } else if (shared->is_compiled()) { |
1966 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. | 1967 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. |
1967 JSFunction::EnsureLiterals(function); | 1968 JSFunction::EnsureLiterals(function); |
1968 } | 1969 } |
1969 } | 1970 } |
1970 | 1971 |
1971 } // namespace internal | 1972 } // namespace internal |
1972 } // namespace v8 | 1973 } // namespace v8 |
OLD | NEW |