Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(700)

Side by Side Diff: src/compiler.cc

Issue 23710014: Introduce concurrent on-stack replacement. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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;
(...skipping 852 matching lines...) Expand 10 before | Expand all | Expand 10 after
956 return InstallFullCode(info); 960 return InstallFullCode(info);
957 } 961 }
958 } 962 }
959 } 963 }
960 964
961 ASSERT(info->code().is_null()); 965 ASSERT(info->code().is_null());
962 return false; 966 return false;
963 } 967 }
964 968
965 969
966 void Compiler::RecompileConcurrent(Handle<JSFunction> closure) { 970 bool Compiler::RecompileConcurrent(Handle<JSFunction> closure,
967 ASSERT(closure->IsMarkedForConcurrentRecompilation()); 971 uint32_t osr_pc_offset) {
972 bool compiling_for_osr = (osr_pc_offset != 0);
973 ASSERT(compiling_for_osr || closure->IsMarkedForConcurrentRecompilation());
titzer 2013/09/04 09:23:23 On second thought, yes, please take the assert out
Yang 2013/09/04 12:55:12 Done.
968 974
969 Isolate* isolate = closure->GetIsolate(); 975 Isolate* isolate = closure->GetIsolate();
970 // Here we prepare compile data for the concurrent recompilation thread, but 976 // Here we prepare compile data for the concurrent recompilation thread, but
971 // this still happens synchronously and interrupts execution. 977 // this still happens synchronously and interrupts execution.
972 Logger::TimerEventScope timer( 978 Logger::TimerEventScope timer(
973 isolate, Logger::TimerEventScope::v8_recompile_synchronous); 979 isolate, Logger::TimerEventScope::v8_recompile_synchronous);
974 980
975 if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) { 981 if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) {
976 if (FLAG_trace_concurrent_recompilation) { 982 if (FLAG_trace_concurrent_recompilation) {
977 PrintF(" ** Compilation queue full, will retry optimizing "); 983 PrintF(" ** Compilation queue full, will retry optimizing ");
978 closure->PrintName(); 984 closure->PrintName();
979 PrintF(" on next run.\n"); 985 PrintF(" on next run.\n");
980 } 986 }
981 return; 987 return false;
982 } 988 }
983 989
984 SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(closure)); 990 SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(closure));
991 Handle<SharedFunctionInfo> shared = info->shared_info();
992
993 if (compiling_for_osr) {
994 BailoutId osr_ast_id =
995 shared->code()->TranslatePcOffsetToAstId(osr_pc_offset);
996 ASSERT(!osr_ast_id.IsNone());
997 info->SetOptimizing(osr_ast_id);
998 info->set_osr_pc_offset(osr_pc_offset);
999
1000 if (FLAG_trace_osr) {
1001 PrintF("[COSR - attempt to queue ");
1002 closure->PrintName();
1003 PrintF(" at AST id %d]\n", osr_ast_id.ToInt());
1004 }
1005 } else {
1006 info->SetOptimizing(BailoutId::None());
1007 }
1008
985 VMState<COMPILER> state(isolate); 1009 VMState<COMPILER> state(isolate);
986 PostponeInterruptsScope postpone(isolate); 1010 PostponeInterruptsScope postpone(isolate);
987 1011
988 Handle<SharedFunctionInfo> shared = info->shared_info();
989 int compiled_size = shared->end_position() - shared->start_position(); 1012 int compiled_size = shared->end_position() - shared->start_position();
990 isolate->counters()->total_compile_size()->Increment(compiled_size); 1013 isolate->counters()->total_compile_size()->Increment(compiled_size);
991 info->SetOptimizing(BailoutId::None());
992 1014
993 { 1015 {
994 CompilationHandleScope handle_scope(*info); 1016 CompilationHandleScope handle_scope(*info);
995 1017
996 if (InstallCodeFromOptimizedCodeMap(*info)) { 1018 if (!compiling_for_osr && InstallCodeFromOptimizedCodeMap(*info)) {
997 return; 1019 return true;
998 } 1020 }
999 1021
1000 if (Parser::Parse(*info)) { 1022 if (Parser::Parse(*info)) {
1001 LanguageMode language_mode = info->function()->language_mode(); 1023 LanguageMode language_mode = info->function()->language_mode();
1002 info->SetLanguageMode(language_mode); 1024 info->SetLanguageMode(language_mode);
1003 shared->set_language_mode(language_mode); 1025 shared->set_language_mode(language_mode);
1004 info->SaveHandles(); 1026 info->SaveHandles();
1005 1027
1006 if (Rewriter::Rewrite(*info) && Scope::Analyze(*info)) { 1028 if (Rewriter::Rewrite(*info) && Scope::Analyze(*info)) {
1007 OptimizingCompiler* compiler = 1029 OptimizingCompiler* compiler =
1008 new(info->zone()) OptimizingCompiler(*info); 1030 new(info->zone()) OptimizingCompiler(*info);
1009 OptimizingCompiler::Status status = compiler->CreateGraph(); 1031 OptimizingCompiler::Status status = compiler->CreateGraph();
1010 if (status == OptimizingCompiler::SUCCEEDED) { 1032 if (status == OptimizingCompiler::SUCCEEDED) {
1011 info.Detach(); 1033 info.Detach();
1012 shared->code()->set_profiler_ticks(0); 1034 shared->code()->set_profiler_ticks(0);
1013 isolate->optimizing_compiler_thread()->QueueForOptimization(compiler); 1035 isolate->optimizing_compiler_thread()->QueueForOptimization(compiler);
1036 ASSERT(!isolate->has_pending_exception());
1037 return true;
1014 } else if (status == OptimizingCompiler::BAILED_OUT) { 1038 } else if (status == OptimizingCompiler::BAILED_OUT) {
1015 isolate->clear_pending_exception(); 1039 isolate->clear_pending_exception();
1016 InstallFullCode(*info); 1040 InstallFullCode(*info);
1017 } 1041 }
1018 } 1042 }
1019 } 1043 }
1020 } 1044 }
1021 1045
1022 if (shared->code()->back_edges_patched_for_osr()) {
1023 // At this point we either put the function on recompilation queue or
1024 // aborted optimization. In either case we want to continue executing
1025 // the unoptimized code without running into OSR. If the unoptimized
1026 // code has been patched for OSR, unpatch it.
1027 Deoptimizer::RevertInterruptCode(isolate, shared->code());
1028 }
1029
1030 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); 1046 if (isolate->has_pending_exception()) isolate->clear_pending_exception();
1047 return false;
1031 } 1048 }
1032 1049
1033 1050
1034 void Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) { 1051 bool Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) {
1035 SmartPointer<CompilationInfo> info(optimizing_compiler->info()); 1052 SmartPointer<CompilationInfo> info(optimizing_compiler->info());
1036 // The function may have already been optimized by OSR. Simply continue. 1053 // The function may have already been optimized by OSR. Simply continue.
1037 // Except when OSR already disabled optimization for some reason. 1054 // Except when OSR already disabled optimization for some reason.
1038 if (info->shared_info()->optimization_disabled()) { 1055 if (info->shared_info()->optimization_disabled()) {
1039 info->AbortOptimization(); 1056 info->AbortOptimization();
1040 InstallFullCode(*info); 1057 InstallFullCode(*info);
1041 if (FLAG_trace_concurrent_recompilation) { 1058 if (FLAG_trace_concurrent_recompilation) {
1042 PrintF(" ** aborting optimization for "); 1059 PrintF(" ** aborting optimization for ");
1043 info->closure()->PrintName(); 1060 info->closure()->PrintName();
1044 PrintF(" as it has been disabled.\n"); 1061 PrintF(" as it has been disabled.\n");
1045 } 1062 }
1046 ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode()); 1063 ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode());
1047 return; 1064 return false;
1048 } 1065 }
1049 1066
1050 Isolate* isolate = info->isolate(); 1067 Isolate* isolate = info->isolate();
1051 VMState<COMPILER> state(isolate); 1068 VMState<COMPILER> state(isolate);
1052 Logger::TimerEventScope timer( 1069 Logger::TimerEventScope timer(
1053 isolate, Logger::TimerEventScope::v8_recompile_synchronous); 1070 isolate, Logger::TimerEventScope::v8_recompile_synchronous);
1054 // If crankshaft succeeded, install the optimized code else install 1071 // If crankshaft succeeded, install the optimized code else install
1055 // the unoptimized code. 1072 // the unoptimized code.
1056 OptimizingCompiler::Status status = optimizing_compiler->last_status(); 1073 OptimizingCompiler::Status status = optimizing_compiler->last_status();
1057 if (info->HasAbortedDueToDependencyChange()) { 1074 if (info->HasAbortedDueToDependencyChange()) {
(...skipping 26 matching lines...) Expand all
1084 PrintF(" installed.\n"); 1101 PrintF(" installed.\n");
1085 } 1102 }
1086 } else { 1103 } else {
1087 info->AbortOptimization(); 1104 info->AbortOptimization();
1088 InstallFullCode(*info); 1105 InstallFullCode(*info);
1089 } 1106 }
1090 // Optimized code is finally replacing unoptimized code. Reset the latter's 1107 // Optimized code is finally replacing unoptimized code. Reset the latter's
1091 // profiler ticks to prevent too soon re-opt after a deopt. 1108 // profiler ticks to prevent too soon re-opt after a deopt.
1092 info->shared_info()->code()->set_profiler_ticks(0); 1109 info->shared_info()->code()->set_profiler_ticks(0);
1093 ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode()); 1110 ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode());
1111 return status == OptimizingCompiler::SUCCEEDED;
1094 } 1112 }
1095 1113
1096 1114
1115 static uint32_t CurrentPcOffset(Isolate* isolate,
1116 Handle<JSFunction> function,
1117 Handle<Code> unoptimized) {
1118 JavaScriptFrameIterator it(isolate);
1119 JavaScriptFrame* frame = it.frame();
1120 ASSERT(frame->function() == *function);
1121 ASSERT(frame->LookupCode() == *unoptimized);
1122 ASSERT(unoptimized->contains(frame->pc()));
1123
1124 // Use linear search of the unoptimized code's back edge table to find
1125 // the AST id matching the PC.
1126 return static_cast<uint32_t>(frame->pc() - unoptimized->instruction_start());
1127 }
1128
1129
1130 static bool IsSuitableForOnStackReplacement(Isolate* isolate,
1131 Handle<JSFunction> function,
1132 Handle<Code> unoptimized) {
1133 // Keep track of whether we've succeeded in optimizing.
1134 if (!unoptimized->optimizable()) return false;
1135 // If we are trying to do OSR when there are already optimized
1136 // activations of the function, it means (a) the function is directly or
1137 // indirectly recursive and (b) an optimized invocation has been
1138 // deoptimized so that we are currently in an unoptimized activation.
1139 // Check for optimized activations of this function.
1140 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
1141 JavaScriptFrame* frame = it.frame();
1142 if (frame->is_optimized() && frame->function() == *function) return false;
1143 }
1144
1145 return true;
1146 }
1147
1148
1149 BailoutId Compiler::CompileForOnStackReplacement(Handle<JSFunction> function) {
1150 Isolate* isolate = function->GetIsolate();
1151 // We have hit a back edge in an unoptimized frame for a function that was
1152 // selected for on-stack replacement. Find the unoptimized code object.
1153 Handle<Code> unoptimized(function->shared()->code(), isolate);
1154
1155 Deoptimizer::RevertInterruptCode(isolate, *unoptimized);
1156 if (FLAG_trace_osr) {
1157 PrintF("[OSR - restored original interrupt calls in ");
1158 function->PrintName();
1159 PrintF("]\n");
1160 }
1161
1162 if (!IsSuitableForOnStackReplacement(isolate, function, unoptimized)) {
1163 return BailoutId::None();
1164 }
1165
1166 uint32_t pc_offset = CurrentPcOffset(isolate, function, unoptimized);
1167
1168 BailoutId ast_id = unoptimized->TranslatePcOffsetToAstId(pc_offset);
1169 ASSERT(!ast_id.IsNone());
1170 if (FLAG_trace_osr) {
1171 PrintF("[OSR - replacing at AST id %d in ", ast_id.ToInt());
1172 function->PrintName();
1173 PrintF("]\n");
1174 }
1175
1176 // Try to compile the optimized code. A true return value from
1177 // CompileOptimized means that compilation succeeded, not necessarily
1178 // that optimization succeeded.
1179 if (JSFunction::CompileOptimized(function, ast_id, CLEAR_EXCEPTION) &&
1180 function->IsOptimized()) {
1181 DeoptimizationInputData* data = DeoptimizationInputData::cast(
1182 function->code()->deoptimization_data());
1183 if (data->OsrPcOffset()->value() >= 0) {
1184 if (FLAG_trace_osr) {
1185 PrintF("[OSR - entry, offset %d in optimized code]\n",
1186 data->OsrPcOffset()->value());
1187 }
1188 ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id);
1189 return ast_id;
1190 }
1191 } else {
1192 if (FLAG_trace_osr) {
1193 PrintF("[OSR - optimization failed for ");
1194 function->PrintName();
1195 PrintF("]\n");
1196 }
1197 }
1198 return BailoutId::None();
1199 }
1200
1201
1202 BailoutId Compiler::CompileForConcurrentOSR(Handle<JSFunction> function) {
1203 ASSERT(FLAG_concurrent_recompilation && FLAG_speculative_concurrent_osr);
1204
1205 Isolate* isolate = function->GetIsolate();
1206 Handle<Code> unoptimized(function->shared()->code(), isolate);
1207
1208 uint32_t pc_offset = CurrentPcOffset(isolate, function, unoptimized);
1209
1210 if (isolate->optimizing_compiler_thread()->
1211 IsQueuedForOSR(function, pc_offset)) {
1212 // Still waiting for the optimizing compiler thread to finish. Carry on.
1213 if (FLAG_trace_osr) {
1214 PrintF("[COSR - polling recompile tasks for ");
1215 function->PrintName();
1216 PrintF("]\n");
1217 }
1218 return BailoutId::None();
1219 }
1220
1221 OptimizingCompiler* compiler = isolate->optimizing_compiler_thread()->
1222 FindReadyOSRCandidate(function, pc_offset);
1223
1224 if (compiler != NULL) {
1225 if (FLAG_trace_osr) {
1226 PrintF("[COSR - optimization complete for ");
1227 function->PrintName();
1228 PrintF(", restoring interrupt calls]\n");
1229 }
1230 Deoptimizer::RevertInterruptCode(isolate, *unoptimized);
1231
1232 BailoutId ast_id = compiler->info()->osr_ast_id();
1233
1234 bool succeeded = InstallOptimizedCode(compiler);
1235
1236 isolate->optimizing_compiler_thread()->RemoveStaleOSRCandidates();
1237
1238 if (!succeeded) {
1239 if (FLAG_trace_osr) {
1240 PrintF("[COSR - optimization failed for ");
1241 function->PrintName();
1242 PrintF("]\n");
1243 }
1244 return BailoutId::None();
1245 }
1246
1247 DeoptimizationInputData* data = DeoptimizationInputData::cast(
1248 function->code()->deoptimization_data());
1249
1250 if (data->OsrPcOffset()->value() >= 0) {
1251 ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id);
1252 if (FLAG_trace_osr) {
1253 PrintF("[COSR - entry at AST id %d, offset %d in optimized code]\n",
1254 ast_id.ToInt(), data->OsrPcOffset()->value());
1255 }
1256 return ast_id;
1257 }
1258 return BailoutId::None();
1259 }
1260
1261 if (!IsSuitableForOnStackReplacement(isolate, function, unoptimized)) {
1262 if (FLAG_trace_osr) {
1263 PrintF("[COSR - ");
1264 function->PrintName();
1265 PrintF(" is unsuitable, restoring interrupt calls]\n");
1266 }
1267 Deoptimizer::RevertInterruptCode(isolate, *unoptimized);
1268 return BailoutId::None();
1269 }
1270
1271 if (!RecompileConcurrent(function, pc_offset)) {
1272 Deoptimizer::RevertInterruptCode(isolate, *unoptimized);
1273 }
1274 return BailoutId::None();
1275 }
1276
1277
1097 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, 1278 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
1098 Handle<Script> script) { 1279 Handle<Script> script) {
1099 // Precondition: code has been parsed and scopes have been analyzed. 1280 // Precondition: code has been parsed and scopes have been analyzed.
1100 CompilationInfoWithZone info(script); 1281 CompilationInfoWithZone info(script);
1101 info.SetFunction(literal); 1282 info.SetFunction(literal);
1102 info.SetScope(literal->scope()); 1283 info.SetScope(literal->scope());
1103 info.SetLanguageMode(literal->scope()->language_mode()); 1284 info.SetLanguageMode(literal->scope()->language_mode());
1104 1285
1105 Isolate* isolate = info.isolate(); 1286 Isolate* isolate = info.isolate();
1106 Factory* factory = isolate->factory(); 1287 Factory* factory = isolate->factory();
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
1256 AllowHandleDereference allow_deref; 1437 AllowHandleDereference allow_deref;
1257 bool tracing_on = info()->IsStub() 1438 bool tracing_on = info()->IsStub()
1258 ? FLAG_trace_hydrogen_stubs 1439 ? FLAG_trace_hydrogen_stubs
1259 : (FLAG_trace_hydrogen && 1440 : (FLAG_trace_hydrogen &&
1260 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); 1441 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter));
1261 return (tracing_on && 1442 return (tracing_on &&
1262 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); 1443 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL);
1263 } 1444 }
1264 1445
1265 } } // namespace v8::internal 1446 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/compiler.h ('k') | src/deoptimizer.h » ('j') | src/flag-definitions.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698