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 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 DECLARATION_NODE_LIST(DEF_VISIT) | 318 DECLARATION_NODE_LIST(DEF_VISIT) |
319 #undef DEF_VISIT | 319 #undef DEF_VISIT |
320 }; | 320 }; |
321 | 321 |
322 | 322 |
323 OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() { | 323 OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() { |
324 DCHECK(isolate()->use_crankshaft()); | 324 DCHECK(isolate()->use_crankshaft()); |
325 DCHECK(info()->IsOptimizing()); | 325 DCHECK(info()->IsOptimizing()); |
326 DCHECK(!info()->IsCompilingForDebugging()); | 326 DCHECK(!info()->IsCompilingForDebugging()); |
327 | 327 |
328 // We should never arrive here if there is no code object on the | |
329 // shared function object. | |
330 DCHECK(info()->shared_info()->code()->kind() == Code::FUNCTION); | |
331 | |
332 // We should never arrive here if optimization has been disabled on the | 328 // We should never arrive here if optimization has been disabled on the |
333 // shared function info. | 329 // shared function info. |
334 DCHECK(!info()->shared_info()->optimization_disabled()); | 330 DCHECK(!info()->shared_info()->optimization_disabled()); |
335 | 331 |
336 // Do not use crankshaft if we need to be able to set break points. | 332 // Do not use crankshaft if we need to be able to set break points. |
337 if (isolate()->DebuggerHasBreakPoints()) { | 333 if (isolate()->DebuggerHasBreakPoints()) { |
338 return AbortOptimization(kDebuggerHasBreakPoints); | 334 return AbortOptimization(kDebuggerHasBreakPoints); |
339 } | 335 } |
340 | 336 |
341 // Limit the number of times we re-compile a functions with | 337 // Limit the number of times we re-compile a functions with |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 return SetLastStatus(FAILED); | 385 return SetLastStatus(FAILED); |
390 } | 386 } |
391 if (FLAG_hydrogen_stats) { | 387 if (FLAG_hydrogen_stats) { |
392 isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed()); | 388 isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed()); |
393 } | 389 } |
394 } | 390 } |
395 | 391 |
396 DCHECK(info()->shared_info()->has_deoptimization_support()); | 392 DCHECK(info()->shared_info()->has_deoptimization_support()); |
397 | 393 |
398 // Check the whitelist for TurboFan. | 394 // Check the whitelist for TurboFan. |
399 if (info()->closure()->PassesFilter(FLAG_turbo_filter)) { | 395 if ((FLAG_turbo_asm && info()->shared_info()->asm_function()) || |
| 396 info()->closure()->PassesFilter(FLAG_turbo_filter)) { |
400 compiler::Pipeline pipeline(info()); | 397 compiler::Pipeline pipeline(info()); |
401 pipeline.GenerateCode(); | 398 pipeline.GenerateCode(); |
402 if (!info()->code().is_null()) { | 399 if (!info()->code().is_null()) { |
403 if (FLAG_turbo_deoptimization) { | 400 if (FLAG_turbo_deoptimization) { |
404 info()->context()->native_context()->AddOptimizedCode(*info()->code()); | 401 info()->context()->native_context()->AddOptimizedCode(*info()->code()); |
405 } | 402 } |
406 return SetLastStatus(SUCCEEDED); | 403 return SetLastStatus(SUCCEEDED); |
407 } | 404 } |
408 } | 405 } |
409 | 406 |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
697 | 694 |
698 // Update the code and feedback vector for the shared function info. | 695 // Update the code and feedback vector for the shared function info. |
699 shared->ReplaceCode(*info->code()); | 696 shared->ReplaceCode(*info->code()); |
700 if (shared->optimization_disabled()) info->code()->set_optimizable(false); | 697 if (shared->optimization_disabled()) info->code()->set_optimizable(false); |
701 shared->set_feedback_vector(*info->feedback_vector()); | 698 shared->set_feedback_vector(*info->feedback_vector()); |
702 | 699 |
703 return info->code(); | 700 return info->code(); |
704 } | 701 } |
705 | 702 |
706 | 703 |
| 704 MUST_USE_RESULT static MaybeHandle<Code> GetCodeFromOptimizedCodeMap( |
| 705 Handle<JSFunction> function, BailoutId osr_ast_id) { |
| 706 if (FLAG_cache_optimized_code) { |
| 707 Handle<SharedFunctionInfo> shared(function->shared()); |
| 708 // Bound functions are not cached. |
| 709 if (shared->bound()) return MaybeHandle<Code>(); |
| 710 DisallowHeapAllocation no_gc; |
| 711 int index = shared->SearchOptimizedCodeMap( |
| 712 function->context()->native_context(), osr_ast_id); |
| 713 if (index > 0) { |
| 714 if (FLAG_trace_opt) { |
| 715 PrintF("[found optimized code for "); |
| 716 function->ShortPrint(); |
| 717 if (!osr_ast_id.IsNone()) { |
| 718 PrintF(" at OSR AST id %d", osr_ast_id.ToInt()); |
| 719 } |
| 720 PrintF("]\n"); |
| 721 } |
| 722 FixedArray* literals = shared->GetLiteralsFromOptimizedCodeMap(index); |
| 723 if (literals != NULL) function->set_literals(literals); |
| 724 return Handle<Code>(shared->GetCodeFromOptimizedCodeMap(index)); |
| 725 } |
| 726 } |
| 727 return MaybeHandle<Code>(); |
| 728 } |
| 729 |
| 730 |
| 731 static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) { |
| 732 Handle<Code> code = info->code(); |
| 733 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do. |
| 734 |
| 735 // Context specialization folds-in the context, so no sharing can occur. |
| 736 if (code->is_turbofanned() && info->is_context_specializing()) return; |
| 737 |
| 738 // Cache optimized code. |
| 739 if (FLAG_cache_optimized_code) { |
| 740 Handle<JSFunction> function = info->closure(); |
| 741 Handle<SharedFunctionInfo> shared(function->shared()); |
| 742 // Do not cache bound functions. |
| 743 if (shared->bound()) return; |
| 744 Handle<FixedArray> literals(function->literals()); |
| 745 Handle<Context> native_context(function->context()->native_context()); |
| 746 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, |
| 747 literals, info->osr_ast_id()); |
| 748 } |
| 749 } |
| 750 |
| 751 |
| 752 static bool CompileOptimizedPrologue(CompilationInfo* info) { |
| 753 if (!Parser::Parse(info)) return false; |
| 754 if (!Rewriter::Rewrite(info)) return false; |
| 755 if (!Scope::Analyze(info)) return false; |
| 756 DCHECK(info->scope() != NULL); |
| 757 return true; |
| 758 } |
| 759 |
| 760 |
| 761 static bool GetOptimizedCodeNow(CompilationInfo* info) { |
| 762 if (!CompileOptimizedPrologue(info)) return false; |
| 763 |
| 764 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); |
| 765 |
| 766 OptimizedCompileJob job(info); |
| 767 if (job.CreateGraph() != OptimizedCompileJob::SUCCEEDED) return false; |
| 768 if (job.OptimizeGraph() != OptimizedCompileJob::SUCCEEDED) return false; |
| 769 if (job.GenerateCode() != OptimizedCompileJob::SUCCEEDED) return false; |
| 770 |
| 771 // Success! |
| 772 DCHECK(!info->isolate()->has_pending_exception()); |
| 773 InsertCodeIntoOptimizedCodeMap(info); |
| 774 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, |
| 775 info->shared_info()); |
| 776 return true; |
| 777 } |
| 778 |
| 779 |
| 780 static bool GetOptimizedCodeLater(CompilationInfo* info) { |
| 781 Isolate* isolate = info->isolate(); |
| 782 if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) { |
| 783 if (FLAG_trace_concurrent_recompilation) { |
| 784 PrintF(" ** Compilation queue full, will retry optimizing "); |
| 785 info->closure()->PrintName(); |
| 786 PrintF(" later.\n"); |
| 787 } |
| 788 return false; |
| 789 } |
| 790 |
| 791 CompilationHandleScope handle_scope(info); |
| 792 if (!CompileOptimizedPrologue(info)) return false; |
| 793 info->SaveHandles(); // Copy handles to the compilation handle scope. |
| 794 |
| 795 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); |
| 796 |
| 797 OptimizedCompileJob* job = new (info->zone()) OptimizedCompileJob(info); |
| 798 OptimizedCompileJob::Status status = job->CreateGraph(); |
| 799 if (status != OptimizedCompileJob::SUCCEEDED) return false; |
| 800 isolate->optimizing_compiler_thread()->QueueForOptimization(job); |
| 801 |
| 802 if (FLAG_trace_concurrent_recompilation) { |
| 803 PrintF(" ** Queued "); |
| 804 info->closure()->PrintName(); |
| 805 if (info->is_osr()) { |
| 806 PrintF(" for concurrent OSR at %d.\n", info->osr_ast_id().ToInt()); |
| 807 } else { |
| 808 PrintF(" for concurrent optimization.\n"); |
| 809 } |
| 810 } |
| 811 return true; |
| 812 } |
| 813 |
| 814 |
707 MaybeHandle<Code> Compiler::GetUnoptimizedCode(Handle<JSFunction> function) { | 815 MaybeHandle<Code> Compiler::GetUnoptimizedCode(Handle<JSFunction> function) { |
708 DCHECK(!function->GetIsolate()->has_pending_exception()); | 816 DCHECK(!function->GetIsolate()->has_pending_exception()); |
709 DCHECK(!function->is_compiled()); | 817 DCHECK(!function->is_compiled()); |
710 if (function->shared()->is_compiled()) { | 818 if (function->shared()->is_compiled()) { |
711 return Handle<Code>(function->shared()->code()); | 819 return Handle<Code>(function->shared()->code()); |
712 } | 820 } |
713 | 821 |
714 CompilationInfoWithZone info(function); | 822 CompilationInfoWithZone info(function); |
715 Handle<Code> result; | 823 Handle<Code> result; |
716 ASSIGN_RETURN_ON_EXCEPTION(info.isolate(), result, | 824 ASSIGN_RETURN_ON_EXCEPTION(info.isolate(), result, |
717 GetUnoptimizedCodeCommon(&info), | 825 GetUnoptimizedCodeCommon(&info), |
718 Code); | 826 Code); |
719 return result; | 827 return result; |
720 } | 828 } |
721 | 829 |
722 | 830 |
723 MaybeHandle<Code> Compiler::GetLazyCode(Handle<JSFunction> function) { | 831 MaybeHandle<Code> Compiler::GetLazyCode(Handle<JSFunction> function) { |
724 DCHECK(!function->GetIsolate()->has_pending_exception()); | 832 DCHECK(!function->GetIsolate()->has_pending_exception()); |
725 DCHECK(!function->is_compiled()); | 833 DCHECK(!function->is_compiled()); |
726 | 834 |
727 if (FLAG_turbo_asm && function->shared()->asm_function()) { | 835 if (FLAG_turbo_asm && function->shared()->asm_function()) { |
728 CompilationInfoWithZone info(function); | 836 CompilationInfoWithZone info(function); |
729 | 837 |
730 VMState<COMPILER> state(info.isolate()); | 838 VMState<COMPILER> state(info.isolate()); |
731 PostponeInterruptsScope postpone(info.isolate()); | 839 PostponeInterruptsScope postpone(info.isolate()); |
732 | 840 |
733 if (FLAG_trace_opt) { | |
734 // TODO(titzer): record and report full stats here. | |
735 PrintF("[optimizing asm "); | |
736 function->ShortPrint(); | |
737 PrintF("]\n"); | |
738 } | |
739 | |
740 if (!Parser::Parse(&info)) return MaybeHandle<Code>(); | |
741 if (!Rewriter::Rewrite(&info)) return MaybeHandle<Code>(); | |
742 if (!Scope::Analyze(&info)) return MaybeHandle<Code>(); | |
743 if (FLAG_turbo_deoptimization && !EnsureDeoptimizationSupport(&info)) { | |
744 return MaybeHandle<Code>(); | |
745 } | |
746 | |
747 info.SetOptimizing(BailoutId::None(), | 841 info.SetOptimizing(BailoutId::None(), |
748 Handle<Code>(function->shared()->code())); | 842 Handle<Code>(function->shared()->code())); |
749 | 843 |
750 info.MarkAsContextSpecializing(); | 844 info.MarkAsContextSpecializing(); |
751 info.MarkAsTypingEnabled(); | 845 info.MarkAsTypingEnabled(); |
752 info.MarkAsInliningDisabled(); | 846 info.MarkAsInliningDisabled(); |
753 compiler::Pipeline pipeline(&info); | 847 |
754 pipeline.GenerateCode(); | 848 if (GetOptimizedCodeNow(&info)) return info.code(); |
755 if (!info.code().is_null()) return info.code(); | |
756 } | 849 } |
757 | 850 |
758 if (function->shared()->is_compiled()) { | 851 if (function->shared()->is_compiled()) { |
759 return Handle<Code>(function->shared()->code()); | 852 return Handle<Code>(function->shared()->code()); |
760 } | 853 } |
761 | 854 |
762 CompilationInfoWithZone info(function); | 855 CompilationInfoWithZone info(function); |
763 Handle<Code> result; | 856 Handle<Code> result; |
764 ASSIGN_RETURN_ON_EXCEPTION(info.isolate(), result, | 857 ASSIGN_RETURN_ON_EXCEPTION(info.isolate(), result, |
765 GetUnoptimizedCodeCommon(&info), Code); | 858 GetUnoptimizedCodeCommon(&info), Code); |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1202 | 1295 |
1203 // Set the expected number of properties for instances and return | 1296 // Set the expected number of properties for instances and return |
1204 // the resulting function. | 1297 // the resulting function. |
1205 SetExpectedNofPropertiesFromEstimate(result, | 1298 SetExpectedNofPropertiesFromEstimate(result, |
1206 literal->expected_property_count()); | 1299 literal->expected_property_count()); |
1207 live_edit_tracker.RecordFunctionInfo(result, literal, info.zone()); | 1300 live_edit_tracker.RecordFunctionInfo(result, literal, info.zone()); |
1208 return result; | 1301 return result; |
1209 } | 1302 } |
1210 | 1303 |
1211 | 1304 |
1212 MUST_USE_RESULT static MaybeHandle<Code> GetCodeFromOptimizedCodeMap( | |
1213 Handle<JSFunction> function, | |
1214 BailoutId osr_ast_id) { | |
1215 if (FLAG_cache_optimized_code) { | |
1216 Handle<SharedFunctionInfo> shared(function->shared()); | |
1217 // Bound functions are not cached. | |
1218 if (shared->bound()) return MaybeHandle<Code>(); | |
1219 DisallowHeapAllocation no_gc; | |
1220 int index = shared->SearchOptimizedCodeMap( | |
1221 function->context()->native_context(), osr_ast_id); | |
1222 if (index > 0) { | |
1223 if (FLAG_trace_opt) { | |
1224 PrintF("[found optimized code for "); | |
1225 function->ShortPrint(); | |
1226 if (!osr_ast_id.IsNone()) { | |
1227 PrintF(" at OSR AST id %d", osr_ast_id.ToInt()); | |
1228 } | |
1229 PrintF("]\n"); | |
1230 } | |
1231 FixedArray* literals = shared->GetLiteralsFromOptimizedCodeMap(index); | |
1232 if (literals != NULL) function->set_literals(literals); | |
1233 return Handle<Code>(shared->GetCodeFromOptimizedCodeMap(index)); | |
1234 } | |
1235 } | |
1236 return MaybeHandle<Code>(); | |
1237 } | |
1238 | |
1239 | |
1240 static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) { | |
1241 Handle<Code> code = info->code(); | |
1242 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do. | |
1243 | |
1244 // Context specialization folds-in the context, so no sharing can occur. | |
1245 if (code->is_turbofanned() && info->is_context_specializing()) return; | |
1246 | |
1247 // Cache optimized code. | |
1248 if (FLAG_cache_optimized_code) { | |
1249 Handle<JSFunction> function = info->closure(); | |
1250 Handle<SharedFunctionInfo> shared(function->shared()); | |
1251 // Do not cache bound functions. | |
1252 if (shared->bound()) return; | |
1253 Handle<FixedArray> literals(function->literals()); | |
1254 Handle<Context> native_context(function->context()->native_context()); | |
1255 SharedFunctionInfo::AddToOptimizedCodeMap( | |
1256 shared, native_context, code, literals, info->osr_ast_id()); | |
1257 } | |
1258 } | |
1259 | |
1260 | |
1261 static bool CompileOptimizedPrologue(CompilationInfo* info) { | |
1262 if (!Parser::Parse(info)) return false; | |
1263 if (!Rewriter::Rewrite(info)) return false; | |
1264 if (!Scope::Analyze(info)) return false; | |
1265 DCHECK(info->scope() != NULL); | |
1266 return true; | |
1267 } | |
1268 | |
1269 | |
1270 static bool GetOptimizedCodeNow(CompilationInfo* info) { | |
1271 if (!CompileOptimizedPrologue(info)) return false; | |
1272 | |
1273 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); | |
1274 | |
1275 OptimizedCompileJob job(info); | |
1276 if (job.CreateGraph() != OptimizedCompileJob::SUCCEEDED) return false; | |
1277 if (job.OptimizeGraph() != OptimizedCompileJob::SUCCEEDED) return false; | |
1278 if (job.GenerateCode() != OptimizedCompileJob::SUCCEEDED) return false; | |
1279 | |
1280 // Success! | |
1281 DCHECK(!info->isolate()->has_pending_exception()); | |
1282 InsertCodeIntoOptimizedCodeMap(info); | |
1283 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, | |
1284 info->shared_info()); | |
1285 return true; | |
1286 } | |
1287 | |
1288 | |
1289 static bool GetOptimizedCodeLater(CompilationInfo* info) { | |
1290 Isolate* isolate = info->isolate(); | |
1291 if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) { | |
1292 if (FLAG_trace_concurrent_recompilation) { | |
1293 PrintF(" ** Compilation queue full, will retry optimizing "); | |
1294 info->closure()->PrintName(); | |
1295 PrintF(" later.\n"); | |
1296 } | |
1297 return false; | |
1298 } | |
1299 | |
1300 CompilationHandleScope handle_scope(info); | |
1301 if (!CompileOptimizedPrologue(info)) return false; | |
1302 info->SaveHandles(); // Copy handles to the compilation handle scope. | |
1303 | |
1304 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); | |
1305 | |
1306 OptimizedCompileJob* job = new(info->zone()) OptimizedCompileJob(info); | |
1307 OptimizedCompileJob::Status status = job->CreateGraph(); | |
1308 if (status != OptimizedCompileJob::SUCCEEDED) return false; | |
1309 isolate->optimizing_compiler_thread()->QueueForOptimization(job); | |
1310 | |
1311 if (FLAG_trace_concurrent_recompilation) { | |
1312 PrintF(" ** Queued "); | |
1313 info->closure()->PrintName(); | |
1314 if (info->is_osr()) { | |
1315 PrintF(" for concurrent OSR at %d.\n", info->osr_ast_id().ToInt()); | |
1316 } else { | |
1317 PrintF(" for concurrent optimization.\n"); | |
1318 } | |
1319 } | |
1320 return true; | |
1321 } | |
1322 | |
1323 | |
1324 MaybeHandle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function, | 1305 MaybeHandle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function, |
1325 Handle<Code> current_code, | 1306 Handle<Code> current_code, |
1326 ConcurrencyMode mode, | 1307 ConcurrencyMode mode, |
1327 BailoutId osr_ast_id) { | 1308 BailoutId osr_ast_id) { |
1328 Handle<Code> cached_code; | 1309 Handle<Code> cached_code; |
1329 if (GetCodeFromOptimizedCodeMap( | 1310 if (GetCodeFromOptimizedCodeMap( |
1330 function, osr_ast_id).ToHandle(&cached_code)) { | 1311 function, osr_ast_id).ToHandle(&cached_code)) { |
1331 return cached_code; | 1312 return cached_code; |
1332 } | 1313 } |
1333 | 1314 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1451 AllowHandleDereference allow_deref; | 1432 AllowHandleDereference allow_deref; |
1452 bool tracing_on = info()->IsStub() | 1433 bool tracing_on = info()->IsStub() |
1453 ? FLAG_trace_hydrogen_stubs | 1434 ? FLAG_trace_hydrogen_stubs |
1454 : (FLAG_trace_hydrogen && | 1435 : (FLAG_trace_hydrogen && |
1455 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); | 1436 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); |
1456 return (tracing_on && | 1437 return (tracing_on && |
1457 base::OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); | 1438 base::OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); |
1458 } | 1439 } |
1459 | 1440 |
1460 } } // namespace v8::internal | 1441 } } // namespace v8::internal |
OLD | NEW |