| 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 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 // The encoding is as a signed value, with parameters and receiver using | 360 // The encoding is as a signed value, with parameters and receiver using |
| 361 // the negative indices and locals the non-negative ones. | 361 // the negative indices and locals the non-negative ones. |
| 362 const int parameter_limit = -LUnallocated::kMinFixedSlotIndex; | 362 const int parameter_limit = -LUnallocated::kMinFixedSlotIndex; |
| 363 Scope* scope = info()->scope(); | 363 Scope* scope = info()->scope(); |
| 364 if ((scope->num_parameters() + 1) > parameter_limit) { | 364 if ((scope->num_parameters() + 1) > parameter_limit) { |
| 365 info()->set_bailout_reason(kTooManyParameters); | 365 info()->set_bailout_reason(kTooManyParameters); |
| 366 return AbortOptimization(); | 366 return AbortOptimization(); |
| 367 } | 367 } |
| 368 | 368 |
| 369 const int locals_limit = LUnallocated::kMaxFixedSlotIndex; | 369 const int locals_limit = LUnallocated::kMaxFixedSlotIndex; |
| 370 if (!info()->osr_ast_id().IsNone() && | 370 if (info()->is_osr() && |
| 371 scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit) { | 371 scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit) { |
| 372 info()->set_bailout_reason(kTooManyParametersLocals); | 372 info()->set_bailout_reason(kTooManyParametersLocals); |
| 373 return AbortOptimization(); | 373 return AbortOptimization(); |
| 374 } | 374 } |
| 375 | 375 |
| 376 // Take --hydrogen-filter into account. | 376 // Take --hydrogen-filter into account. |
| 377 if (!info()->closure()->PassesFilter(FLAG_hydrogen_filter)) { | 377 if (!info()->closure()->PassesFilter(FLAG_hydrogen_filter)) { |
| 378 info()->AbortOptimization(); | 378 info()->AbortOptimization(); |
| 379 return SetLastStatus(BAILED_OUT); | 379 return SetLastStatus(BAILED_OUT); |
| 380 } | 380 } |
| (...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 886 } | 886 } |
| 887 Compiler::RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared); | 887 Compiler::RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared); |
| 888 } | 888 } |
| 889 | 889 |
| 890 | 890 |
| 891 static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) { | 891 static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) { |
| 892 Handle<Code> code = info->code(); | 892 Handle<Code> code = info->code(); |
| 893 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do. | 893 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do. |
| 894 | 894 |
| 895 // Cache non-OSR optimized code. | 895 // Cache non-OSR optimized code. |
| 896 if (FLAG_cache_optimized_code && info->osr_ast_id().IsNone()) { | 896 if (FLAG_cache_optimized_code && !info->is_osr()) { |
| 897 Handle<JSFunction> function = info->closure(); | 897 Handle<JSFunction> function = info->closure(); |
| 898 Handle<SharedFunctionInfo> shared(function->shared()); | 898 Handle<SharedFunctionInfo> shared(function->shared()); |
| 899 Handle<FixedArray> literals(function->literals()); | 899 Handle<FixedArray> literals(function->literals()); |
| 900 Handle<Context> native_context(function->context()->native_context()); | 900 Handle<Context> native_context(function->context()->native_context()); |
| 901 SharedFunctionInfo::AddToOptimizedCodeMap( | 901 SharedFunctionInfo::AddToOptimizedCodeMap( |
| 902 shared, native_context, code, literals); | 902 shared, native_context, code, literals); |
| 903 } | 903 } |
| 904 } | 904 } |
| 905 | 905 |
| 906 | 906 |
| 907 static bool InstallCodeFromOptimizedCodeMap(CompilationInfo* info) { | 907 static bool InstallCodeFromOptimizedCodeMap(CompilationInfo* info) { |
| 908 if (!info->IsOptimizing()) return false; // Nothing to look up. | 908 if (!info->IsOptimizing()) return false; // Nothing to look up. |
| 909 | 909 |
| 910 // Lookup non-OSR optimized code. | 910 // Lookup non-OSR optimized code. |
| 911 if (FLAG_cache_optimized_code && info->osr_ast_id().IsNone()) { | 911 if (FLAG_cache_optimized_code && !info->is_osr()) { |
| 912 Handle<SharedFunctionInfo> shared = info->shared_info(); | 912 Handle<SharedFunctionInfo> shared = info->shared_info(); |
| 913 Handle<JSFunction> function = info->closure(); | 913 Handle<JSFunction> function = info->closure(); |
| 914 ASSERT(!function.is_null()); | 914 ASSERT(!function.is_null()); |
| 915 Handle<Context> native_context(function->context()->native_context()); | 915 Handle<Context> native_context(function->context()->native_context()); |
| 916 int index = shared->SearchOptimizedCodeMap(*native_context); | 916 int index = shared->SearchOptimizedCodeMap(*native_context); |
| 917 if (index > 0) { | 917 if (index > 0) { |
| 918 if (FLAG_trace_opt) { | 918 if (FLAG_trace_opt) { |
| 919 PrintF("[found optimized code for "); | 919 PrintF("[found optimized code for "); |
| 920 function->ShortPrint(); | 920 function->ShortPrint(); |
| 921 PrintF("]\n"); | 921 PrintF("]\n"); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 957 | 957 |
| 958 // Compile the code. | 958 // Compile the code. |
| 959 if (!MakeCode(info)) { | 959 if (!MakeCode(info)) { |
| 960 if (!isolate->has_pending_exception()) { | 960 if (!isolate->has_pending_exception()) { |
| 961 isolate->StackOverflow(); | 961 isolate->StackOverflow(); |
| 962 } | 962 } |
| 963 } else { | 963 } else { |
| 964 InstallCodeCommon(info); | 964 InstallCodeCommon(info); |
| 965 | 965 |
| 966 if (info->IsOptimizing()) { | 966 if (info->IsOptimizing()) { |
| 967 // Optimized code successfully created. |
| 967 Handle<Code> code = info->code(); | 968 Handle<Code> code = info->code(); |
| 968 ASSERT(shared->scope_info() != ScopeInfo::Empty(isolate)); | 969 ASSERT(shared->scope_info() != ScopeInfo::Empty(isolate)); |
| 970 // TODO(titzer): Only replace the code if it was not an OSR compile. |
| 969 info->closure()->ReplaceCode(*code); | 971 info->closure()->ReplaceCode(*code); |
| 970 InsertCodeIntoOptimizedCodeMap(info); | 972 InsertCodeIntoOptimizedCodeMap(info); |
| 971 return true; | 973 return true; |
| 972 } else { | 974 } else if (!info->is_osr()) { |
| 975 // Compilation failed. Replace with full code if not OSR compile. |
| 973 return InstallFullCode(info); | 976 return InstallFullCode(info); |
| 974 } | 977 } |
| 975 } | 978 } |
| 976 } | 979 } |
| 977 | 980 |
| 978 ASSERT(info->code().is_null()); | 981 ASSERT(info->code().is_null()); |
| 979 return false; | 982 return false; |
| 980 } | 983 } |
| 981 | 984 |
| 982 | 985 |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1151 // Check for optimized activations of this function. | 1154 // Check for optimized activations of this function. |
| 1152 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) { | 1155 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) { |
| 1153 JavaScriptFrame* frame = it.frame(); | 1156 JavaScriptFrame* frame = it.frame(); |
| 1154 if (frame->is_optimized() && frame->function() == *function) return false; | 1157 if (frame->is_optimized() && frame->function() == *function) return false; |
| 1155 } | 1158 } |
| 1156 | 1159 |
| 1157 return true; | 1160 return true; |
| 1158 } | 1161 } |
| 1159 | 1162 |
| 1160 | 1163 |
| 1161 BailoutId Compiler::CompileForOnStackReplacement(Handle<JSFunction> function) { | 1164 Handle<Code> Compiler::CompileForOnStackReplacement( |
| 1165 Handle<JSFunction> function) { |
| 1162 Isolate* isolate = function->GetIsolate(); | 1166 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); | 1167 Handle<Code> unoptimized(function->shared()->code(), isolate); |
| 1166 | 1168 |
| 1167 Deoptimizer::RevertInterruptCode(isolate, *unoptimized); | 1169 Deoptimizer::RevertInterruptCode(isolate, *unoptimized); |
| 1168 if (FLAG_trace_osr) { | 1170 if (FLAG_trace_osr) { |
| 1169 PrintF("[OSR - restored original interrupt calls in "); | 1171 PrintF("[OSR - restored original interrupt calls in "); |
| 1170 function->PrintName(); | 1172 function->PrintName(); |
| 1171 PrintF("]\n"); | 1173 PrintF("]\n"); |
| 1172 } | 1174 } |
| 1173 | 1175 |
| 1174 if (!IsSuitableForOnStackReplacement(isolate, function, unoptimized)) { | 1176 if (IsSuitableForOnStackReplacement(isolate, function, unoptimized)) { |
| 1175 return BailoutId::None(); | 1177 // Find the PC offset in unoptimized code and translate to an AST id. |
| 1176 } | 1178 uint32_t pc_offset = CurrentPcOffset(isolate, function, unoptimized); |
| 1179 BailoutId ast_id = unoptimized->TranslatePcOffsetToAstId(pc_offset); |
| 1180 ASSERT(!ast_id.IsNone()); |
| 1181 if (FLAG_trace_osr) { |
| 1182 PrintF("[OSR - replacing at AST id %d in ", ast_id.ToInt()); |
| 1183 function->PrintName(); |
| 1184 PrintF("]\n"); |
| 1185 } |
| 1177 | 1186 |
| 1178 uint32_t pc_offset = CurrentPcOffset(isolate, function, unoptimized); | 1187 // Attempt OSR compilation. |
| 1188 Handle<Code> result = JSFunction::CompileOsr( |
| 1189 function, ast_id, CLEAR_EXCEPTION); |
| 1179 | 1190 |
| 1180 BailoutId ast_id = unoptimized->TranslatePcOffsetToAstId(pc_offset); | 1191 if (!result.is_null() && result->kind() == Code::OPTIMIZED_FUNCTION) { |
| 1181 ASSERT(!ast_id.IsNone()); | 1192 // OSR compilation succeeded. |
| 1182 if (FLAG_trace_osr) { | 1193 DeoptimizationInputData* data = |
| 1183 PrintF("[OSR - replacing at AST id %d in ", ast_id.ToInt()); | 1194 DeoptimizationInputData::cast(result->deoptimization_data()); |
| 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) { | 1195 if (FLAG_trace_osr) { |
| 1197 PrintF("[OSR - entry, offset %d in optimized code]\n", | 1196 PrintF("[OSR - entry, offset %d in optimized code]\n", |
| 1198 data->OsrPcOffset()->value()); | 1197 data->OsrPcOffset()->value()); |
| 1199 } | 1198 } |
| 1200 ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id); | 1199 ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id); |
| 1201 return ast_id; | 1200 return result; |
| 1202 } | |
| 1203 } else { | |
| 1204 if (FLAG_trace_osr) { | |
| 1205 PrintF("[OSR - optimization failed for "); | |
| 1206 function->PrintName(); | |
| 1207 PrintF("]\n"); | |
| 1208 } | 1201 } |
| 1209 } | 1202 } |
| 1210 return BailoutId::None(); | 1203 |
| 1204 if (FLAG_trace_osr) { |
| 1205 PrintF("[OSR - attempt failed for "); |
| 1206 function->PrintName(); |
| 1207 PrintF("]\n"); |
| 1208 } |
| 1209 return Handle<Code>::null(); |
| 1211 } | 1210 } |
| 1212 | 1211 |
| 1213 | 1212 |
| 1214 BailoutId Compiler::CompileForConcurrentOSR(Handle<JSFunction> function) { | 1213 Handle<Code> Compiler::CompileForConcurrentOSR(Handle<JSFunction> function) { |
| 1215 Isolate* isolate = function->GetIsolate(); | 1214 Isolate* isolate = function->GetIsolate(); |
| 1216 Handle<Code> unoptimized(function->shared()->code(), isolate); | 1215 Handle<Code> unoptimized(function->shared()->code(), isolate); |
| 1217 | 1216 |
| 1218 uint32_t pc_offset = CurrentPcOffset(isolate, function, unoptimized); | 1217 uint32_t pc_offset = CurrentPcOffset(isolate, function, unoptimized); |
| 1219 | 1218 |
| 1220 if (isolate->optimizing_compiler_thread()-> | 1219 if (isolate->optimizing_compiler_thread()-> |
| 1221 IsQueuedForOSR(function, pc_offset)) { | 1220 IsQueuedForOSR(function, pc_offset)) { |
| 1222 // Still waiting for the optimizing compiler thread to finish. Carry on. | 1221 // Still waiting for the optimizing compiler thread to finish. Carry on. |
| 1223 if (FLAG_trace_osr) { | 1222 if (FLAG_trace_osr) { |
| 1224 PrintF("[COSR - polling recompile tasks for "); | 1223 PrintF("[COSR - polling recompile tasks for "); |
| 1225 function->PrintName(); | 1224 function->PrintName(); |
| 1226 PrintF("]\n"); | 1225 PrintF("]\n"); |
| 1227 } | 1226 } |
| 1228 return BailoutId::None(); | 1227 return Handle<Code>::null(); |
| 1229 } | 1228 } |
| 1230 | 1229 |
| 1231 OptimizingCompiler* compiler = isolate->optimizing_compiler_thread()-> | 1230 OptimizingCompiler* compiler = isolate->optimizing_compiler_thread()-> |
| 1232 FindReadyOSRCandidate(function, pc_offset); | 1231 FindReadyOSRCandidate(function, pc_offset); |
| 1233 | 1232 |
| 1234 if (compiler != NULL) { | 1233 if (compiler != NULL) { |
| 1235 if (FLAG_trace_osr) { | 1234 if (FLAG_trace_osr) { |
| 1236 PrintF("[COSR - optimization complete for "); | 1235 PrintF("[COSR - optimization complete for "); |
| 1237 function->PrintName(); | 1236 function->PrintName(); |
| 1238 PrintF(", restoring interrupt calls]\n"); | 1237 PrintF(", restoring interrupt calls]\n"); |
| 1239 } | 1238 } |
| 1240 Deoptimizer::RevertInterruptCode(isolate, *unoptimized); | 1239 Deoptimizer::RevertInterruptCode(isolate, *unoptimized); |
| 1241 | 1240 |
| 1242 BailoutId ast_id = compiler->info()->osr_ast_id(); | 1241 // TODO(titzer): don't install the OSR code into the function. |
| 1243 | |
| 1244 bool succeeded = InstallOptimizedCode(compiler); | 1242 bool succeeded = InstallOptimizedCode(compiler); |
| 1245 | 1243 |
| 1246 isolate->optimizing_compiler_thread()->RemoveStaleOSRCandidates(); | 1244 isolate->optimizing_compiler_thread()->RemoveStaleOSRCandidates(); |
| 1247 | 1245 |
| 1248 if (!succeeded) { | 1246 if (!succeeded) { |
| 1249 if (FLAG_trace_osr) { | 1247 if (FLAG_trace_osr) { |
| 1250 PrintF("[COSR - optimization failed for "); | 1248 PrintF("[COSR - optimization failed for "); |
| 1251 function->PrintName(); | 1249 function->PrintName(); |
| 1252 PrintF("]\n"); | 1250 PrintF("]\n"); |
| 1253 } | 1251 } |
| 1254 return BailoutId::None(); | 1252 return Handle<Code>::null(); |
| 1255 } | 1253 } |
| 1254 Handle<Code> result = compiler->info()->code(); |
| 1256 | 1255 |
| 1257 DeoptimizationInputData* data = DeoptimizationInputData::cast( | 1256 // Check the result matches our expectations, and don't use it otherwise. |
| 1258 function->code()->deoptimization_data()); | 1257 if (result->kind() == Code::OPTIMIZED_FUNCTION) { |
| 1258 DeoptimizationInputData* data = |
| 1259 DeoptimizationInputData::cast(result->deoptimization_data()); |
| 1259 | 1260 |
| 1260 if (data->OsrPcOffset()->value() >= 0) { | 1261 if (data->OsrPcOffset()->value() >= 0) { |
| 1261 ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id); | 1262 BailoutId ast_id = compiler->info()->osr_ast_id(); |
| 1262 if (FLAG_trace_osr) { | 1263 ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id); |
| 1263 PrintF("[COSR - entry at AST id %d, offset %d in optimized code]\n", | 1264 if (FLAG_trace_osr) { |
| 1264 ast_id.ToInt(), data->OsrPcOffset()->value()); | 1265 PrintF("[COSR - entry at AST id %d, offset %d in optimized code]\n", |
| 1266 ast_id.ToInt(), data->OsrPcOffset()->value()); |
| 1267 } |
| 1268 return result; |
| 1265 } | 1269 } |
| 1266 return ast_id; | |
| 1267 } | 1270 } |
| 1268 return BailoutId::None(); | 1271 return Handle<Code>::null(); |
| 1269 } | 1272 } |
| 1270 | 1273 |
| 1271 if (!IsSuitableForOnStackReplacement(isolate, function, unoptimized)) { | 1274 if (!IsSuitableForOnStackReplacement(isolate, function, unoptimized)) { |
| 1272 if (FLAG_trace_osr) { | 1275 if (FLAG_trace_osr) { |
| 1273 PrintF("[COSR - "); | 1276 PrintF("[COSR - "); |
| 1274 function->PrintName(); | 1277 function->PrintName(); |
| 1275 PrintF(" is unsuitable, restoring interrupt calls]\n"); | 1278 PrintF(" is unsuitable, restoring interrupt calls]\n"); |
| 1276 } | 1279 } |
| 1277 Deoptimizer::RevertInterruptCode(isolate, *unoptimized); | 1280 Deoptimizer::RevertInterruptCode(isolate, *unoptimized); |
| 1278 return BailoutId::None(); | 1281 return Handle<Code>::null(); |
| 1279 } | 1282 } |
| 1280 | 1283 |
| 1281 if (!RecompileConcurrent(function, pc_offset)) { | 1284 if (!RecompileConcurrent(function, pc_offset)) { |
| 1282 Deoptimizer::RevertInterruptCode(isolate, *unoptimized); | 1285 Deoptimizer::RevertInterruptCode(isolate, *unoptimized); |
| 1283 } | 1286 } |
| 1284 return BailoutId::None(); | 1287 return Handle<Code>::null(); |
| 1285 } | 1288 } |
| 1286 | 1289 |
| 1287 | 1290 |
| 1288 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, | 1291 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, |
| 1289 Handle<Script> script) { | 1292 Handle<Script> script) { |
| 1290 // Precondition: code has been parsed and scopes have been analyzed. | 1293 // Precondition: code has been parsed and scopes have been analyzed. |
| 1291 CompilationInfoWithZone info(script); | 1294 CompilationInfoWithZone info(script); |
| 1292 info.SetFunction(literal); | 1295 info.SetFunction(literal); |
| 1293 info.SetScope(literal->scope()); | 1296 info.SetScope(literal->scope()); |
| 1294 info.SetLanguageMode(literal->scope()->language_mode()); | 1297 info.SetLanguageMode(literal->scope()->language_mode()); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1447 AllowHandleDereference allow_deref; | 1450 AllowHandleDereference allow_deref; |
| 1448 bool tracing_on = info()->IsStub() | 1451 bool tracing_on = info()->IsStub() |
| 1449 ? FLAG_trace_hydrogen_stubs | 1452 ? FLAG_trace_hydrogen_stubs |
| 1450 : (FLAG_trace_hydrogen && | 1453 : (FLAG_trace_hydrogen && |
| 1451 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); | 1454 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); |
| 1452 return (tracing_on && | 1455 return (tracing_on && |
| 1453 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); | 1456 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); |
| 1454 } | 1457 } |
| 1455 | 1458 |
| 1456 } } // namespace v8::internal | 1459 } } // namespace v8::internal |
| OLD | NEW |