| 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 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 727 if (natives == NATIVES_CODE) { | 727 if (natives == NATIVES_CODE) { |
| 728 script->set_type(Smi::FromInt(Script::TYPE_NATIVE)); | 728 script->set_type(Smi::FromInt(Script::TYPE_NATIVE)); |
| 729 } | 729 } |
| 730 if (!script_name.is_null()) { | 730 if (!script_name.is_null()) { |
| 731 script->set_name(*script_name); | 731 script->set_name(*script_name); |
| 732 script->set_line_offset(Smi::FromInt(line_offset)); | 732 script->set_line_offset(Smi::FromInt(line_offset)); |
| 733 script->set_column_offset(Smi::FromInt(column_offset)); | 733 script->set_column_offset(Smi::FromInt(column_offset)); |
| 734 } | 734 } |
| 735 script->set_is_shared_cross_origin(is_shared_cross_origin); | 735 script->set_is_shared_cross_origin(is_shared_cross_origin); |
| 736 | 736 |
| 737 script->set_data(script_data.is_null() ? HEAP->undefined_value() | 737 script->set_data(script_data.is_null() ? isolate->heap()->undefined_value() |
| 738 : *script_data); | 738 : *script_data); |
| 739 | 739 |
| 740 // Compile the function and add it to the cache. | 740 // Compile the function and add it to the cache. |
| 741 CompilationInfoWithZone info(script); | 741 CompilationInfoWithZone info(script); |
| 742 info.MarkAsGlobal(); | 742 info.MarkAsGlobal(); |
| 743 info.SetExtension(extension); | 743 info.SetExtension(extension); |
| 744 info.SetPreParseData(pre_data); | 744 info.SetPreParseData(pre_data); |
| 745 info.SetContext(context); | 745 info.SetContext(context); |
| 746 if (FLAG_use_strict) { | 746 if (FLAG_use_strict) { |
| 747 info.SetLanguageMode(FLAG_harmony_scoping ? EXTENDED_MODE : STRICT_MODE); | 747 info.SetLanguageMode(FLAG_harmony_scoping ? EXTENDED_MODE : STRICT_MODE); |
| 748 } | 748 } |
| 749 result = MakeFunctionInfo(&info); | 749 result = MakeFunctionInfo(&info); |
| 750 if (extension == NULL && !result.is_null() && !result->dont_cache()) { | 750 if (extension == NULL && !result.is_null() && !result->dont_cache()) { |
| 751 compilation_cache->PutScript(source, context, result); | 751 compilation_cache->PutScript(source, context, result); |
| 752 } | 752 } |
| 753 } else { | 753 } else { |
| 754 if (result->ic_age() != HEAP->global_ic_age()) { | 754 if (result->ic_age() != isolate->heap()->global_ic_age()) { |
| 755 result->ResetForNewContext(HEAP->global_ic_age()); | 755 result->ResetForNewContext(isolate->heap()->global_ic_age()); |
| 756 } | 756 } |
| 757 } | 757 } |
| 758 | 758 |
| 759 if (result.is_null()) isolate->ReportPendingMessages(); | 759 if (result.is_null()) isolate->ReportPendingMessages(); |
| 760 return result; | 760 return result; |
| 761 } | 761 } |
| 762 | 762 |
| 763 | 763 |
| 764 Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source, | 764 Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source, |
| 765 Handle<Context> context, | 765 Handle<Context> context, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 807 // If caller is in extended mode, the result must also be in | 807 // If caller is in extended mode, the result must also be in |
| 808 // extended mode. | 808 // extended mode. |
| 809 ASSERT(language_mode != EXTENDED_MODE || | 809 ASSERT(language_mode != EXTENDED_MODE || |
| 810 result->is_extended_mode()); | 810 result->is_extended_mode()); |
| 811 if (!result->dont_cache()) { | 811 if (!result->dont_cache()) { |
| 812 compilation_cache->PutEval( | 812 compilation_cache->PutEval( |
| 813 source, context, is_global, result, scope_position); | 813 source, context, is_global, result, scope_position); |
| 814 } | 814 } |
| 815 } | 815 } |
| 816 } else { | 816 } else { |
| 817 if (result->ic_age() != HEAP->global_ic_age()) { | 817 if (result->ic_age() != isolate->heap()->global_ic_age()) { |
| 818 result->ResetForNewContext(HEAP->global_ic_age()); | 818 result->ResetForNewContext(isolate->heap()->global_ic_age()); |
| 819 } | 819 } |
| 820 } | 820 } |
| 821 | 821 |
| 822 return result; | 822 return result; |
| 823 } | 823 } |
| 824 | 824 |
| 825 | 825 |
| 826 static bool InstallFullCode(CompilationInfo* info) { | 826 static bool InstallFullCode(CompilationInfo* info) { |
| 827 // Update the shared function info with the compiled code and the | 827 // Update the shared function info with the compiled code and the |
| 828 // scope info. Please note, that the order of the shared function | 828 // scope info. Please note, that the order of the shared function |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1056 } | 1056 } |
| 1057 } | 1057 } |
| 1058 } | 1058 } |
| 1059 } | 1059 } |
| 1060 | 1060 |
| 1061 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); | 1061 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); |
| 1062 return false; | 1062 return false; |
| 1063 } | 1063 } |
| 1064 | 1064 |
| 1065 | 1065 |
| 1066 bool Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) { | 1066 Handle<Code> Compiler::InstallOptimizedCode( |
| 1067 OptimizingCompiler* optimizing_compiler) { |
| 1067 SmartPointer<CompilationInfo> info(optimizing_compiler->info()); | 1068 SmartPointer<CompilationInfo> info(optimizing_compiler->info()); |
| 1068 // The function may have already been optimized by OSR. Simply continue. | 1069 // The function may have already been optimized by OSR. Simply continue. |
| 1069 // Except when OSR already disabled optimization for some reason. | 1070 // Except when OSR already disabled optimization for some reason. |
| 1070 if (info->shared_info()->optimization_disabled()) { | 1071 if (info->shared_info()->optimization_disabled()) { |
| 1071 info->AbortOptimization(); | 1072 info->AbortOptimization(); |
| 1072 InstallFullCode(*info); | 1073 InstallFullCode(*info); |
| 1073 if (FLAG_trace_concurrent_recompilation) { | 1074 if (FLAG_trace_concurrent_recompilation) { |
| 1074 PrintF(" ** aborting optimization for "); | 1075 PrintF(" ** aborting optimization for "); |
| 1075 info->closure()->PrintName(); | 1076 info->closure()->PrintName(); |
| 1076 PrintF(" as it has been disabled.\n"); | 1077 PrintF(" as it has been disabled.\n"); |
| 1077 } | 1078 } |
| 1078 ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode()); | 1079 ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode()); |
| 1079 return false; | 1080 return Handle<Code>::null(); |
| 1080 } | 1081 } |
| 1081 | 1082 |
| 1082 Isolate* isolate = info->isolate(); | 1083 Isolate* isolate = info->isolate(); |
| 1083 VMState<COMPILER> state(isolate); | 1084 VMState<COMPILER> state(isolate); |
| 1084 Logger::TimerEventScope timer( | 1085 Logger::TimerEventScope timer( |
| 1085 isolate, Logger::TimerEventScope::v8_recompile_synchronous); | 1086 isolate, Logger::TimerEventScope::v8_recompile_synchronous); |
| 1086 // If crankshaft succeeded, install the optimized code else install | 1087 // If crankshaft succeeded, install the optimized code else install |
| 1087 // the unoptimized code. | 1088 // the unoptimized code. |
| 1088 OptimizingCompiler::Status status = optimizing_compiler->last_status(); | 1089 OptimizingCompiler::Status status = optimizing_compiler->last_status(); |
| 1089 if (info->HasAbortedDueToDependencyChange()) { | 1090 if (info->HasAbortedDueToDependencyChange()) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1116 PrintF(" installed.\n"); | 1117 PrintF(" installed.\n"); |
| 1117 } | 1118 } |
| 1118 } else { | 1119 } else { |
| 1119 info->AbortOptimization(); | 1120 info->AbortOptimization(); |
| 1120 InstallFullCode(*info); | 1121 InstallFullCode(*info); |
| 1121 } | 1122 } |
| 1122 // Optimized code is finally replacing unoptimized code. Reset the latter's | 1123 // Optimized code is finally replacing unoptimized code. Reset the latter's |
| 1123 // profiler ticks to prevent too soon re-opt after a deopt. | 1124 // profiler ticks to prevent too soon re-opt after a deopt. |
| 1124 info->shared_info()->code()->set_profiler_ticks(0); | 1125 info->shared_info()->code()->set_profiler_ticks(0); |
| 1125 ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode()); | 1126 ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode()); |
| 1126 return status == OptimizingCompiler::SUCCEEDED; | 1127 return (status == OptimizingCompiler::SUCCEEDED) ? info->code() |
| 1128 : Handle<Code>::null(); |
| 1127 } | 1129 } |
| 1128 | 1130 |
| 1129 | 1131 |
| 1130 static uint32_t CurrentPcOffset(Isolate* isolate, | |
| 1131 Handle<JSFunction> function, | |
| 1132 Handle<Code> unoptimized) { | |
| 1133 JavaScriptFrameIterator it(isolate); | |
| 1134 JavaScriptFrame* frame = it.frame(); | |
| 1135 ASSERT(frame->function() == *function); | |
| 1136 ASSERT(frame->LookupCode() == *unoptimized); | |
| 1137 ASSERT(unoptimized->contains(frame->pc())); | |
| 1138 | |
| 1139 // Use linear search of the unoptimized code's back edge table to find | |
| 1140 // the AST id matching the PC. | |
| 1141 return static_cast<uint32_t>(frame->pc() - unoptimized->instruction_start()); | |
| 1142 } | |
| 1143 | |
| 1144 | |
| 1145 static bool IsSuitableForOnStackReplacement(Isolate* isolate, | |
| 1146 Handle<JSFunction> function, | |
| 1147 Handle<Code> unoptimized) { | |
| 1148 // Keep track of whether we've succeeded in optimizing. | |
| 1149 if (!unoptimized->optimizable()) return false; | |
| 1150 // If we are trying to do OSR when there are already optimized | |
| 1151 // activations of the function, it means (a) the function is directly or | |
| 1152 // indirectly recursive and (b) an optimized invocation has been | |
| 1153 // deoptimized so that we are currently in an unoptimized activation. | |
| 1154 // Check for optimized activations of this function. | |
| 1155 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) { | |
| 1156 JavaScriptFrame* frame = it.frame(); | |
| 1157 if (frame->is_optimized() && frame->function() == *function) return false; | |
| 1158 } | |
| 1159 | |
| 1160 return true; | |
| 1161 } | |
| 1162 | |
| 1163 | |
| 1164 Handle<Code> Compiler::CompileForOnStackReplacement( | |
| 1165 Handle<JSFunction> function) { | |
| 1166 Isolate* isolate = function->GetIsolate(); | |
| 1167 Handle<Code> unoptimized(function->shared()->code(), isolate); | |
| 1168 | |
| 1169 Deoptimizer::RevertInterruptCode(isolate, *unoptimized); | |
| 1170 if (FLAG_trace_osr) { | |
| 1171 PrintF("[OSR - restored original interrupt calls in "); | |
| 1172 function->PrintName(); | |
| 1173 PrintF("]\n"); | |
| 1174 } | |
| 1175 | |
| 1176 if (IsSuitableForOnStackReplacement(isolate, function, unoptimized)) { | |
| 1177 // Find the PC offset in unoptimized code and translate to an AST id. | |
| 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 } | |
| 1186 | |
| 1187 // Attempt OSR compilation. | |
| 1188 Handle<Code> result = JSFunction::CompileOsr( | |
| 1189 function, ast_id, CLEAR_EXCEPTION); | |
| 1190 | |
| 1191 if (!result.is_null() && result->kind() == Code::OPTIMIZED_FUNCTION) { | |
| 1192 // OSR compilation succeeded. | |
| 1193 DeoptimizationInputData* data = | |
| 1194 DeoptimizationInputData::cast(result->deoptimization_data()); | |
| 1195 if (FLAG_trace_osr) { | |
| 1196 PrintF("[OSR - entry, offset %d in optimized code]\n", | |
| 1197 data->OsrPcOffset()->value()); | |
| 1198 } | |
| 1199 ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id); | |
| 1200 return result; | |
| 1201 } | |
| 1202 } | |
| 1203 | |
| 1204 if (FLAG_trace_osr) { | |
| 1205 PrintF("[OSR - attempt failed for "); | |
| 1206 function->PrintName(); | |
| 1207 PrintF("]\n"); | |
| 1208 } | |
| 1209 return Handle<Code>::null(); | |
| 1210 } | |
| 1211 | |
| 1212 | |
| 1213 Handle<Code> Compiler::CompileForConcurrentOSR(Handle<JSFunction> function) { | |
| 1214 Isolate* isolate = function->GetIsolate(); | |
| 1215 Handle<Code> unoptimized(function->shared()->code(), isolate); | |
| 1216 | |
| 1217 uint32_t pc_offset = CurrentPcOffset(isolate, function, unoptimized); | |
| 1218 | |
| 1219 if (isolate->optimizing_compiler_thread()-> | |
| 1220 IsQueuedForOSR(function, pc_offset)) { | |
| 1221 // Still waiting for the optimizing compiler thread to finish. Carry on. | |
| 1222 if (FLAG_trace_osr) { | |
| 1223 PrintF("[COSR - polling recompile tasks for "); | |
| 1224 function->PrintName(); | |
| 1225 PrintF("]\n"); | |
| 1226 } | |
| 1227 return Handle<Code>::null(); | |
| 1228 } | |
| 1229 | |
| 1230 OptimizingCompiler* compiler = isolate->optimizing_compiler_thread()-> | |
| 1231 FindReadyOSRCandidate(function, pc_offset); | |
| 1232 | |
| 1233 if (compiler != NULL) { | |
| 1234 if (FLAG_trace_osr) { | |
| 1235 PrintF("[COSR - optimization complete for "); | |
| 1236 function->PrintName(); | |
| 1237 PrintF(", restoring interrupt calls]\n"); | |
| 1238 } | |
| 1239 Deoptimizer::RevertInterruptCode(isolate, *unoptimized); | |
| 1240 | |
| 1241 // TODO(titzer): don't install the OSR code into the function. | |
| 1242 bool succeeded = InstallOptimizedCode(compiler); | |
| 1243 | |
| 1244 isolate->optimizing_compiler_thread()->RemoveStaleOSRCandidates(); | |
| 1245 | |
| 1246 if (!succeeded) { | |
| 1247 if (FLAG_trace_osr) { | |
| 1248 PrintF("[COSR - optimization failed for "); | |
| 1249 function->PrintName(); | |
| 1250 PrintF("]\n"); | |
| 1251 } | |
| 1252 return Handle<Code>::null(); | |
| 1253 } | |
| 1254 Handle<Code> result = compiler->info()->code(); | |
| 1255 | |
| 1256 // Check the result matches our expectations, and don't use it otherwise. | |
| 1257 if (result->kind() == Code::OPTIMIZED_FUNCTION) { | |
| 1258 DeoptimizationInputData* data = | |
| 1259 DeoptimizationInputData::cast(result->deoptimization_data()); | |
| 1260 | |
| 1261 if (data->OsrPcOffset()->value() >= 0) { | |
| 1262 BailoutId ast_id = compiler->info()->osr_ast_id(); | |
| 1263 ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id); | |
| 1264 if (FLAG_trace_osr) { | |
| 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; | |
| 1269 } | |
| 1270 } | |
| 1271 return Handle<Code>::null(); | |
| 1272 } | |
| 1273 | |
| 1274 if (!IsSuitableForOnStackReplacement(isolate, function, unoptimized)) { | |
| 1275 if (FLAG_trace_osr) { | |
| 1276 PrintF("[COSR - "); | |
| 1277 function->PrintName(); | |
| 1278 PrintF(" is unsuitable, restoring interrupt calls]\n"); | |
| 1279 } | |
| 1280 Deoptimizer::RevertInterruptCode(isolate, *unoptimized); | |
| 1281 return Handle<Code>::null(); | |
| 1282 } | |
| 1283 | |
| 1284 if (!RecompileConcurrent(function, pc_offset)) { | |
| 1285 Deoptimizer::RevertInterruptCode(isolate, *unoptimized); | |
| 1286 } | |
| 1287 return Handle<Code>::null(); | |
| 1288 } | |
| 1289 | |
| 1290 | |
| 1291 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, | 1132 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, |
| 1292 Handle<Script> script) { | 1133 Handle<Script> script) { |
| 1293 // Precondition: code has been parsed and scopes have been analyzed. | 1134 // Precondition: code has been parsed and scopes have been analyzed. |
| 1294 CompilationInfoWithZone info(script); | 1135 CompilationInfoWithZone info(script); |
| 1295 info.SetFunction(literal); | 1136 info.SetFunction(literal); |
| 1296 info.SetScope(literal->scope()); | 1137 info.SetScope(literal->scope()); |
| 1297 info.SetLanguageMode(literal->scope()->language_mode()); | 1138 info.SetLanguageMode(literal->scope()->language_mode()); |
| 1298 | 1139 |
| 1299 Isolate* isolate = info.isolate(); | 1140 Isolate* isolate = info.isolate(); |
| 1300 Factory* factory = isolate->factory(); | 1141 Factory* factory = isolate->factory(); |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1450 AllowHandleDereference allow_deref; | 1291 AllowHandleDereference allow_deref; |
| 1451 bool tracing_on = info()->IsStub() | 1292 bool tracing_on = info()->IsStub() |
| 1452 ? FLAG_trace_hydrogen_stubs | 1293 ? FLAG_trace_hydrogen_stubs |
| 1453 : (FLAG_trace_hydrogen && | 1294 : (FLAG_trace_hydrogen && |
| 1454 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); | 1295 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); |
| 1455 return (tracing_on && | 1296 return (tracing_on && |
| 1456 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); | 1297 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); |
| 1457 } | 1298 } |
| 1458 | 1299 |
| 1459 } } // namespace v8::internal | 1300 } } // namespace v8::internal |
| OLD | NEW |