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

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

Powered by Google App Engine
This is Rietveld 408576698