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

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: addressed comments. 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 void Compiler::RecompileConcurrent(Handle<JSFunction> closure,
967 ASSERT(closure->IsMarkedForConcurrentRecompilation()); 971 uint32_t osr_pc_offset) {
972 ASSERT(osr_pc_offset != 0 || closure->IsMarkedForConcurrentRecompilation());
titzer 2013/09/03 14:05:36 Not sure what you are trying to assert here.
Yang 2013/09/03 14:49:44 Asserting that if we are not recompiling for OSR,
968 973
969 Isolate* isolate = closure->GetIsolate(); 974 Isolate* isolate = closure->GetIsolate();
970 // Here we prepare compile data for the concurrent recompilation thread, but 975 // Here we prepare compile data for the concurrent recompilation thread, but
971 // this still happens synchronously and interrupts execution. 976 // this still happens synchronously and interrupts execution.
972 Logger::TimerEventScope timer( 977 Logger::TimerEventScope timer(
973 isolate, Logger::TimerEventScope::v8_recompile_synchronous); 978 isolate, Logger::TimerEventScope::v8_recompile_synchronous);
974 979
975 if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) { 980 if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) {
976 if (FLAG_trace_concurrent_recompilation) { 981 if (FLAG_trace_concurrent_recompilation) {
977 PrintF(" ** Compilation queue full, will retry optimizing "); 982 PrintF(" ** Compilation queue full, will retry optimizing ");
978 closure->PrintName(); 983 closure->PrintName();
979 PrintF(" on next run.\n"); 984 PrintF(" on next run.\n");
980 } 985 }
981 return; 986 return;
982 } 987 }
983 988
984 SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(closure)); 989 SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(closure));
990 Handle<SharedFunctionInfo> shared = info->shared_info();
991
992 if (osr_pc_offset != 0) {
993 int loop_depth;
994 BailoutId osr_ast_id = shared->code()->TranslatePcOffsetToAstId(
titzer 2013/09/03 14:05:36 Are you calling this method in another place? Othe
Yang 2013/09/03 14:49:44 Done.
995 osr_pc_offset, &loop_depth);
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(" for concurrent compilation at AST id %d, loop depth %d]\n",
1004 osr_ast_id.ToInt(), loop_depth);
1005 }
1006 } else {
1007 info->SetOptimizing(BailoutId::None());
1008 }
1009
985 VMState<COMPILER> state(isolate); 1010 VMState<COMPILER> state(isolate);
986 PostponeInterruptsScope postpone(isolate); 1011 PostponeInterruptsScope postpone(isolate);
987 1012
988 Handle<SharedFunctionInfo> shared = info->shared_info();
989 int compiled_size = shared->end_position() - shared->start_position(); 1013 int compiled_size = shared->end_position() - shared->start_position();
990 isolate->counters()->total_compile_size()->Increment(compiled_size); 1014 isolate->counters()->total_compile_size()->Increment(compiled_size);
991 info->SetOptimizing(BailoutId::None());
992 1015
993 { 1016 {
994 CompilationHandleScope handle_scope(*info); 1017 CompilationHandleScope handle_scope(*info);
995 1018
996 if (InstallCodeFromOptimizedCodeMap(*info)) { 1019 if (InstallCodeFromOptimizedCodeMap(*info)) {
997 return; 1020 return;
998 } 1021 }
999 1022
1000 if (Parser::Parse(*info)) { 1023 if (Parser::Parse(*info)) {
1001 LanguageMode language_mode = info->function()->language_mode(); 1024 LanguageMode language_mode = info->function()->language_mode();
(...skipping 10 matching lines...) Expand all
1012 shared->code()->set_profiler_ticks(0); 1035 shared->code()->set_profiler_ticks(0);
1013 isolate->optimizing_compiler_thread()->QueueForOptimization(compiler); 1036 isolate->optimizing_compiler_thread()->QueueForOptimization(compiler);
1014 } else if (status == OptimizingCompiler::BAILED_OUT) { 1037 } else if (status == OptimizingCompiler::BAILED_OUT) {
1015 isolate->clear_pending_exception(); 1038 isolate->clear_pending_exception();
1016 InstallFullCode(*info); 1039 InstallFullCode(*info);
1017 } 1040 }
1018 } 1041 }
1019 } 1042 }
1020 } 1043 }
1021 1044
1022 if (shared->code()->back_edges_patched_for_osr()) { 1045 // If we don't compile for on-stack replacement in the background thread,
1023 // At this point we either put the function on recompilation queue or 1046 // reset the OSR attempt to avoid recompilation being preempted by OSR.
1024 // aborted optimization. In either case we want to continue executing 1047 if (!FLAG_speculative_concurrent_osr &&
1025 // the unoptimized code without running into OSR. If the unoptimized 1048 shared->code()->back_edges_patched_for_osr()) {
1026 // code has been patched for OSR, unpatch it.
1027 Deoptimizer::RevertInterruptCode(isolate, shared->code()); 1049 Deoptimizer::RevertInterruptCode(isolate, shared->code());
1028 } 1050 }
1029 1051
1030 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); 1052 if (isolate->has_pending_exception()) isolate->clear_pending_exception();
1031 } 1053 }
1032 1054
1033 1055
1034 void Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) { 1056 void Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) {
1035 SmartPointer<CompilationInfo> info(optimizing_compiler->info()); 1057 SmartPointer<CompilationInfo> info(optimizing_compiler->info());
1036 // The function may have already been optimized by OSR. Simply continue. 1058 // The function may have already been optimized by OSR. Simply continue.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1087 info->AbortOptimization(); 1109 info->AbortOptimization();
1088 InstallFullCode(*info); 1110 InstallFullCode(*info);
1089 } 1111 }
1090 // Optimized code is finally replacing unoptimized code. Reset the latter's 1112 // Optimized code is finally replacing unoptimized code. Reset the latter's
1091 // profiler ticks to prevent too soon re-opt after a deopt. 1113 // profiler ticks to prevent too soon re-opt after a deopt.
1092 info->shared_info()->code()->set_profiler_ticks(0); 1114 info->shared_info()->code()->set_profiler_ticks(0);
1093 ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode()); 1115 ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode());
1094 } 1116 }
1095 1117
1096 1118
1119 static uint32_t CurrentPcOffset(Isolate* isolate,
1120 Handle<JSFunction> function,
1121 Handle<Code> unoptimized) {
titzer 2013/09/03 14:05:36 Please put the mechanism for finding the osr_pc_of
Yang 2013/09/03 14:49:44 I got a CL in queue that removes this completely.
1122 JavaScriptFrameIterator it(isolate);
1123 JavaScriptFrame* frame = it.frame();
1124 ASSERT(frame->function() == *function);
1125 ASSERT(frame->LookupCode() == *unoptimized);
1126 ASSERT(unoptimized->contains(frame->pc()));
1127
1128 // Use linear search of the unoptimized code's back edge table to find
1129 // the AST id matching the PC.
1130 return static_cast<uint32_t>(frame->pc() - unoptimized->instruction_start());
1131 }
1132
1133
1134 static bool IsSuitableForOnStackReplacement(Isolate* isolate,
1135 Handle<JSFunction> function,
1136 Handle<Code> unoptimized) {
1137 // Keep track of whether we've succeeded in optimizing.
1138 if (!unoptimized->optimizable()) return false;
1139 // If we are trying to do OSR when there are already optimized
1140 // activations of the function, it means (a) the function is directly or
1141 // indirectly recursive and (b) an optimized invocation has been
1142 // deoptimized so that we are currently in an unoptimized activation.
1143 // Check for optimized activations of this function.
1144 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
1145 JavaScriptFrame* frame = it.frame();
1146 if (frame->is_optimized() && frame->function() == *function) return false;
1147 }
1148
1149 return true;
1150 }
1151
1152
1153 bool Compiler::CompileForOnStackReplacement(Handle<JSFunction> function,
1154 BailoutId* ast_id) {
titzer 2013/09/03 14:05:36 This should take the osr_pc_offset as a parameter.
Yang 2013/09/03 14:49:44 Ditto. CL queued up doing exactly that.
1155 Isolate* isolate = function->GetIsolate();
1156 // We have hit a back edge in an unoptimized frame for a function that was
1157 // selected for on-stack replacement. Find the unoptimized code object.
1158 Handle<Code> unoptimized(function->shared()->code(), isolate);
1159
1160 Deoptimizer::RevertInterruptCode(isolate, *unoptimized);
1161 if (FLAG_trace_osr) {
1162 PrintF("[OSR - restored original interrupt calls in ");
1163 function->PrintName();
1164 PrintF("]\n");
1165 }
1166
1167 if (!IsSuitableForOnStackReplacement(isolate, function, unoptimized)) {
1168 return false;
1169 }
1170
1171 uint32_t pc_offset = CurrentPcOffset(isolate, function, unoptimized);
1172
1173 int loop_depth;
1174 *ast_id = unoptimized->TranslatePcOffsetToAstId(pc_offset, &loop_depth);
titzer 2013/09/03 14:05:36 If you move this code back to the runtime, you don
Yang 2013/09/03 14:49:44 I changed this so that we return the AST id direct
1175 ASSERT(!ast_id->IsNone());
1176 if (FLAG_trace_osr) {
1177 PrintF("[OSR - replacing at AST id %d, loop depth %d in ",
1178 ast_id->ToInt(), loop_depth);
1179 function->PrintName();
1180 PrintF("]\n");
1181 }
1182
1183 // Try to compile the optimized code. A true return value from
1184 // CompileOptimized means that compilation succeeded, not necessarily
1185 // that optimization succeeded.
1186 if (JSFunction::CompileOptimized(function, *ast_id, CLEAR_EXCEPTION) &&
1187 function->IsOptimized()) {
1188 DeoptimizationInputData* data = DeoptimizationInputData::cast(
1189 function->code()->deoptimization_data());
1190 if (data->OsrPcOffset()->value() >= 0) {
1191 if (FLAG_trace_osr) {
1192 PrintF("[OSR - entry, offset %d in optimized code]\n",
1193 data->OsrPcOffset()->value());
1194 }
1195 ASSERT(BailoutId(data->OsrAstId()->value()) == *ast_id);
1196 return true;
1197 }
1198 } else {
1199 if (FLAG_trace_osr) {
1200 PrintF("[OSR - optimization failed for ");
1201 function->PrintName();
1202 PrintF("]\n");
1203 }
1204 }
1205 return false;
1206 }
1207
1208
1209 bool Compiler::CompileForConcurrentOSR(Handle<JSFunction> function,
1210 BailoutId* ast_id) {
1211 ASSERT(FLAG_concurrent_recompilation && FLAG_speculative_concurrent_osr);
1212
1213 Isolate* isolate = function->GetIsolate();
1214 Handle<Code> unoptimized(function->shared()->code(), isolate);
1215
1216 uint32_t pc_offset = CurrentPcOffset(isolate, function, unoptimized);
1217
1218 if (isolate->optimizing_compiler_thread()->
1219 IsQueuedForOSR(function, pc_offset)) {
1220 // Still waiting for the optimizing compiler thread to finish. Carry on.
1221 if (FLAG_trace_osr) {
1222 PrintF("[COSR - polling recompile tasks for ");
1223 function->PrintName();
1224 PrintF("]\n");
1225 }
1226 return false;
1227 }
1228
1229 OptimizingCompiler* compiler = isolate->optimizing_compiler_thread()->
1230 FindReadyOSRCandidate(function, pc_offset);
1231
1232 if (compiler != NULL) {
1233 if (FLAG_trace_osr) {
1234 PrintF("[COSR - optimization complete for ");
1235 function->PrintName();
1236 PrintF(", restoring interrupt calls]\n");
1237 }
1238 Deoptimizer::RevertInterruptCode(isolate, *unoptimized);
1239
1240 *ast_id = compiler->info()->osr_ast_id();
1241
1242 InstallOptimizedCode(compiler);
1243 isolate->optimizing_compiler_thread()->RemoveStaleOSRCandidates();
1244
1245 if (!function->IsOptimized()) {
titzer 2013/09/03 14:05:36 You shouldn't check function->IsOptimized, but loo
Yang 2013/09/03 14:49:44 Done.
1246 if (FLAG_trace_osr) {
1247 PrintF("[COSR - optimization failed for ");
1248 function->PrintName();
1249 PrintF("]\n");
1250 }
1251 return false;
1252 }
1253
1254 DeoptimizationInputData* data = DeoptimizationInputData::cast(
1255 function->code()->deoptimization_data());
1256
1257 if (data->OsrPcOffset()->value() >= 0) {
1258 ASSERT(BailoutId(data->OsrAstId()->value()) == *ast_id);
1259 if (FLAG_trace_osr) {
1260 PrintF("[COSR - entry at AST id %d, offset %d in optimized code]\n",
1261 ast_id->ToInt(), data->OsrPcOffset()->value());
1262 }
1263 return true;
1264 }
1265 return false;
1266 }
1267
1268 if (!IsSuitableForOnStackReplacement(isolate, function, unoptimized)) {
1269 if (FLAG_trace_osr) {
1270 PrintF("[COSR - ");
1271 function->PrintName();
1272 PrintF(" is unsuitable, restoring interrupt calls]\n");
1273 }
1274 Deoptimizer::RevertInterruptCode(isolate, *unoptimized);
1275 return false;
1276 }
1277
1278 RecompileConcurrent(function, pc_offset);
1279 return false;
1280 }
1281
1282
1097 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, 1283 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
1098 Handle<Script> script) { 1284 Handle<Script> script) {
1099 // Precondition: code has been parsed and scopes have been analyzed. 1285 // Precondition: code has been parsed and scopes have been analyzed.
1100 CompilationInfoWithZone info(script); 1286 CompilationInfoWithZone info(script);
1101 info.SetFunction(literal); 1287 info.SetFunction(literal);
1102 info.SetScope(literal->scope()); 1288 info.SetScope(literal->scope());
1103 info.SetLanguageMode(literal->scope()->language_mode()); 1289 info.SetLanguageMode(literal->scope()->language_mode());
1104 1290
1105 Isolate* isolate = info.isolate(); 1291 Isolate* isolate = info.isolate();
1106 Factory* factory = isolate->factory(); 1292 Factory* factory = isolate->factory();
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
1256 AllowHandleDereference allow_deref; 1442 AllowHandleDereference allow_deref;
1257 bool tracing_on = info()->IsStub() 1443 bool tracing_on = info()->IsStub()
1258 ? FLAG_trace_hydrogen_stubs 1444 ? FLAG_trace_hydrogen_stubs
1259 : (FLAG_trace_hydrogen && 1445 : (FLAG_trace_hydrogen &&
1260 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); 1446 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter));
1261 return (tracing_on && 1447 return (tracing_on &&
1262 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); 1448 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL);
1263 } 1449 }
1264 1450
1265 } } // namespace v8::internal 1451 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/compiler.h ('k') | src/deoptimizer.h » ('j') | test/mjsunit/compiler/optimized-for-in.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698