OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler.h" | 5 #include "src/compiler.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "src/ast-numbering.h" | 9 #include "src/ast-numbering.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 : CompilationInfo(parse_info, nullptr, BASE, parse_info->isolate(), | 105 : CompilationInfo(parse_info, nullptr, BASE, parse_info->isolate(), |
106 parse_info->zone()) { | 106 parse_info->zone()) { |
107 // Compiling for the snapshot typically results in different code than | 107 // Compiling for the snapshot typically results in different code than |
108 // compiling later on. This means that code recompiled with deoptimization | 108 // compiling later on. This means that code recompiled with deoptimization |
109 // support won't be "equivalent" (as defined by SharedFunctionInfo:: | 109 // support won't be "equivalent" (as defined by SharedFunctionInfo:: |
110 // EnableDeoptimizationSupport), so it will replace the old code and all | 110 // EnableDeoptimizationSupport), so it will replace the old code and all |
111 // its type feedback. To avoid this, always compile functions in the snapshot | 111 // its type feedback. To avoid this, always compile functions in the snapshot |
112 // with deoptimization support. | 112 // with deoptimization support. |
113 if (isolate_->serializer_enabled()) EnableDeoptimizationSupport(); | 113 if (isolate_->serializer_enabled()) EnableDeoptimizationSupport(); |
114 | 114 |
115 if (isolate_->debug()->is_active()) MarkAsDebug(); | |
116 if (FLAG_context_specialization) MarkAsContextSpecializing(); | 115 if (FLAG_context_specialization) MarkAsContextSpecializing(); |
117 if (FLAG_turbo_inlining) MarkAsInliningEnabled(); | 116 if (FLAG_turbo_inlining) MarkAsInliningEnabled(); |
118 if (FLAG_turbo_source_positions) MarkAsSourcePositionsEnabled(); | 117 if (FLAG_turbo_source_positions) MarkAsSourcePositionsEnabled(); |
119 if (FLAG_turbo_splitting) MarkAsSplittingEnabled(); | 118 if (FLAG_turbo_splitting) MarkAsSplittingEnabled(); |
120 if (FLAG_turbo_types) MarkAsTypingEnabled(); | 119 if (FLAG_turbo_types) MarkAsTypingEnabled(); |
121 | 120 |
122 if (has_shared_info()) { | 121 if (has_shared_info()) { |
123 if (shared_info()->is_compiled()) { | 122 if (shared_info()->is_compiled()) { |
124 // We should initialize the CompilationInfo feedback vector from the | 123 // We should initialize the CompilationInfo feedback vector from the |
125 // passed in shared info, rather than creating a new one. | 124 // passed in shared info, rather than creating a new one. |
(...skipping 833 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 shared->set_scope_info(*target_scope_info); | 958 shared->set_scope_info(*target_scope_info); |
960 } | 959 } |
961 | 960 |
962 // The existing unoptimized code was replaced with the new one. | 961 // The existing unoptimized code was replaced with the new one. |
963 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized, shared); | 962 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized, shared); |
964 } | 963 } |
965 return true; | 964 return true; |
966 } | 965 } |
967 | 966 |
968 | 967 |
969 MaybeHandle<Code> CompileForDebugging(CompilationInfo* info) { | 968 bool CompileEvalForDebugging(Handle<JSFunction> function, |
970 info->MarkAsDebug(); | 969 Handle<SharedFunctionInfo> shared) { |
971 VMState<COMPILER> state(info->isolate()); | 970 Handle<Script> script(Script::cast(shared->script())); |
972 MaybeHandle<Code> maybe_new_code = GetUnoptimizedCodeCommon(info); | 971 Handle<Context> context(function->context()); |
973 Handle<Code> new_code; | 972 |
974 if (!maybe_new_code.ToHandle(&new_code)) { | 973 Zone zone; |
975 info->isolate()->clear_pending_exception(); | 974 ParseInfo parse_info(&zone, script); |
| 975 CompilationInfo info(&parse_info); |
| 976 Isolate* isolate = info.isolate(); |
| 977 |
| 978 parse_info.set_eval(); |
| 979 parse_info.set_context(context); |
| 980 if (context->IsNativeContext()) parse_info.set_global(); |
| 981 parse_info.set_toplevel(); |
| 982 parse_info.set_allow_lazy_parsing(false); |
| 983 parse_info.set_language_mode(shared->language_mode()); |
| 984 parse_info.set_parse_restriction(NO_PARSE_RESTRICTION); |
| 985 info.MarkAsDebug(); |
| 986 |
| 987 VMState<COMPILER> state(info.isolate()); |
| 988 |
| 989 if (!Parser::ParseStatic(&parse_info)) { |
| 990 isolate->clear_pending_exception(); |
| 991 return false; |
976 } | 992 } |
977 return maybe_new_code; | 993 |
| 994 FunctionLiteral* lit = info.function(); |
| 995 LiveEditFunctionTracker live_edit_tracker(isolate, lit); |
| 996 |
| 997 if (!CompileUnoptimizedCode(&info)) { |
| 998 isolate->clear_pending_exception(); |
| 999 return false; |
| 1000 } |
| 1001 shared->ReplaceCode(*info.code()); |
| 1002 return true; |
978 } | 1003 } |
979 | 1004 |
980 | 1005 |
981 MaybeHandle<Code> Compiler::GetDebugCode(Handle<JSFunction> function) { | 1006 bool CompileForDebugging(CompilationInfo* info) { |
982 CompilationInfoWithZone info(function); | 1007 info->MarkAsDebug(); |
983 VMState<COMPILER> state(info.isolate()); | 1008 if (GetUnoptimizedCodeCommon(info).is_null()) { |
984 return CompileForDebugging(&info); | 1009 info->isolate()->clear_pending_exception(); |
| 1010 return false; |
| 1011 } |
| 1012 return true; |
985 } | 1013 } |
986 | 1014 |
987 | 1015 |
988 MaybeHandle<Code> Compiler::GetDebugCode(Handle<SharedFunctionInfo> shared) { | 1016 bool Compiler::CompileDebugCode(Handle<JSFunction> function) { |
| 1017 Handle<SharedFunctionInfo> shared(function->shared()); |
| 1018 if (shared->is_toplevel() && shared->script()->IsScript() && |
| 1019 Script::cast(shared->script())->compilation_type() == |
| 1020 Script::COMPILATION_TYPE_EVAL) { |
| 1021 return CompileEvalForDebugging(function, shared); |
| 1022 } else { |
| 1023 CompilationInfoWithZone info(function); |
| 1024 return CompileForDebugging(&info); |
| 1025 } |
| 1026 } |
| 1027 |
| 1028 |
| 1029 bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) { |
989 DCHECK(shared->allows_lazy_compilation_without_context()); | 1030 DCHECK(shared->allows_lazy_compilation_without_context()); |
990 Zone zone; | 1031 Zone zone; |
991 ParseInfo parse_info(&zone, shared); | 1032 ParseInfo parse_info(&zone, shared); |
992 CompilationInfo info(&parse_info); | 1033 CompilationInfo info(&parse_info); |
993 return CompileForDebugging(&info); | 1034 return CompileForDebugging(&info); |
994 } | 1035 } |
995 | 1036 |
996 | 1037 |
997 void Compiler::CompileForLiveEdit(Handle<Script> script) { | 1038 void Compiler::CompileForLiveEdit(Handle<Script> script) { |
998 // TODO(635): support extensions. | 1039 // TODO(635): support extensions. |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1113 // the instances of the function. | 1154 // the instances of the function. |
1114 SetExpectedNofPropertiesFromEstimate(result, | 1155 SetExpectedNofPropertiesFromEstimate(result, |
1115 lit->expected_property_count()); | 1156 lit->expected_property_count()); |
1116 | 1157 |
1117 if (!script.is_null()) | 1158 if (!script.is_null()) |
1118 script->set_compilation_state(Script::COMPILATION_STATE_COMPILED); | 1159 script->set_compilation_state(Script::COMPILATION_STATE_COMPILED); |
1119 | 1160 |
1120 live_edit_tracker.RecordFunctionInfo(result, lit, info->zone()); | 1161 live_edit_tracker.RecordFunctionInfo(result, lit, info->zone()); |
1121 } | 1162 } |
1122 | 1163 |
1123 isolate->debug()->OnAfterCompile(script); | |
1124 | |
1125 return result; | 1164 return result; |
1126 } | 1165 } |
1127 | 1166 |
1128 | 1167 |
1129 MaybeHandle<JSFunction> Compiler::GetFunctionFromEval( | 1168 MaybeHandle<JSFunction> Compiler::GetFunctionFromEval( |
1130 Handle<String> source, Handle<SharedFunctionInfo> outer_info, | 1169 Handle<String> source, Handle<SharedFunctionInfo> outer_info, |
1131 Handle<Context> context, LanguageMode language_mode, | 1170 Handle<Context> context, LanguageMode language_mode, |
1132 ParseRestriction restriction, int line_offset, int column_offset, | 1171 ParseRestriction restriction, int line_offset, int column_offset, |
1133 Handle<Object> script_name, ScriptOriginOptions options) { | 1172 Handle<Object> script_name, ScriptOriginOptions options) { |
1134 Isolate* isolate = source->GetIsolate(); | 1173 Isolate* isolate = source->GetIsolate(); |
1135 int source_length = source->length(); | 1174 int source_length = source->length(); |
1136 isolate->counters()->total_eval_size()->Increment(source_length); | 1175 isolate->counters()->total_eval_size()->Increment(source_length); |
1137 isolate->counters()->total_compile_size()->Increment(source_length); | 1176 isolate->counters()->total_compile_size()->Increment(source_length); |
1138 | 1177 |
1139 CompilationCache* compilation_cache = isolate->compilation_cache(); | 1178 CompilationCache* compilation_cache = isolate->compilation_cache(); |
1140 MaybeHandle<SharedFunctionInfo> maybe_shared_info = | 1179 MaybeHandle<SharedFunctionInfo> maybe_shared_info = |
1141 compilation_cache->LookupEval(source, outer_info, context, language_mode, | 1180 compilation_cache->LookupEval(source, outer_info, context, language_mode, |
1142 line_offset); | 1181 line_offset); |
1143 Handle<SharedFunctionInfo> shared_info; | 1182 Handle<SharedFunctionInfo> shared_info; |
1144 | 1183 |
| 1184 Handle<Script> script; |
1145 if (!maybe_shared_info.ToHandle(&shared_info)) { | 1185 if (!maybe_shared_info.ToHandle(&shared_info)) { |
1146 Handle<Script> script = isolate->factory()->NewScript(source); | 1186 script = isolate->factory()->NewScript(source); |
1147 if (!script_name.is_null()) { | 1187 if (!script_name.is_null()) { |
1148 script->set_name(*script_name); | 1188 script->set_name(*script_name); |
1149 script->set_line_offset(Smi::FromInt(line_offset)); | 1189 script->set_line_offset(Smi::FromInt(line_offset)); |
1150 script->set_column_offset(Smi::FromInt(column_offset)); | 1190 script->set_column_offset(Smi::FromInt(column_offset)); |
1151 } | 1191 } |
1152 script->set_origin_options(options); | 1192 script->set_origin_options(options); |
1153 Zone zone; | 1193 Zone zone; |
1154 ParseInfo parse_info(&zone, script); | 1194 ParseInfo parse_info(&zone, script); |
1155 CompilationInfo info(&parse_info); | 1195 CompilationInfo info(&parse_info); |
1156 parse_info.set_eval(); | 1196 parse_info.set_eval(); |
1157 if (context->IsNativeContext()) parse_info.set_global(); | 1197 if (context->IsNativeContext()) parse_info.set_global(); |
1158 parse_info.set_language_mode(language_mode); | 1198 parse_info.set_language_mode(language_mode); |
1159 parse_info.set_parse_restriction(restriction); | 1199 parse_info.set_parse_restriction(restriction); |
1160 parse_info.set_context(context); | 1200 parse_info.set_context(context); |
1161 | 1201 |
1162 // If we eval from debug code, compile for debugging as well. | |
1163 if (outer_info->HasDebugCode()) info.MarkAsDebug(); | |
1164 Debug::RecordEvalCaller(script); | 1202 Debug::RecordEvalCaller(script); |
1165 | 1203 |
1166 shared_info = CompileToplevel(&info); | 1204 shared_info = CompileToplevel(&info); |
1167 | 1205 |
1168 if (shared_info.is_null()) { | 1206 if (shared_info.is_null()) { |
1169 return MaybeHandle<JSFunction>(); | 1207 return MaybeHandle<JSFunction>(); |
1170 } else { | 1208 } else { |
1171 // Explicitly disable optimization for eval code. We're not yet prepared | 1209 // Explicitly disable optimization for eval code. We're not yet prepared |
1172 // to handle eval-code in the optimizing compiler. | 1210 // to handle eval-code in the optimizing compiler. |
1173 if (restriction != ONLY_SINGLE_FUNCTION_LITERAL) { | 1211 if (restriction != ONLY_SINGLE_FUNCTION_LITERAL) { |
1174 shared_info->DisableOptimization(kEval); | 1212 shared_info->DisableOptimization(kEval); |
1175 } | 1213 } |
1176 | 1214 |
1177 // If caller is strict mode, the result must be in strict mode as well. | 1215 // If caller is strict mode, the result must be in strict mode as well. |
1178 DCHECK(is_sloppy(language_mode) || | 1216 DCHECK(is_sloppy(language_mode) || |
1179 is_strict(shared_info->language_mode())); | 1217 is_strict(shared_info->language_mode())); |
1180 compilation_cache->PutEval(source, outer_info, context, shared_info, | 1218 compilation_cache->PutEval(source, outer_info, context, shared_info, |
1181 line_offset); | 1219 line_offset); |
1182 } | 1220 } |
1183 } else if (shared_info->ic_age() != isolate->heap()->global_ic_age()) { | 1221 } else if (shared_info->ic_age() != isolate->heap()->global_ic_age()) { |
1184 shared_info->ResetForNewContext(isolate->heap()->global_ic_age()); | 1222 shared_info->ResetForNewContext(isolate->heap()->global_ic_age()); |
1185 } | 1223 } |
1186 | 1224 |
1187 return isolate->factory()->NewFunctionFromSharedFunctionInfo( | 1225 Handle<JSFunction> result = |
1188 shared_info, context, NOT_TENURED); | 1226 isolate->factory()->NewFunctionFromSharedFunctionInfo( |
| 1227 shared_info, context, NOT_TENURED); |
| 1228 |
| 1229 // OnAfterCompile has to be called after we create the JSFunction, which we |
| 1230 // may require to recompile the eval for debugging, if we find a function |
| 1231 // that contains break points in the eval script. |
| 1232 isolate->debug()->OnAfterCompile(script); |
| 1233 |
| 1234 return result; |
1189 } | 1235 } |
1190 | 1236 |
1191 | 1237 |
1192 Handle<SharedFunctionInfo> Compiler::CompileScript( | 1238 Handle<SharedFunctionInfo> Compiler::CompileScript( |
1193 Handle<String> source, Handle<Object> script_name, int line_offset, | 1239 Handle<String> source, Handle<Object> script_name, int line_offset, |
1194 int column_offset, ScriptOriginOptions resource_options, | 1240 int column_offset, ScriptOriginOptions resource_options, |
1195 Handle<Object> source_map_url, Handle<Context> context, | 1241 Handle<Object> source_map_url, Handle<Context> context, |
1196 v8::Extension* extension, ScriptData** cached_data, | 1242 v8::Extension* extension, ScriptData** cached_data, |
1197 ScriptCompiler::CompileOptions compile_options, NativesFlag natives, | 1243 ScriptCompiler::CompileOptions compile_options, NativesFlag natives, |
1198 bool is_module) { | 1244 bool is_module) { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1300 HistogramTimerScope histogram_timer( | 1346 HistogramTimerScope histogram_timer( |
1301 isolate->counters()->compile_serialize()); | 1347 isolate->counters()->compile_serialize()); |
1302 *cached_data = CodeSerializer::Serialize(isolate, result, source); | 1348 *cached_data = CodeSerializer::Serialize(isolate, result, source); |
1303 if (FLAG_profile_deserialization) { | 1349 if (FLAG_profile_deserialization) { |
1304 PrintF("[Compiling and serializing took %0.3f ms]\n", | 1350 PrintF("[Compiling and serializing took %0.3f ms]\n", |
1305 timer.Elapsed().InMillisecondsF()); | 1351 timer.Elapsed().InMillisecondsF()); |
1306 } | 1352 } |
1307 } | 1353 } |
1308 } | 1354 } |
1309 | 1355 |
1310 if (result.is_null()) isolate->ReportPendingMessages(); | 1356 if (result.is_null()) { |
| 1357 isolate->ReportPendingMessages(); |
| 1358 } else { |
| 1359 isolate->debug()->OnAfterCompile(script); |
| 1360 } |
1311 } else if (result->ic_age() != isolate->heap()->global_ic_age()) { | 1361 } else if (result->ic_age() != isolate->heap()->global_ic_age()) { |
1312 result->ResetForNewContext(isolate->heap()->global_ic_age()); | 1362 result->ResetForNewContext(isolate->heap()->global_ic_age()); |
1313 } | 1363 } |
1314 return result; | 1364 return result; |
1315 } | 1365 } |
1316 | 1366 |
1317 | 1367 |
1318 Handle<SharedFunctionInfo> Compiler::CompileStreamedScript( | 1368 Handle<SharedFunctionInfo> Compiler::CompileStreamedScript( |
1319 Handle<Script> script, ParseInfo* parse_info, int source_length) { | 1369 Handle<Script> script, ParseInfo* parse_info, int source_length) { |
1320 Isolate* isolate = script->GetIsolate(); | 1370 Isolate* isolate = script->GetIsolate(); |
1321 // TODO(titzer): increment the counters in caller. | 1371 // TODO(titzer): increment the counters in caller. |
1322 isolate->counters()->total_load_size()->Increment(source_length); | 1372 isolate->counters()->total_load_size()->Increment(source_length); |
1323 isolate->counters()->total_compile_size()->Increment(source_length); | 1373 isolate->counters()->total_compile_size()->Increment(source_length); |
1324 | 1374 |
1325 LanguageMode language_mode = | 1375 LanguageMode language_mode = |
1326 construct_language_mode(FLAG_use_strict, FLAG_use_strong); | 1376 construct_language_mode(FLAG_use_strict, FLAG_use_strong); |
1327 parse_info->set_language_mode( | 1377 parse_info->set_language_mode( |
1328 static_cast<LanguageMode>(parse_info->language_mode() | language_mode)); | 1378 static_cast<LanguageMode>(parse_info->language_mode() | language_mode)); |
1329 | 1379 |
1330 CompilationInfo compile_info(parse_info); | 1380 CompilationInfo compile_info(parse_info); |
1331 | 1381 |
1332 // If compiling for debugging, parse eagerly from scratch. | 1382 // If compiling for debugging, parse eagerly from scratch. |
1333 if (compile_info.is_debug()) parse_info->set_literal(NULL); | 1383 if (compile_info.is_debug()) parse_info->set_literal(NULL); |
1334 | 1384 |
1335 return CompileToplevel(&compile_info); | 1385 Handle<SharedFunctionInfo> result = CompileToplevel(&compile_info); |
| 1386 if (!result.is_null()) isolate->debug()->OnAfterCompile(script); |
| 1387 return result; |
1336 } | 1388 } |
1337 | 1389 |
1338 | 1390 |
1339 Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo( | 1391 Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo( |
1340 FunctionLiteral* literal, Handle<Script> script, | 1392 FunctionLiteral* literal, Handle<Script> script, |
1341 CompilationInfo* outer_info) { | 1393 CompilationInfo* outer_info) { |
1342 // Precondition: code has been parsed and scopes have been analyzed. | 1394 // Precondition: code has been parsed and scopes have been analyzed. |
1343 Isolate* isolate = outer_info->isolate(); | 1395 Isolate* isolate = outer_info->isolate(); |
1344 MaybeHandle<SharedFunctionInfo> maybe_existing; | 1396 MaybeHandle<SharedFunctionInfo> maybe_existing; |
1345 if (outer_info->is_first_compile()) { | 1397 if (outer_info->is_first_compile()) { |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1618 | 1670 |
1619 | 1671 |
1620 #if DEBUG | 1672 #if DEBUG |
1621 void CompilationInfo::PrintAstForTesting() { | 1673 void CompilationInfo::PrintAstForTesting() { |
1622 PrintF("--- Source from AST ---\n%s\n", | 1674 PrintF("--- Source from AST ---\n%s\n", |
1623 PrettyPrinter(isolate(), zone()).PrintProgram(function())); | 1675 PrettyPrinter(isolate(), zone()).PrintProgram(function())); |
1624 } | 1676 } |
1625 #endif | 1677 #endif |
1626 } // namespace internal | 1678 } // namespace internal |
1627 } // namespace v8 | 1679 } // namespace v8 |
OLD | NEW |