| 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 |
| 285 void CompilationJob::RecordOptimizationStats() { | |
| 286 DCHECK(info()->IsOptimizing()); | |
| 287 Handle<JSFunction> function = info()->closure(); | |
| 288 if (!function->IsOptimized()) { | |
| 289 // Concurrent recompilation and OSR may race. Increment only once. | |
| 290 int opt_count = function->shared()->opt_count(); | |
| 291 function->shared()->set_opt_count(opt_count + 1); | |
| 292 } | |
| 293 double ms_creategraph = time_taken_to_prepare_.InMillisecondsF(); | |
| 294 double ms_optimize = time_taken_to_execute_.InMillisecondsF(); | |
| 295 double ms_codegen = time_taken_to_finalize_.InMillisecondsF(); | |
| 296 if (FLAG_trace_opt) { | |
| 297 PrintF("[optimizing "); | |
| 298 function->ShortPrint(); | |
| 299 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize, | |
| 300 ms_codegen); | |
| 301 } | |
| 302 if (FLAG_trace_opt_stats) { | |
| 303 static double compilation_time = 0.0; | |
| 304 static int compiled_functions = 0; | |
| 305 static int code_size = 0; | |
| 306 | |
| 307 compilation_time += (ms_creategraph + ms_optimize + ms_codegen); | |
| 308 compiled_functions++; | |
| 309 code_size += function->shared()->SourceSize(); | |
| 310 PrintF("Compiled: %d functions with %d byte source size in %fms.\n", | |
| 311 compiled_functions, code_size, compilation_time); | |
| 312 } | |
| 313 if (FLAG_hydrogen_stats) { | |
| 314 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_prepare_, | |
| 315 time_taken_to_execute_, | |
| 316 time_taken_to_finalize_); | |
| 317 } | |
| 318 } | |
| 319 | 284 |
| 320 namespace { | 285 namespace { |
| 321 | 286 |
| 322 void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object, | 287 void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object, |
| 323 Handle<Code> code) { | 288 Handle<Code> code) { |
| 324 Handle<WeakCell> cell = Code::WeakCellFor(code); | 289 Handle<WeakCell> cell = Code::WeakCellFor(code); |
| 325 Heap* heap = isolate->heap(); | 290 Heap* heap = isolate->heap(); |
| 326 if (heap->InNewSpace(*object)) { | 291 if (heap->InNewSpace(*object)) { |
| 327 heap->AddWeakNewSpaceObjectToCodeDependency(object, cell); | 292 heap->AddWeakNewSpaceObjectToCodeDependency(object, cell); |
| 328 } else { | 293 } else { |
| 329 Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object)); | 294 Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object)); |
| 330 dep = | 295 dep = |
| 331 DependentCode::InsertWeakCode(dep, DependentCode::kWeakCodeGroup, cell); | 296 DependentCode::InsertWeakCode(dep, DependentCode::kWeakCodeGroup, cell); |
| 332 heap->AddWeakObjectToCodeDependency(object, dep); | 297 heap->AddWeakObjectToCodeDependency(object, dep); |
| 333 } | 298 } |
| 334 } | 299 } |
| 335 | 300 |
| 336 } // namespace | 301 } // namespace |
| 337 | 302 |
| 338 // static | |
| 339 void CompilationJob::RegisterWeakObjectsInOptimizedCode(Handle<Code> code) { | 303 void CompilationJob::RegisterWeakObjectsInOptimizedCode(Handle<Code> code) { |
| 340 // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies. | 304 // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies. |
| 341 Isolate* const isolate = code->GetIsolate(); | 305 Isolate* const isolate = code->GetIsolate(); |
| 342 DCHECK(code->is_optimized_code()); | 306 DCHECK(code->is_optimized_code()); |
| 343 std::vector<Handle<Map>> maps; | 307 std::vector<Handle<Map>> maps; |
| 344 std::vector<Handle<HeapObject>> objects; | 308 std::vector<Handle<HeapObject>> objects; |
| 345 { | 309 { |
| 346 DisallowHeapAllocation no_gc; | 310 DisallowHeapAllocation no_gc; |
| 347 int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | | 311 int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | |
| 348 RelocInfo::ModeMask(RelocInfo::CELL); | 312 RelocInfo::ModeMask(RelocInfo::CELL); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 369 isolate->heap()->AddRetainedMap(map); | 333 isolate->heap()->AddRetainedMap(map); |
| 370 } | 334 } |
| 371 Map::AddDependentCode(map, DependentCode::kWeakCodeGroup, code); | 335 Map::AddDependentCode(map, DependentCode::kWeakCodeGroup, code); |
| 372 } | 336 } |
| 373 for (Handle<HeapObject> object : objects) { | 337 for (Handle<HeapObject> object : objects) { |
| 374 AddWeakObjectToCodeDependency(isolate, object, code); | 338 AddWeakObjectToCodeDependency(isolate, object, code); |
| 375 } | 339 } |
| 376 code->set_can_have_weak_objects(true); | 340 code->set_can_have_weak_objects(true); |
| 377 } | 341 } |
| 378 | 342 |
| 343 void CompilationJob::RecordOptimizationStats() { |
| 344 Handle<JSFunction> function = info()->closure(); |
| 345 if (!function->IsOptimized()) { |
| 346 // Concurrent recompilation and OSR may race. Increment only once. |
| 347 int opt_count = function->shared()->opt_count(); |
| 348 function->shared()->set_opt_count(opt_count + 1); |
| 349 } |
| 350 double ms_creategraph = time_taken_to_create_graph_.InMillisecondsF(); |
| 351 double ms_optimize = time_taken_to_optimize_.InMillisecondsF(); |
| 352 double ms_codegen = time_taken_to_codegen_.InMillisecondsF(); |
| 353 if (FLAG_trace_opt) { |
| 354 PrintF("[optimizing "); |
| 355 function->ShortPrint(); |
| 356 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize, |
| 357 ms_codegen); |
| 358 } |
| 359 if (FLAG_trace_opt_stats) { |
| 360 static double compilation_time = 0.0; |
| 361 static int compiled_functions = 0; |
| 362 static int code_size = 0; |
| 363 |
| 364 compilation_time += (ms_creategraph + ms_optimize + ms_codegen); |
| 365 compiled_functions++; |
| 366 code_size += function->shared()->SourceSize(); |
| 367 PrintF("Compiled: %d functions with %d byte source size in %fms.\n", |
| 368 compiled_functions, |
| 369 code_size, |
| 370 compilation_time); |
| 371 } |
| 372 if (FLAG_hydrogen_stats) { |
| 373 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_, |
| 374 time_taken_to_optimize_, |
| 375 time_taken_to_codegen_); |
| 376 } |
| 377 } |
| 378 |
| 379 // ---------------------------------------------------------------------------- | 379 // ---------------------------------------------------------------------------- |
| 380 // Local helper methods that make up the compilation pipeline. | 380 // Local helper methods that make up the compilation pipeline. |
| 381 | 381 |
| 382 namespace { | 382 namespace { |
| 383 | 383 |
| 384 bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) { | 384 bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) { |
| 385 return shared->is_toplevel() && shared->script()->IsScript() && | 385 return shared->is_toplevel() && shared->script()->IsScript() && |
| 386 Script::cast(shared->script())->compilation_type() == | 386 Script::cast(shared->script())->compilation_type() == |
| 387 Script::COMPILATION_TYPE_EVAL; | 387 Script::COMPILATION_TYPE_EVAL; |
| 388 } | 388 } |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 } | 665 } |
| 666 | 666 |
| 667 JSFunction::EnsureLiterals(info->closure()); | 667 JSFunction::EnsureLiterals(info->closure()); |
| 668 | 668 |
| 669 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate); | 669 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate); |
| 670 RuntimeCallTimerScope runtimeTimer(isolate, | 670 RuntimeCallTimerScope runtimeTimer(isolate, |
| 671 &RuntimeCallStats::RecompileSynchronous); | 671 &RuntimeCallStats::RecompileSynchronous); |
| 672 TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_SCOPED( | 672 TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_SCOPED( |
| 673 isolate, &tracing::TraceEventStatsTable::RecompileSynchronous); | 673 isolate, &tracing::TraceEventStatsTable::RecompileSynchronous); |
| 674 | 674 |
| 675 if (job->PrepareJob() != CompilationJob::SUCCEEDED || | 675 if (job->CreateGraph() != CompilationJob::SUCCEEDED || |
| 676 job->ExecuteJob() != CompilationJob::SUCCEEDED || | 676 job->OptimizeGraph() != CompilationJob::SUCCEEDED || |
| 677 job->FinalizeJob() != CompilationJob::SUCCEEDED) { | 677 job->GenerateCode() != CompilationJob::SUCCEEDED) { |
| 678 if (FLAG_trace_opt) { | 678 if (FLAG_trace_opt) { |
| 679 PrintF("[aborted optimizing "); | 679 PrintF("[aborted optimizing "); |
| 680 info->closure()->ShortPrint(); | 680 info->closure()->ShortPrint(); |
| 681 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); | 681 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); |
| 682 } | 682 } |
| 683 return false; | 683 return false; |
| 684 } | 684 } |
| 685 | 685 |
| 686 // Success! | 686 // Success! |
| 687 job->RecordOptimizationStats(); | 687 job->RecordOptimizationStats(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 728 // Reopen handles in the new CompilationHandleScope. | 728 // Reopen handles in the new CompilationHandleScope. |
| 729 info->ReopenHandlesInNewHandleScope(); | 729 info->ReopenHandlesInNewHandleScope(); |
| 730 info->parse_info()->ReopenHandlesInNewHandleScope(); | 730 info->parse_info()->ReopenHandlesInNewHandleScope(); |
| 731 | 731 |
| 732 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); | 732 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); |
| 733 RuntimeCallTimerScope runtimeTimer(info->isolate(), | 733 RuntimeCallTimerScope runtimeTimer(info->isolate(), |
| 734 &RuntimeCallStats::RecompileSynchronous); | 734 &RuntimeCallStats::RecompileSynchronous); |
| 735 TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_SCOPED( | 735 TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_SCOPED( |
| 736 isolate, &tracing::TraceEventStatsTable::RecompileSynchronous); | 736 isolate, &tracing::TraceEventStatsTable::RecompileSynchronous); |
| 737 | 737 |
| 738 if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false; | 738 if (job->CreateGraph() != CompilationJob::SUCCEEDED) return false; |
| 739 isolate->optimizing_compile_dispatcher()->QueueForOptimization(job); | 739 isolate->optimizing_compile_dispatcher()->QueueForOptimization(job); |
| 740 | 740 |
| 741 if (FLAG_trace_concurrent_recompilation) { | 741 if (FLAG_trace_concurrent_recompilation) { |
| 742 PrintF(" ** Queued "); | 742 PrintF(" ** Queued "); |
| 743 info->closure()->ShortPrint(); | 743 info->closure()->ShortPrint(); |
| 744 PrintF(" for concurrent optimization.\n"); | 744 PrintF(" for concurrent optimization.\n"); |
| 745 } | 745 } |
| 746 return true; | 746 return true; |
| 747 } | 747 } |
| 748 | 748 |
| (...skipping 1151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1900 Handle<SharedFunctionInfo> shared = info->shared_info(); | 1900 Handle<SharedFunctionInfo> shared = info->shared_info(); |
| 1901 shared->code()->set_profiler_ticks(0); | 1901 shared->code()->set_profiler_ticks(0); |
| 1902 | 1902 |
| 1903 DCHECK(!shared->HasDebugInfo()); | 1903 DCHECK(!shared->HasDebugInfo()); |
| 1904 | 1904 |
| 1905 // 1) Optimization on the concurrent thread may have failed. | 1905 // 1) Optimization on the concurrent thread may have failed. |
| 1906 // 2) The function may have already been optimized by OSR. Simply continue. | 1906 // 2) The function may have already been optimized by OSR. Simply continue. |
| 1907 // Except when OSR already disabled optimization for some reason. | 1907 // Except when OSR already disabled optimization for some reason. |
| 1908 // 3) The code may have already been invalidated due to dependency change. | 1908 // 3) The code may have already been invalidated due to dependency change. |
| 1909 // 4) Code generation may have failed. | 1909 // 4) Code generation may have failed. |
| 1910 if (job->state() == CompilationJob::State::kReadyToFinalize) { | 1910 if (job->last_status() == CompilationJob::SUCCEEDED) { |
| 1911 if (shared->optimization_disabled()) { | 1911 if (shared->optimization_disabled()) { |
| 1912 job->RetryOptimization(kOptimizationDisabled); | 1912 job->RetryOptimization(kOptimizationDisabled); |
| 1913 } else if (info->dependencies()->HasAborted()) { | 1913 } else if (info->dependencies()->HasAborted()) { |
| 1914 job->RetryOptimization(kBailedOutDueToDependencyChange); | 1914 job->RetryOptimization(kBailedOutDueToDependencyChange); |
| 1915 } else if (job->FinalizeJob() == CompilationJob::SUCCEEDED) { | 1915 } else if (job->GenerateCode() == CompilationJob::SUCCEEDED) { |
| 1916 job->RecordOptimizationStats(); | 1916 job->RecordOptimizationStats(); |
| 1917 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); | 1917 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); |
| 1918 if (shared->SearchOptimizedCodeMap(info->context()->native_context(), | 1918 if (shared->SearchOptimizedCodeMap(info->context()->native_context(), |
| 1919 info->osr_ast_id()).code == nullptr) { | 1919 info->osr_ast_id()).code == nullptr) { |
| 1920 InsertCodeIntoOptimizedCodeMap(info); | 1920 InsertCodeIntoOptimizedCodeMap(info); |
| 1921 } | 1921 } |
| 1922 if (FLAG_trace_opt) { | 1922 if (FLAG_trace_opt) { |
| 1923 PrintF("[completed optimizing "); | 1923 PrintF("[completed optimizing "); |
| 1924 info->closure()->ShortPrint(); | 1924 info->closure()->ShortPrint(); |
| 1925 PrintF("]\n"); | 1925 PrintF("]\n"); |
| 1926 } | 1926 } |
| 1927 info->closure()->ReplaceCode(*info->code()); | 1927 info->closure()->ReplaceCode(*info->code()); |
| 1928 return; | 1928 return; |
| 1929 } | 1929 } |
| 1930 } | 1930 } |
| 1931 | 1931 |
| 1932 DCHECK(job->state() == CompilationJob::State::kFailed); | 1932 DCHECK(job->last_status() != CompilationJob::SUCCEEDED); |
| 1933 if (FLAG_trace_opt) { | 1933 if (FLAG_trace_opt) { |
| 1934 PrintF("[aborted optimizing "); | 1934 PrintF("[aborted optimizing "); |
| 1935 info->closure()->ShortPrint(); | 1935 info->closure()->ShortPrint(); |
| 1936 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); | 1936 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); |
| 1937 } | 1937 } |
| 1938 info->closure()->ReplaceCode(shared->code()); | 1938 info->closure()->ReplaceCode(shared->code()); |
| 1939 } | 1939 } |
| 1940 | 1940 |
| 1941 void Compiler::PostInstantiation(Handle<JSFunction> function, | 1941 void Compiler::PostInstantiation(Handle<JSFunction> function, |
| 1942 PretenureFlag pretenure) { | 1942 PretenureFlag pretenure) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1959 DCHECK(shared->is_compiled()); | 1959 DCHECK(shared->is_compiled()); |
| 1960 function->set_literals(cached.literals); | 1960 function->set_literals(cached.literals); |
| 1961 } else if (shared->is_compiled()) { | 1961 } else if (shared->is_compiled()) { |
| 1962 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. | 1962 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. |
| 1963 JSFunction::EnsureLiterals(function); | 1963 JSFunction::EnsureLiterals(function); |
| 1964 } | 1964 } |
| 1965 } | 1965 } |
| 1966 | 1966 |
| 1967 } // namespace internal | 1967 } // namespace internal |
| 1968 } // namespace v8 | 1968 } // namespace v8 |
| OLD | NEW |