| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 #include "vm-state-inl.h" | 51 #include "vm-state-inl.h" |
| 52 | 52 |
| 53 namespace v8 { | 53 namespace v8 { |
| 54 namespace internal { | 54 namespace internal { |
| 55 | 55 |
| 56 | 56 |
| 57 CompilationInfo::CompilationInfo(Handle<Script> script, | 57 CompilationInfo::CompilationInfo(Handle<Script> script, |
| 58 Zone* zone) | 58 Zone* zone) |
| 59 : flags_(LanguageModeField::encode(CLASSIC_MODE)), | 59 : flags_(LanguageModeField::encode(CLASSIC_MODE)), |
| 60 script_(script), | 60 script_(script), |
| 61 osr_ast_id_(BailoutId::None()) { | 61 osr_ast_id_(BailoutId::None()), |
| 62 osr_pc_offset_(0) { |
| 62 Initialize(script->GetIsolate(), BASE, zone); | 63 Initialize(script->GetIsolate(), BASE, zone); |
| 63 } | 64 } |
| 64 | 65 |
| 65 | 66 |
| 66 CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info, | 67 CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info, |
| 67 Zone* zone) | 68 Zone* zone) |
| 68 : flags_(LanguageModeField::encode(CLASSIC_MODE) | IsLazy::encode(true)), | 69 : flags_(LanguageModeField::encode(CLASSIC_MODE) | IsLazy::encode(true)), |
| 69 shared_info_(shared_info), | 70 shared_info_(shared_info), |
| 70 script_(Handle<Script>(Script::cast(shared_info->script()))), | 71 script_(Handle<Script>(Script::cast(shared_info->script()))), |
| 71 osr_ast_id_(BailoutId::None()) { | 72 osr_ast_id_(BailoutId::None()), |
| 73 osr_pc_offset_(0) { |
| 72 Initialize(script_->GetIsolate(), BASE, zone); | 74 Initialize(script_->GetIsolate(), BASE, zone); |
| 73 } | 75 } |
| 74 | 76 |
| 75 | 77 |
| 76 CompilationInfo::CompilationInfo(Handle<JSFunction> closure, | 78 CompilationInfo::CompilationInfo(Handle<JSFunction> closure, |
| 77 Zone* zone) | 79 Zone* zone) |
| 78 : flags_(LanguageModeField::encode(CLASSIC_MODE) | IsLazy::encode(true)), | 80 : flags_(LanguageModeField::encode(CLASSIC_MODE) | IsLazy::encode(true)), |
| 79 closure_(closure), | 81 closure_(closure), |
| 80 shared_info_(Handle<SharedFunctionInfo>(closure->shared())), | 82 shared_info_(Handle<SharedFunctionInfo>(closure->shared())), |
| 81 script_(Handle<Script>(Script::cast(shared_info_->script()))), | 83 script_(Handle<Script>(Script::cast(shared_info_->script()))), |
| 82 context_(closure->context()), | 84 context_(closure->context()), |
| 83 osr_ast_id_(BailoutId::None()) { | 85 osr_ast_id_(BailoutId::None()), |
| 86 osr_pc_offset_(0) { |
| 84 Initialize(script_->GetIsolate(), BASE, zone); | 87 Initialize(script_->GetIsolate(), BASE, zone); |
| 85 } | 88 } |
| 86 | 89 |
| 87 | 90 |
| 88 CompilationInfo::CompilationInfo(HydrogenCodeStub* stub, | 91 CompilationInfo::CompilationInfo(HydrogenCodeStub* stub, |
| 89 Isolate* isolate, | 92 Isolate* isolate, |
| 90 Zone* zone) | 93 Zone* zone) |
| 91 : flags_(LanguageModeField::encode(CLASSIC_MODE) | | 94 : flags_(LanguageModeField::encode(CLASSIC_MODE) | |
| 92 IsLazy::encode(true)), | 95 IsLazy::encode(true)), |
| 93 osr_ast_id_(BailoutId::None()) { | 96 osr_ast_id_(BailoutId::None()), |
| 97 osr_pc_offset_(0) { |
| 94 Initialize(isolate, STUB, zone); | 98 Initialize(isolate, STUB, zone); |
| 95 code_stub_ = stub; | 99 code_stub_ = stub; |
| 96 } | 100 } |
| 97 | 101 |
| 98 | 102 |
| 99 void CompilationInfo::Initialize(Isolate* isolate, | 103 void CompilationInfo::Initialize(Isolate* isolate, |
| 100 Mode mode, | 104 Mode mode, |
| 101 Zone* zone) { | 105 Zone* zone) { |
| 102 isolate_ = isolate; | 106 isolate_ = isolate; |
| 103 function_ = NULL; | 107 function_ = NULL; |
| 104 scope_ = NULL; | 108 scope_ = NULL; |
| 105 global_scope_ = NULL; | 109 global_scope_ = NULL; |
| 106 extension_ = NULL; | 110 extension_ = NULL; |
| 107 pre_parse_data_ = NULL; | 111 pre_parse_data_ = NULL; |
| 108 zone_ = zone; | 112 zone_ = zone; |
| 109 deferred_handles_ = NULL; | 113 deferred_handles_ = NULL; |
| 110 code_stub_ = NULL; | 114 code_stub_ = NULL; |
| 111 prologue_offset_ = kPrologueOffsetNotSet; | 115 prologue_offset_ = kPrologueOffsetNotSet; |
| 112 opt_count_ = shared_info().is_null() ? 0 : shared_info()->opt_count(); | 116 opt_count_ = shared_info().is_null() ? 0 : shared_info()->opt_count(); |
| 113 no_frame_ranges_ = isolate->cpu_profiler()->is_profiling() | 117 no_frame_ranges_ = isolate->cpu_profiler()->is_profiling() |
| 114 ? new List<OffsetRange>(2) : NULL; | 118 ? new List<OffsetRange>(2) : NULL; |
| 115 for (int i = 0; i < DependentCode::kGroupCount; i++) { | 119 for (int i = 0; i < DependentCode::kGroupCount; i++) { |
| 116 dependencies_[i] = NULL; | 120 dependencies_[i] = NULL; |
| 117 } | 121 } |
| 118 if (mode == STUB) { | 122 if (mode == STUB) { |
| 119 mode_ = STUB; | 123 mode_ = STUB; |
| 120 return; | 124 return; |
| 121 } | 125 } |
| 122 mode_ = V8::UseCrankshaft() ? mode : NONOPT; | 126 mode_ = isolate->use_crankshaft() ? mode : NONOPT; |
| 123 abort_due_to_dependency_ = false; | 127 abort_due_to_dependency_ = false; |
| 124 if (script_->type()->value() == Script::TYPE_NATIVE) { | 128 if (script_->type()->value() == Script::TYPE_NATIVE) { |
| 125 MarkAsNative(); | 129 MarkAsNative(); |
| 126 } | 130 } |
| 127 if (!shared_info_.is_null()) { | 131 if (!shared_info_.is_null()) { |
| 128 ASSERT(language_mode() == CLASSIC_MODE); | 132 ASSERT(language_mode() == CLASSIC_MODE); |
| 129 SetLanguageMode(shared_info_->language_mode()); | 133 SetLanguageMode(shared_info_->language_mode()); |
| 130 } | 134 } |
| 131 set_bailout_reason(kUnknown); | 135 set_bailout_reason(kUnknown); |
| 132 } | 136 } |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 } | 223 } |
| 220 | 224 |
| 221 | 225 |
| 222 // Primitive functions are unlikely to be picked up by the stack-walking | 226 // Primitive functions are unlikely to be picked up by the stack-walking |
| 223 // profiler, so they trigger their own optimization when they're called | 227 // profiler, so they trigger their own optimization when they're called |
| 224 // for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time. | 228 // for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time. |
| 225 bool CompilationInfo::ShouldSelfOptimize() { | 229 bool CompilationInfo::ShouldSelfOptimize() { |
| 226 return FLAG_self_optimization && | 230 return FLAG_self_optimization && |
| 227 FLAG_crankshaft && | 231 FLAG_crankshaft && |
| 228 !function()->flags()->Contains(kDontSelfOptimize) && | 232 !function()->flags()->Contains(kDontSelfOptimize) && |
| 229 !function()->flags()->Contains(kDontOptimize) && | 233 !function()->dont_optimize() && |
| 230 function()->scope()->AllowsLazyCompilation() && | 234 function()->scope()->AllowsLazyCompilation() && |
| 231 (shared_info().is_null() || !shared_info()->optimization_disabled()); | 235 (shared_info().is_null() || !shared_info()->optimization_disabled()); |
| 232 } | 236 } |
| 233 | 237 |
| 234 | 238 |
| 235 // Determine whether to use the full compiler for all code. If the flag | 239 // Determine whether to use the full compiler for all code. If the flag |
| 236 // --always-full-compiler is specified this is the case. For the virtual frame | 240 // --always-full-compiler is specified this is the case. For the virtual frame |
| 237 // based compiler the full compiler is also used if a debugger is connected, as | 241 // based compiler the full compiler is also used if a debugger is connected, as |
| 238 // the code from the full compiler supports mode precise break points. For the | 242 // the code from the full compiler supports mode precise break points. For the |
| 239 // crankshaft adaptive compiler debugging the optimized code is not possible at | 243 // crankshaft adaptive compiler debugging the optimized code is not possible at |
| 240 // all. However crankshaft support recompilation of functions, so in this case | 244 // all. However crankshaft support recompilation of functions, so in this case |
| 241 // the full compiler need not be be used if a debugger is attached, but only if | 245 // the full compiler need not be be used if a debugger is attached, but only if |
| 242 // break points has actually been set. | 246 // break points has actually been set. |
| 243 static bool IsDebuggerActive(Isolate* isolate) { | 247 static bool IsDebuggerActive(Isolate* isolate) { |
| 244 #ifdef ENABLE_DEBUGGER_SUPPORT | 248 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 245 return V8::UseCrankshaft() ? | 249 return isolate->use_crankshaft() ? |
| 246 isolate->debug()->has_break_points() : | 250 isolate->debug()->has_break_points() : |
| 247 isolate->debugger()->IsDebuggerActive(); | 251 isolate->debugger()->IsDebuggerActive(); |
| 248 #else | 252 #else |
| 249 return false; | 253 return false; |
| 250 #endif | 254 #endif |
| 251 } | 255 } |
| 252 | 256 |
| 253 | 257 |
| 254 static bool AlwaysFullCompiler(Isolate* isolate) { | 258 static bool AlwaysFullCompiler(Isolate* isolate) { |
| 255 return FLAG_always_full_compiler || IsDebuggerActive(isolate); | 259 return FLAG_always_full_compiler || IsDebuggerActive(isolate); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 if (status != OptimizingCompiler::SUCCEEDED) { | 307 if (status != OptimizingCompiler::SUCCEEDED) { |
| 304 status = compiler.AbortOptimization(); | 308 status = compiler.AbortOptimization(); |
| 305 return status != OptimizingCompiler::FAILED; | 309 return status != OptimizingCompiler::FAILED; |
| 306 } | 310 } |
| 307 status = compiler.GenerateAndInstallCode(); | 311 status = compiler.GenerateAndInstallCode(); |
| 308 return status != OptimizingCompiler::FAILED; | 312 return status != OptimizingCompiler::FAILED; |
| 309 } | 313 } |
| 310 | 314 |
| 311 | 315 |
| 312 OptimizingCompiler::Status OptimizingCompiler::CreateGraph() { | 316 OptimizingCompiler::Status OptimizingCompiler::CreateGraph() { |
| 313 ASSERT(V8::UseCrankshaft()); | 317 ASSERT(isolate()->use_crankshaft()); |
| 314 ASSERT(info()->IsOptimizing()); | 318 ASSERT(info()->IsOptimizing()); |
| 315 ASSERT(!info()->IsCompilingForDebugging()); | 319 ASSERT(!info()->IsCompilingForDebugging()); |
| 316 | 320 |
| 317 // We should never arrive here if there is no code object on the | 321 // We should never arrive here if there is no code object on the |
| 318 // shared function object. | 322 // shared function object. |
| 319 ASSERT(info()->shared_info()->code()->kind() == Code::FUNCTION); | 323 ASSERT(info()->shared_info()->code()->kind() == Code::FUNCTION); |
| 320 | 324 |
| 321 if (FLAG_trace_opt) { | 325 if (FLAG_trace_opt) { |
| 322 // TODO(jbramley): This was added to help analyse the behaviour of | 326 // TODO(jbramley): This was added to help analyse the behaviour of |
| 323 // Crankshaft for the A64 Crankshaft port. It should eventually be deleted. | 327 // Crankshaft for the A64 Crankshaft port. It should eventually be deleted. |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 Handle<Code> optimized_code = chunk_->Codegen(); | 500 Handle<Code> optimized_code = chunk_->Codegen(); |
| 497 if (optimized_code.is_null()) { | 501 if (optimized_code.is_null()) { |
| 498 if (info()->bailout_reason() == kNoReason) { | 502 if (info()->bailout_reason() == kNoReason) { |
| 499 info()->set_bailout_reason(kCodeGenerationFailed); | 503 info()->set_bailout_reason(kCodeGenerationFailed); |
| 500 } | 504 } |
| 501 return AbortOptimization(); | 505 return AbortOptimization(); |
| 502 } | 506 } |
| 503 info()->SetCode(optimized_code); | 507 info()->SetCode(optimized_code); |
| 504 } | 508 } |
| 505 RecordOptimizationStats(); | 509 RecordOptimizationStats(); |
| 510 // Add to the weak list of optimized code objects. |
| 511 info()->context()->native_context()->AddOptimizedCode(*info()->code()); |
| 506 return SetLastStatus(SUCCEEDED); | 512 return SetLastStatus(SUCCEEDED); |
| 507 } | 513 } |
| 508 | 514 |
| 509 | 515 |
| 510 static bool GenerateCode(CompilationInfo* info) { | 516 static bool GenerateCode(CompilationInfo* info) { |
| 511 bool is_optimizing = V8::UseCrankshaft() && | 517 bool is_optimizing = info->isolate()->use_crankshaft() && |
| 512 !info->IsCompilingForDebugging() && | 518 !info->IsCompilingForDebugging() && |
| 513 info->IsOptimizing(); | 519 info->IsOptimizing(); |
| 514 if (is_optimizing) { | 520 if (is_optimizing) { |
| 515 Logger::TimerEventScope timer( | 521 Logger::TimerEventScope timer( |
| 516 info->isolate(), Logger::TimerEventScope::v8_recompile_synchronous); | 522 info->isolate(), Logger::TimerEventScope::v8_recompile_synchronous); |
| 517 return MakeCrankshaftCode(info); | 523 return MakeCrankshaftCode(info); |
| 518 } else { | 524 } else { |
| 519 if (info->IsOptimizing()) { | 525 if (info->IsOptimizing()) { |
| 520 // Have the CompilationInfo decide if the compilation should be | 526 // Have the CompilationInfo decide if the compilation should be |
| 521 // BASE or NONOPT. | 527 // BASE or NONOPT. |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 836 ASSERT(!function->IsOptimized()); | 842 ASSERT(!function->IsOptimized()); |
| 837 } | 843 } |
| 838 | 844 |
| 839 // Set the expected number of properties for instances. | 845 // Set the expected number of properties for instances. |
| 840 FunctionLiteral* lit = info->function(); | 846 FunctionLiteral* lit = info->function(); |
| 841 int expected = lit->expected_property_count(); | 847 int expected = lit->expected_property_count(); |
| 842 SetExpectedNofPropertiesFromEstimate(shared, expected); | 848 SetExpectedNofPropertiesFromEstimate(shared, expected); |
| 843 | 849 |
| 844 // Check the function has compiled code. | 850 // Check the function has compiled code. |
| 845 ASSERT(shared->is_compiled()); | 851 ASSERT(shared->is_compiled()); |
| 846 shared->set_dont_optimize(lit->flags()->Contains(kDontOptimize)); | 852 shared->set_dont_optimize_reason(lit->dont_optimize_reason()); |
| 847 shared->set_dont_inline(lit->flags()->Contains(kDontInline)); | 853 shared->set_dont_inline(lit->flags()->Contains(kDontInline)); |
| 848 shared->set_ast_node_count(lit->ast_node_count()); | 854 shared->set_ast_node_count(lit->ast_node_count()); |
| 849 | 855 |
| 850 if (V8::UseCrankshaft() && | 856 if (info->isolate()->use_crankshaft() && |
| 851 !function.is_null() && | 857 !function.is_null() && |
| 852 !shared->optimization_disabled()) { | 858 !shared->optimization_disabled()) { |
| 853 // If we're asked to always optimize, we compile the optimized | 859 // If we're asked to always optimize, we compile the optimized |
| 854 // version of the function right away - unless the debugger is | 860 // version of the function right away - unless the debugger is |
| 855 // active as it makes no sense to compile optimized code then. | 861 // active as it makes no sense to compile optimized code then. |
| 856 if (FLAG_always_opt && | 862 if (FLAG_always_opt && |
| 857 !info->isolate()->DebuggerHasBreakPoints()) { | 863 !info->isolate()->DebuggerHasBreakPoints()) { |
| 858 CompilationInfoWithZone optimized(function); | 864 CompilationInfoWithZone optimized(function); |
| 859 optimized.SetOptimizing(BailoutId::None()); | 865 optimized.SetOptimizing(BailoutId::None()); |
| 860 return Compiler::CompileLazy(&optimized); | 866 return Compiler::CompileLazy(&optimized); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 877 if (shared->code() == *code) { | 883 if (shared->code() == *code) { |
| 878 // Do not send compilation event for the same code twice. | 884 // Do not send compilation event for the same code twice. |
| 879 return; | 885 return; |
| 880 } | 886 } |
| 881 Compiler::RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared); | 887 Compiler::RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared); |
| 882 } | 888 } |
| 883 | 889 |
| 884 | 890 |
| 885 static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) { | 891 static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) { |
| 886 Handle<Code> code = info->code(); | 892 Handle<Code> code = info->code(); |
| 887 if (FLAG_cache_optimized_code && | 893 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do. |
| 888 info->osr_ast_id().IsNone() && | 894 |
| 889 code->kind() == Code::OPTIMIZED_FUNCTION) { | 895 // Cache non-OSR optimized code. |
| 896 if (FLAG_cache_optimized_code && info->osr_ast_id().IsNone()) { |
| 890 Handle<JSFunction> function = info->closure(); | 897 Handle<JSFunction> function = info->closure(); |
| 891 Handle<SharedFunctionInfo> shared(function->shared()); | 898 Handle<SharedFunctionInfo> shared(function->shared()); |
| 892 Handle<FixedArray> literals(function->literals()); | 899 Handle<FixedArray> literals(function->literals()); |
| 893 Handle<Context> native_context(function->context()->native_context()); | 900 Handle<Context> native_context(function->context()->native_context()); |
| 894 SharedFunctionInfo::AddToOptimizedCodeMap( | 901 SharedFunctionInfo::AddToOptimizedCodeMap( |
| 895 shared, native_context, code, literals); | 902 shared, native_context, code, literals); |
| 896 } | 903 } |
| 897 } | 904 } |
| 898 | 905 |
| 899 | 906 |
| 900 static bool InstallCodeFromOptimizedCodeMap(CompilationInfo* info) { | 907 static bool InstallCodeFromOptimizedCodeMap(CompilationInfo* info) { |
| 901 if (FLAG_cache_optimized_code && | 908 if (!info->IsOptimizing()) return false; // Nothing to look up. |
| 902 info->osr_ast_id().IsNone() && | 909 |
| 903 info->IsOptimizing()) { | 910 // Lookup non-OSR optimized code. |
| 911 if (FLAG_cache_optimized_code && info->osr_ast_id().IsNone()) { |
| 904 Handle<SharedFunctionInfo> shared = info->shared_info(); | 912 Handle<SharedFunctionInfo> shared = info->shared_info(); |
| 905 Handle<JSFunction> function = info->closure(); | 913 Handle<JSFunction> function = info->closure(); |
| 906 ASSERT(!function.is_null()); | 914 ASSERT(!function.is_null()); |
| 907 Handle<Context> native_context(function->context()->native_context()); | 915 Handle<Context> native_context(function->context()->native_context()); |
| 908 int index = shared->SearchOptimizedCodeMap(*native_context); | 916 int index = shared->SearchOptimizedCodeMap(*native_context); |
| 909 if (index > 0) { | 917 if (index > 0) { |
| 910 if (FLAG_trace_opt) { | 918 if (FLAG_trace_opt) { |
| 911 PrintF("[found optimized code for "); | 919 PrintF("[found optimized code for "); |
| 912 function->ShortPrint(); | 920 function->ShortPrint(); |
| 913 PrintF("]\n"); | 921 PrintF("]\n"); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 965 return InstallFullCode(info); | 973 return InstallFullCode(info); |
| 966 } | 974 } |
| 967 } | 975 } |
| 968 } | 976 } |
| 969 | 977 |
| 970 ASSERT(info->code().is_null()); | 978 ASSERT(info->code().is_null()); |
| 971 return false; | 979 return false; |
| 972 } | 980 } |
| 973 | 981 |
| 974 | 982 |
| 975 void Compiler::RecompileConcurrent(Handle<JSFunction> closure) { | 983 bool Compiler::RecompileConcurrent(Handle<JSFunction> closure, |
| 976 ASSERT(closure->IsMarkedForConcurrentRecompilation()); | 984 uint32_t osr_pc_offset) { |
| 985 bool compiling_for_osr = (osr_pc_offset != 0); |
| 977 | 986 |
| 978 Isolate* isolate = closure->GetIsolate(); | 987 Isolate* isolate = closure->GetIsolate(); |
| 979 // Here we prepare compile data for the concurrent recompilation thread, but | 988 // Here we prepare compile data for the concurrent recompilation thread, but |
| 980 // this still happens synchronously and interrupts execution. | 989 // this still happens synchronously and interrupts execution. |
| 981 Logger::TimerEventScope timer( | 990 Logger::TimerEventScope timer( |
| 982 isolate, Logger::TimerEventScope::v8_recompile_synchronous); | 991 isolate, Logger::TimerEventScope::v8_recompile_synchronous); |
| 983 | 992 |
| 984 if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) { | 993 if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) { |
| 985 if (FLAG_trace_concurrent_recompilation) { | 994 if (FLAG_trace_concurrent_recompilation) { |
| 986 PrintF(" ** Compilation queue full, will retry optimizing "); | 995 PrintF(" ** Compilation queue full, will retry optimizing "); |
| 987 closure->PrintName(); | 996 closure->PrintName(); |
| 988 PrintF(" on next run.\n"); | 997 PrintF(" on next run.\n"); |
| 989 } | 998 } |
| 990 return; | 999 return false; |
| 991 } | 1000 } |
| 992 | 1001 |
| 993 SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(closure)); | 1002 SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(closure)); |
| 1003 Handle<SharedFunctionInfo> shared = info->shared_info(); |
| 1004 |
| 1005 if (compiling_for_osr) { |
| 1006 BailoutId osr_ast_id = |
| 1007 shared->code()->TranslatePcOffsetToAstId(osr_pc_offset); |
| 1008 ASSERT(!osr_ast_id.IsNone()); |
| 1009 info->SetOptimizing(osr_ast_id); |
| 1010 info->set_osr_pc_offset(osr_pc_offset); |
| 1011 |
| 1012 if (FLAG_trace_osr) { |
| 1013 PrintF("[COSR - attempt to queue "); |
| 1014 closure->PrintName(); |
| 1015 PrintF(" at AST id %d]\n", osr_ast_id.ToInt()); |
| 1016 } |
| 1017 } else { |
| 1018 info->SetOptimizing(BailoutId::None()); |
| 1019 } |
| 1020 |
| 994 VMState<COMPILER> state(isolate); | 1021 VMState<COMPILER> state(isolate); |
| 995 PostponeInterruptsScope postpone(isolate); | 1022 PostponeInterruptsScope postpone(isolate); |
| 996 | 1023 |
| 997 Handle<SharedFunctionInfo> shared = info->shared_info(); | |
| 998 int compiled_size = shared->end_position() - shared->start_position(); | 1024 int compiled_size = shared->end_position() - shared->start_position(); |
| 999 isolate->counters()->total_compile_size()->Increment(compiled_size); | 1025 isolate->counters()->total_compile_size()->Increment(compiled_size); |
| 1000 info->SetOptimizing(BailoutId::None()); | |
| 1001 | 1026 |
| 1002 { | 1027 { |
| 1003 CompilationHandleScope handle_scope(*info); | 1028 CompilationHandleScope handle_scope(*info); |
| 1004 | 1029 |
| 1005 if (InstallCodeFromOptimizedCodeMap(*info)) { | 1030 if (!compiling_for_osr && InstallCodeFromOptimizedCodeMap(*info)) { |
| 1006 return; | 1031 return true; |
| 1007 } | 1032 } |
| 1008 | 1033 |
| 1009 if (Parser::Parse(*info)) { | 1034 if (Parser::Parse(*info)) { |
| 1010 LanguageMode language_mode = info->function()->language_mode(); | 1035 LanguageMode language_mode = info->function()->language_mode(); |
| 1011 info->SetLanguageMode(language_mode); | 1036 info->SetLanguageMode(language_mode); |
| 1012 shared->set_language_mode(language_mode); | 1037 shared->set_language_mode(language_mode); |
| 1013 info->SaveHandles(); | 1038 info->SaveHandles(); |
| 1014 | 1039 |
| 1015 if (Rewriter::Rewrite(*info) && Scope::Analyze(*info)) { | 1040 if (Rewriter::Rewrite(*info) && Scope::Analyze(*info)) { |
| 1016 OptimizingCompiler* compiler = | 1041 OptimizingCompiler* compiler = |
| 1017 new(info->zone()) OptimizingCompiler(*info); | 1042 new(info->zone()) OptimizingCompiler(*info); |
| 1018 OptimizingCompiler::Status status = compiler->CreateGraph(); | 1043 OptimizingCompiler::Status status = compiler->CreateGraph(); |
| 1019 if (status == OptimizingCompiler::SUCCEEDED) { | 1044 if (status == OptimizingCompiler::SUCCEEDED) { |
| 1020 info.Detach(); | 1045 info.Detach(); |
| 1021 shared->code()->set_profiler_ticks(0); | 1046 shared->code()->set_profiler_ticks(0); |
| 1022 isolate->optimizing_compiler_thread()->QueueForOptimization(compiler); | 1047 isolate->optimizing_compiler_thread()->QueueForOptimization(compiler); |
| 1048 ASSERT(!isolate->has_pending_exception()); |
| 1049 return true; |
| 1023 } else if (status == OptimizingCompiler::BAILED_OUT) { | 1050 } else if (status == OptimizingCompiler::BAILED_OUT) { |
| 1024 isolate->clear_pending_exception(); | 1051 isolate->clear_pending_exception(); |
| 1025 InstallFullCode(*info); | 1052 InstallFullCode(*info); |
| 1026 } | 1053 } |
| 1027 } | 1054 } |
| 1028 } | 1055 } |
| 1029 } | 1056 } |
| 1030 | 1057 |
| 1031 if (shared->code()->back_edges_patched_for_osr()) { | |
| 1032 // At this point we either put the function on recompilation queue or | |
| 1033 // aborted optimization. In either case we want to continue executing | |
| 1034 // the unoptimized code without running into OSR. If the unoptimized | |
| 1035 // code has been patched for OSR, unpatch it. | |
| 1036 Deoptimizer::RevertInterruptCode(isolate, shared->code()); | |
| 1037 } | |
| 1038 | |
| 1039 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); | 1058 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); |
| 1059 return false; |
| 1040 } | 1060 } |
| 1041 | 1061 |
| 1042 | 1062 |
| 1043 void Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) { | 1063 bool Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) { |
| 1044 SmartPointer<CompilationInfo> info(optimizing_compiler->info()); | 1064 SmartPointer<CompilationInfo> info(optimizing_compiler->info()); |
| 1045 // The function may have already been optimized by OSR. Simply continue. | 1065 // The function may have already been optimized by OSR. Simply continue. |
| 1046 // Except when OSR already disabled optimization for some reason. | 1066 // Except when OSR already disabled optimization for some reason. |
| 1047 if (info->shared_info()->optimization_disabled()) { | 1067 if (info->shared_info()->optimization_disabled()) { |
| 1048 info->AbortOptimization(); | 1068 info->AbortOptimization(); |
| 1049 InstallFullCode(*info); | 1069 InstallFullCode(*info); |
| 1050 if (FLAG_trace_concurrent_recompilation) { | 1070 if (FLAG_trace_concurrent_recompilation) { |
| 1051 PrintF(" ** aborting optimization for "); | 1071 PrintF(" ** aborting optimization for "); |
| 1052 info->closure()->PrintName(); | 1072 info->closure()->PrintName(); |
| 1053 PrintF(" as it has been disabled.\n"); | 1073 PrintF(" as it has been disabled.\n"); |
| 1054 } | 1074 } |
| 1055 ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode()); | 1075 ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode()); |
| 1056 return; | 1076 return false; |
| 1057 } | 1077 } |
| 1058 | 1078 |
| 1059 Isolate* isolate = info->isolate(); | 1079 Isolate* isolate = info->isolate(); |
| 1060 VMState<COMPILER> state(isolate); | 1080 VMState<COMPILER> state(isolate); |
| 1061 Logger::TimerEventScope timer( | 1081 Logger::TimerEventScope timer( |
| 1062 isolate, Logger::TimerEventScope::v8_recompile_synchronous); | 1082 isolate, Logger::TimerEventScope::v8_recompile_synchronous); |
| 1063 // If crankshaft succeeded, install the optimized code else install | 1083 // If crankshaft succeeded, install the optimized code else install |
| 1064 // the unoptimized code. | 1084 // the unoptimized code. |
| 1065 OptimizingCompiler::Status status = optimizing_compiler->last_status(); | 1085 OptimizingCompiler::Status status = optimizing_compiler->last_status(); |
| 1066 if (info->HasAbortedDueToDependencyChange()) { | 1086 if (info->HasAbortedDueToDependencyChange()) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1093 PrintF(" installed.\n"); | 1113 PrintF(" installed.\n"); |
| 1094 } | 1114 } |
| 1095 } else { | 1115 } else { |
| 1096 info->AbortOptimization(); | 1116 info->AbortOptimization(); |
| 1097 InstallFullCode(*info); | 1117 InstallFullCode(*info); |
| 1098 } | 1118 } |
| 1099 // Optimized code is finally replacing unoptimized code. Reset the latter's | 1119 // Optimized code is finally replacing unoptimized code. Reset the latter's |
| 1100 // profiler ticks to prevent too soon re-opt after a deopt. | 1120 // profiler ticks to prevent too soon re-opt after a deopt. |
| 1101 info->shared_info()->code()->set_profiler_ticks(0); | 1121 info->shared_info()->code()->set_profiler_ticks(0); |
| 1102 ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode()); | 1122 ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode()); |
| 1123 return status == OptimizingCompiler::SUCCEEDED; |
| 1103 } | 1124 } |
| 1104 | 1125 |
| 1105 | 1126 |
| 1127 static uint32_t CurrentPcOffset(Isolate* isolate, |
| 1128 Handle<JSFunction> function, |
| 1129 Handle<Code> unoptimized) { |
| 1130 JavaScriptFrameIterator it(isolate); |
| 1131 JavaScriptFrame* frame = it.frame(); |
| 1132 ASSERT(frame->function() == *function); |
| 1133 ASSERT(frame->LookupCode() == *unoptimized); |
| 1134 ASSERT(unoptimized->contains(frame->pc())); |
| 1135 |
| 1136 // Use linear search of the unoptimized code's back edge table to find |
| 1137 // the AST id matching the PC. |
| 1138 return static_cast<uint32_t>(frame->pc() - unoptimized->instruction_start()); |
| 1139 } |
| 1140 |
| 1141 |
| 1142 static bool IsSuitableForOnStackReplacement(Isolate* isolate, |
| 1143 Handle<JSFunction> function, |
| 1144 Handle<Code> unoptimized) { |
| 1145 // Keep track of whether we've succeeded in optimizing. |
| 1146 if (!unoptimized->optimizable()) return false; |
| 1147 // If we are trying to do OSR when there are already optimized |
| 1148 // activations of the function, it means (a) the function is directly or |
| 1149 // indirectly recursive and (b) an optimized invocation has been |
| 1150 // deoptimized so that we are currently in an unoptimized activation. |
| 1151 // Check for optimized activations of this function. |
| 1152 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) { |
| 1153 JavaScriptFrame* frame = it.frame(); |
| 1154 if (frame->is_optimized() && frame->function() == *function) return false; |
| 1155 } |
| 1156 |
| 1157 return true; |
| 1158 } |
| 1159 |
| 1160 |
| 1161 BailoutId Compiler::CompileForOnStackReplacement(Handle<JSFunction> function) { |
| 1162 Isolate* isolate = function->GetIsolate(); |
| 1163 // We have hit a back edge in an unoptimized frame for a function that was |
| 1164 // selected for on-stack replacement. Find the unoptimized code object. |
| 1165 Handle<Code> unoptimized(function->shared()->code(), isolate); |
| 1166 |
| 1167 Deoptimizer::RevertInterruptCode(isolate, *unoptimized); |
| 1168 if (FLAG_trace_osr) { |
| 1169 PrintF("[OSR - restored original interrupt calls in "); |
| 1170 function->PrintName(); |
| 1171 PrintF("]\n"); |
| 1172 } |
| 1173 |
| 1174 if (!IsSuitableForOnStackReplacement(isolate, function, unoptimized)) { |
| 1175 return BailoutId::None(); |
| 1176 } |
| 1177 |
| 1178 uint32_t pc_offset = CurrentPcOffset(isolate, function, unoptimized); |
| 1179 |
| 1180 BailoutId ast_id = unoptimized->TranslatePcOffsetToAstId(pc_offset); |
| 1181 ASSERT(!ast_id.IsNone()); |
| 1182 if (FLAG_trace_osr) { |
| 1183 PrintF("[OSR - replacing at AST id %d in ", ast_id.ToInt()); |
| 1184 function->PrintName(); |
| 1185 PrintF("]\n"); |
| 1186 } |
| 1187 |
| 1188 // Try to compile the optimized code. A true return value from |
| 1189 // CompileOptimized means that compilation succeeded, not necessarily |
| 1190 // that optimization succeeded. |
| 1191 if (JSFunction::CompileOptimized(function, ast_id, CLEAR_EXCEPTION) && |
| 1192 function->IsOptimized()) { |
| 1193 DeoptimizationInputData* data = DeoptimizationInputData::cast( |
| 1194 function->code()->deoptimization_data()); |
| 1195 if (data->OsrPcOffset()->value() >= 0) { |
| 1196 if (FLAG_trace_osr) { |
| 1197 PrintF("[OSR - entry, offset %d in optimized code]\n", |
| 1198 data->OsrPcOffset()->value()); |
| 1199 } |
| 1200 ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id); |
| 1201 return ast_id; |
| 1202 } |
| 1203 } else { |
| 1204 if (FLAG_trace_osr) { |
| 1205 PrintF("[OSR - optimization failed for "); |
| 1206 function->PrintName(); |
| 1207 PrintF("]\n"); |
| 1208 } |
| 1209 } |
| 1210 return BailoutId::None(); |
| 1211 } |
| 1212 |
| 1213 |
| 1214 BailoutId Compiler::CompileForConcurrentOSR(Handle<JSFunction> function) { |
| 1215 Isolate* isolate = function->GetIsolate(); |
| 1216 Handle<Code> unoptimized(function->shared()->code(), isolate); |
| 1217 |
| 1218 uint32_t pc_offset = CurrentPcOffset(isolate, function, unoptimized); |
| 1219 |
| 1220 if (isolate->optimizing_compiler_thread()-> |
| 1221 IsQueuedForOSR(function, pc_offset)) { |
| 1222 // Still waiting for the optimizing compiler thread to finish. Carry on. |
| 1223 if (FLAG_trace_osr) { |
| 1224 PrintF("[COSR - polling recompile tasks for "); |
| 1225 function->PrintName(); |
| 1226 PrintF("]\n"); |
| 1227 } |
| 1228 return BailoutId::None(); |
| 1229 } |
| 1230 |
| 1231 OptimizingCompiler* compiler = isolate->optimizing_compiler_thread()-> |
| 1232 FindReadyOSRCandidate(function, pc_offset); |
| 1233 |
| 1234 if (compiler != NULL) { |
| 1235 if (FLAG_trace_osr) { |
| 1236 PrintF("[COSR - optimization complete for "); |
| 1237 function->PrintName(); |
| 1238 PrintF(", restoring interrupt calls]\n"); |
| 1239 } |
| 1240 Deoptimizer::RevertInterruptCode(isolate, *unoptimized); |
| 1241 |
| 1242 BailoutId ast_id = compiler->info()->osr_ast_id(); |
| 1243 |
| 1244 bool succeeded = InstallOptimizedCode(compiler); |
| 1245 |
| 1246 isolate->optimizing_compiler_thread()->RemoveStaleOSRCandidates(); |
| 1247 |
| 1248 if (!succeeded) { |
| 1249 if (FLAG_trace_osr) { |
| 1250 PrintF("[COSR - optimization failed for "); |
| 1251 function->PrintName(); |
| 1252 PrintF("]\n"); |
| 1253 } |
| 1254 return BailoutId::None(); |
| 1255 } |
| 1256 |
| 1257 DeoptimizationInputData* data = DeoptimizationInputData::cast( |
| 1258 function->code()->deoptimization_data()); |
| 1259 |
| 1260 if (data->OsrPcOffset()->value() >= 0) { |
| 1261 ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id); |
| 1262 if (FLAG_trace_osr) { |
| 1263 PrintF("[COSR - entry at AST id %d, offset %d in optimized code]\n", |
| 1264 ast_id.ToInt(), data->OsrPcOffset()->value()); |
| 1265 } |
| 1266 return ast_id; |
| 1267 } |
| 1268 return BailoutId::None(); |
| 1269 } |
| 1270 |
| 1271 if (!IsSuitableForOnStackReplacement(isolate, function, unoptimized)) { |
| 1272 if (FLAG_trace_osr) { |
| 1273 PrintF("[COSR - "); |
| 1274 function->PrintName(); |
| 1275 PrintF(" is unsuitable, restoring interrupt calls]\n"); |
| 1276 } |
| 1277 Deoptimizer::RevertInterruptCode(isolate, *unoptimized); |
| 1278 return BailoutId::None(); |
| 1279 } |
| 1280 |
| 1281 if (!RecompileConcurrent(function, pc_offset)) { |
| 1282 Deoptimizer::RevertInterruptCode(isolate, *unoptimized); |
| 1283 } |
| 1284 return BailoutId::None(); |
| 1285 } |
| 1286 |
| 1287 |
| 1106 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, | 1288 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, |
| 1107 Handle<Script> script) { | 1289 Handle<Script> script) { |
| 1108 // Precondition: code has been parsed and scopes have been analyzed. | 1290 // Precondition: code has been parsed and scopes have been analyzed. |
| 1109 CompilationInfoWithZone info(script); | 1291 CompilationInfoWithZone info(script); |
| 1110 info.SetFunction(literal); | 1292 info.SetFunction(literal); |
| 1111 info.SetScope(literal->scope()); | 1293 info.SetScope(literal->scope()); |
| 1112 info.SetLanguageMode(literal->scope()->language_mode()); | 1294 info.SetLanguageMode(literal->scope()->language_mode()); |
| 1113 | 1295 |
| 1114 Isolate* isolate = info.isolate(); | 1296 Isolate* isolate = info.isolate(); |
| 1115 Factory* factory = isolate->factory(); | 1297 Factory* factory = isolate->factory(); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1180 function_info->set_is_toplevel(is_toplevel); | 1362 function_info->set_is_toplevel(is_toplevel); |
| 1181 function_info->set_inferred_name(*lit->inferred_name()); | 1363 function_info->set_inferred_name(*lit->inferred_name()); |
| 1182 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation()); | 1364 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation()); |
| 1183 function_info->set_allows_lazy_compilation_without_context( | 1365 function_info->set_allows_lazy_compilation_without_context( |
| 1184 lit->AllowsLazyCompilationWithoutContext()); | 1366 lit->AllowsLazyCompilationWithoutContext()); |
| 1185 function_info->set_language_mode(lit->language_mode()); | 1367 function_info->set_language_mode(lit->language_mode()); |
| 1186 function_info->set_uses_arguments(lit->scope()->arguments() != NULL); | 1368 function_info->set_uses_arguments(lit->scope()->arguments() != NULL); |
| 1187 function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters()); | 1369 function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters()); |
| 1188 function_info->set_ast_node_count(lit->ast_node_count()); | 1370 function_info->set_ast_node_count(lit->ast_node_count()); |
| 1189 function_info->set_is_function(lit->is_function()); | 1371 function_info->set_is_function(lit->is_function()); |
| 1190 function_info->set_dont_optimize(lit->flags()->Contains(kDontOptimize)); | 1372 function_info->set_dont_optimize_reason(lit->dont_optimize_reason()); |
| 1191 function_info->set_dont_inline(lit->flags()->Contains(kDontInline)); | 1373 function_info->set_dont_inline(lit->flags()->Contains(kDontInline)); |
| 1192 function_info->set_dont_cache(lit->flags()->Contains(kDontCache)); | 1374 function_info->set_dont_cache(lit->flags()->Contains(kDontCache)); |
| 1193 function_info->set_is_generator(lit->is_generator()); | 1375 function_info->set_is_generator(lit->is_generator()); |
| 1194 } | 1376 } |
| 1195 | 1377 |
| 1196 | 1378 |
| 1197 void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag, | 1379 void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag, |
| 1198 CompilationInfo* info, | 1380 CompilationInfo* info, |
| 1199 Handle<SharedFunctionInfo> shared) { | 1381 Handle<SharedFunctionInfo> shared) { |
| 1200 // SharedFunctionInfo is passed separately, because if CompilationInfo | 1382 // SharedFunctionInfo is passed separately, because if CompilationInfo |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1265 AllowHandleDereference allow_deref; | 1447 AllowHandleDereference allow_deref; |
| 1266 bool tracing_on = info()->IsStub() | 1448 bool tracing_on = info()->IsStub() |
| 1267 ? FLAG_trace_hydrogen_stubs | 1449 ? FLAG_trace_hydrogen_stubs |
| 1268 : (FLAG_trace_hydrogen && | 1450 : (FLAG_trace_hydrogen && |
| 1269 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); | 1451 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); |
| 1270 return (tracing_on && | 1452 return (tracing_on && |
| 1271 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); | 1453 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); |
| 1272 } | 1454 } |
| 1273 | 1455 |
| 1274 } } // namespace v8::internal | 1456 } } // namespace v8::internal |
| OLD | NEW |