| 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/ast-numbering.h" | 9 #include "src/ast/ast-numbering.h" |
| 10 #include "src/ast/prettyprinter.h" | 10 #include "src/ast/prettyprinter.h" |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 // support won't be "equivalent" (as defined by SharedFunctionInfo:: | 129 // support won't be "equivalent" (as defined by SharedFunctionInfo:: |
| 130 // EnableDeoptimizationSupport), so it will replace the old code and all | 130 // EnableDeoptimizationSupport), so it will replace the old code and all |
| 131 // its type feedback. To avoid this, always compile functions in the snapshot | 131 // its type feedback. To avoid this, always compile functions in the snapshot |
| 132 // with deoptimization support. | 132 // with deoptimization support. |
| 133 if (isolate_->serializer_enabled()) EnableDeoptimizationSupport(); | 133 if (isolate_->serializer_enabled()) EnableDeoptimizationSupport(); |
| 134 | 134 |
| 135 if (FLAG_function_context_specialization) MarkAsFunctionContextSpecializing(); | 135 if (FLAG_function_context_specialization) MarkAsFunctionContextSpecializing(); |
| 136 if (FLAG_turbo_inlining) MarkAsInliningEnabled(); | 136 if (FLAG_turbo_inlining) MarkAsInliningEnabled(); |
| 137 if (FLAG_turbo_source_positions) MarkAsSourcePositionsEnabled(); | 137 if (FLAG_turbo_source_positions) MarkAsSourcePositionsEnabled(); |
| 138 if (FLAG_turbo_splitting) MarkAsSplittingEnabled(); | 138 if (FLAG_turbo_splitting) MarkAsSplittingEnabled(); |
| 139 | |
| 140 if (has_shared_info()) { | |
| 141 if (shared_info()->never_compiled()) MarkAsFirstCompile(); | |
| 142 } | |
| 143 } | 139 } |
| 144 | 140 |
| 145 | 141 |
| 146 CompilationInfo::CompilationInfo(const char* debug_name, Isolate* isolate, | 142 CompilationInfo::CompilationInfo(const char* debug_name, Isolate* isolate, |
| 147 Zone* zone, Code::Flags code_flags) | 143 Zone* zone, Code::Flags code_flags) |
| 148 : CompilationInfo(nullptr, debug_name, code_flags, STUB, isolate, zone) {} | 144 : CompilationInfo(nullptr, debug_name, code_flags, STUB, isolate, zone) {} |
| 149 | 145 |
| 150 CompilationInfo::CompilationInfo(ParseInfo* parse_info, const char* debug_name, | 146 CompilationInfo::CompilationInfo(ParseInfo* parse_info, const char* debug_name, |
| 151 Code::Flags code_flags, Mode mode, | 147 Code::Flags code_flags, Mode mode, |
| 152 Isolate* isolate, Zone* zone) | 148 Isolate* isolate, Zone* zone) |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 } | 335 } |
| 340 if (!Compiler::EnsureDeoptimizationSupport(info())) { | 336 if (!Compiler::EnsureDeoptimizationSupport(info())) { |
| 341 return SetLastStatus(FAILED); | 337 return SetLastStatus(FAILED); |
| 342 } | 338 } |
| 343 if (FLAG_hydrogen_stats) { | 339 if (FLAG_hydrogen_stats) { |
| 344 isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed()); | 340 isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed()); |
| 345 } | 341 } |
| 346 } | 342 } |
| 347 | 343 |
| 348 DCHECK(info()->shared_info()->has_deoptimization_support()); | 344 DCHECK(info()->shared_info()->has_deoptimization_support()); |
| 349 DCHECK(!info()->is_first_compile()); | 345 DCHECK(!info()->shared_info()->never_compiled()); |
| 350 | 346 |
| 351 if (FLAG_trace_opt) { | 347 if (FLAG_trace_opt) { |
| 352 OFStream os(stdout); | 348 OFStream os(stdout); |
| 353 os << "[compiling method " << Brief(*info()->closure()) << " using " | 349 os << "[compiling method " << Brief(*info()->closure()) << " using " |
| 354 << compiler_name_; | 350 << compiler_name_; |
| 355 if (info()->is_osr()) os << " OSR"; | 351 if (info()->is_osr()) os << " OSR"; |
| 356 os << "]" << std::endl; | 352 os << "]" << std::endl; |
| 357 } | 353 } |
| 358 | 354 |
| 359 // Delegate to the underlying implementation. | 355 // Delegate to the underlying implementation. |
| (...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1013 parse_info->set_cached_data(nullptr); | 1009 parse_info->set_cached_data(nullptr); |
| 1014 parse_info->set_compile_options(ScriptCompiler::kNoCompileOptions); | 1010 parse_info->set_compile_options(ScriptCompiler::kNoCompileOptions); |
| 1015 } | 1011 } |
| 1016 if (!Parser::ParseStatic(parse_info)) { | 1012 if (!Parser::ParseStatic(parse_info)) { |
| 1017 return Handle<SharedFunctionInfo>::null(); | 1013 return Handle<SharedFunctionInfo>::null(); |
| 1018 } | 1014 } |
| 1019 } | 1015 } |
| 1020 | 1016 |
| 1021 DCHECK(!info->is_debug() || !parse_info->allow_lazy_parsing()); | 1017 DCHECK(!info->is_debug() || !parse_info->allow_lazy_parsing()); |
| 1022 | 1018 |
| 1023 info->MarkAsFirstCompile(); | |
| 1024 | |
| 1025 FunctionLiteral* lit = parse_info->literal(); | 1019 FunctionLiteral* lit = parse_info->literal(); |
| 1026 LiveEditFunctionTracker live_edit_tracker(isolate, lit); | 1020 LiveEditFunctionTracker live_edit_tracker(isolate, lit); |
| 1027 | 1021 |
| 1028 // Measure how long it takes to do the compilation; only take the | 1022 // Measure how long it takes to do the compilation; only take the |
| 1029 // rest of the function into account to avoid overlap with the | 1023 // rest of the function into account to avoid overlap with the |
| 1030 // parsing statistics. | 1024 // parsing statistics. |
| 1031 HistogramTimer* rate = info->is_eval() | 1025 HistogramTimer* rate = info->is_eval() |
| 1032 ? info->isolate()->counters()->compile_eval() | 1026 ? info->isolate()->counters()->compile_eval() |
| 1033 : info->isolate()->counters()->compile(); | 1027 : info->isolate()->counters()->compile(); |
| 1034 HistogramTimerScope timer(rate); | 1028 HistogramTimerScope timer(rate); |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1200 // can be added without losing IC state. | 1194 // can be added without losing IC state. |
| 1201 if (shared->code()->kind() == Code::FUNCTION && | 1195 if (shared->code()->kind() == Code::FUNCTION && |
| 1202 shared->code()->has_reloc_info_for_serialization()) { | 1196 shared->code()->has_reloc_info_for_serialization()) { |
| 1203 unoptimized.PrepareForSerializing(); | 1197 unoptimized.PrepareForSerializing(); |
| 1204 } | 1198 } |
| 1205 EnsureFeedbackVector(&unoptimized); | 1199 EnsureFeedbackVector(&unoptimized); |
| 1206 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false; | 1200 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false; |
| 1207 | 1201 |
| 1208 shared->EnableDeoptimizationSupport(*unoptimized.code()); | 1202 shared->EnableDeoptimizationSupport(*unoptimized.code()); |
| 1209 | 1203 |
| 1210 info->MarkAsCompiled(); | |
| 1211 | |
| 1212 // The scope info might not have been set if a lazily compiled | 1204 // The scope info might not have been set if a lazily compiled |
| 1213 // function is inlined before being called for the first time. | 1205 // function is inlined before being called for the first time. |
| 1214 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) { | 1206 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) { |
| 1215 Handle<ScopeInfo> target_scope_info = | 1207 Handle<ScopeInfo> target_scope_info = |
| 1216 ScopeInfo::Create(info->isolate(), info->zone(), info->scope()); | 1208 ScopeInfo::Create(info->isolate(), info->zone(), info->scope()); |
| 1217 shared->set_scope_info(*target_scope_info); | 1209 shared->set_scope_info(*target_scope_info); |
| 1218 } | 1210 } |
| 1219 | 1211 |
| 1220 // The existing unoptimized code was replaced with the new one. | 1212 // The existing unoptimized code was replaced with the new one. |
| 1221 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized, shared); | 1213 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized, shared); |
| 1222 } | 1214 } |
| 1223 return true; | 1215 return true; |
| 1224 } | 1216 } |
| 1225 | 1217 |
| 1226 void Compiler::CompileForLiveEdit(Handle<Script> script) { | 1218 void Compiler::CompileForLiveEdit(Handle<Script> script) { |
| 1227 // TODO(635): support extensions. | 1219 // TODO(635): support extensions. |
| 1228 Zone zone(script->GetIsolate()->allocator()); | 1220 Zone zone(script->GetIsolate()->allocator()); |
| 1229 ParseInfo parse_info(&zone, script); | 1221 ParseInfo parse_info(&zone, script); |
| 1230 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); | 1222 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); |
| 1231 PostponeInterruptsScope postpone(info.isolate()); | 1223 PostponeInterruptsScope postpone(info.isolate()); |
| 1232 VMState<COMPILER> state(info.isolate()); | 1224 VMState<COMPILER> state(info.isolate()); |
| 1233 | 1225 |
| 1234 // Get rid of old list of shared function infos. | |
| 1235 info.MarkAsFirstCompile(); | |
| 1236 info.MarkAsDebug(); | 1226 info.MarkAsDebug(); |
| 1237 info.parse_info()->set_global(); | 1227 info.parse_info()->set_global(); |
| 1238 if (!Parser::ParseStatic(info.parse_info())) return; | 1228 if (!Parser::ParseStatic(info.parse_info())) return; |
| 1239 | 1229 |
| 1240 LiveEditFunctionTracker tracker(info.isolate(), parse_info.literal()); | 1230 LiveEditFunctionTracker tracker(info.isolate(), parse_info.literal()); |
| 1241 if (!CompileUnoptimizedCode(&info)) return; | 1231 if (!CompileUnoptimizedCode(&info)) return; |
| 1242 tracker.RecordRootFunctionInfo(info.code()); | 1232 tracker.RecordRootFunctionInfo(info.code()); |
| 1243 } | 1233 } |
| 1244 | 1234 |
| 1245 MaybeHandle<JSFunction> Compiler::GetFunctionFromEval( | 1235 MaybeHandle<JSFunction> Compiler::GetFunctionFromEval( |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1460 return result; | 1450 return result; |
| 1461 } | 1451 } |
| 1462 | 1452 |
| 1463 | 1453 |
| 1464 Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo( | 1454 Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo( |
| 1465 FunctionLiteral* literal, Handle<Script> script, | 1455 FunctionLiteral* literal, Handle<Script> script, |
| 1466 CompilationInfo* outer_info) { | 1456 CompilationInfo* outer_info) { |
| 1467 // Precondition: code has been parsed and scopes have been analyzed. | 1457 // Precondition: code has been parsed and scopes have been analyzed. |
| 1468 Isolate* isolate = outer_info->isolate(); | 1458 Isolate* isolate = outer_info->isolate(); |
| 1469 MaybeHandle<SharedFunctionInfo> maybe_existing; | 1459 MaybeHandle<SharedFunctionInfo> maybe_existing; |
| 1470 if (outer_info->is_first_compile()) { | 1460 |
| 1461 // The only reason we ever get here without having a shared function info for |
| 1462 // the outer function, is when we are compiling for live edit. That is also |
| 1463 // the case in which we want to re-generate all inner shared function info |
| 1464 // objects by just assuming the top-most one has not been compiled yet. |
| 1465 DCHECK_IMPLIES(!outer_info->has_shared_info(), |
| 1466 isolate->debug()->live_edit_enabled()); |
| 1467 bool outer_function_was_never_compiled = |
| 1468 !outer_info->has_shared_info() || |
| 1469 outer_info->shared_info()->never_compiled(); |
| 1470 |
| 1471 // Find any previously allocated shared function info for the given literal. |
| 1472 if (outer_function_was_never_compiled) { |
| 1471 // On the first compile, there are no existing shared function info for | 1473 // On the first compile, there are no existing shared function info for |
| 1472 // inner functions yet, so do not try to find them. All bets are off for | 1474 // inner functions yet, so do not try to find them. All bets are off for |
| 1473 // live edit though. | 1475 // live edit though. |
| 1474 SLOW_DCHECK(script->FindSharedFunctionInfo(literal).is_null() || | 1476 SLOW_DCHECK(script->FindSharedFunctionInfo(literal).is_null() || |
| 1475 isolate->debug()->live_edit_enabled()); | 1477 isolate->debug()->live_edit_enabled()); |
| 1476 } else { | 1478 } else { |
| 1477 maybe_existing = script->FindSharedFunctionInfo(literal); | 1479 maybe_existing = script->FindSharedFunctionInfo(literal); |
| 1478 } | 1480 } |
| 1481 |
| 1479 // We found an existing shared function info. If it's already compiled, | 1482 // We found an existing shared function info. If it's already compiled, |
| 1480 // don't worry about compiling it, and simply return it. If it's not yet | 1483 // don't worry about compiling it, and simply return it. If it's not yet |
| 1481 // compiled, continue to decide whether to eagerly compile. | 1484 // compiled, continue to decide whether to eagerly compile. |
| 1482 // Carry on if we are compiling eager to obtain code for debugging, | 1485 // Carry on if we are compiling eager to obtain code for debugging, |
| 1483 // unless we already have code with debut break slots. | 1486 // unless we already have code with debut break slots. |
| 1484 Handle<SharedFunctionInfo> existing; | 1487 Handle<SharedFunctionInfo> existing; |
| 1485 if (maybe_existing.ToHandle(&existing) && existing->is_compiled()) { | 1488 if (maybe_existing.ToHandle(&existing) && existing->is_compiled()) { |
| 1486 if (!outer_info->is_debug() || existing->HasDebugCode()) { | 1489 if (!outer_info->is_debug() || existing->HasDebugCode()) { |
| 1487 return existing; | 1490 return existing; |
| 1488 } | 1491 } |
| 1489 } | 1492 } |
| 1490 | 1493 |
| 1491 // Allocate a shared function info object. | 1494 // Allocate a shared function info object. |
| 1492 Handle<SharedFunctionInfo> result; | 1495 Handle<SharedFunctionInfo> result; |
| 1493 if (!maybe_existing.ToHandle(&result)) { | 1496 if (!maybe_existing.ToHandle(&result)) { |
| 1494 result = NewSharedFunctionInfoForLiteral(isolate, literal, script); | 1497 result = NewSharedFunctionInfoForLiteral(isolate, literal, script); |
| 1495 result->set_is_toplevel(false); | 1498 result->set_is_toplevel(false); |
| 1499 |
| 1500 // If the outer function has been compiled before, we cannot be sure that |
| 1501 // shared function info for this function literal has been created for the |
| 1502 // first time. It may have already been compiled previously. |
| 1503 result->set_never_compiled(outer_function_was_never_compiled); |
| 1496 } | 1504 } |
| 1497 | 1505 |
| 1498 Zone zone(isolate->allocator()); | 1506 Zone zone(isolate->allocator()); |
| 1499 ParseInfo parse_info(&zone, script); | 1507 ParseInfo parse_info(&zone, script); |
| 1500 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); | 1508 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); |
| 1501 parse_info.set_literal(literal); | 1509 parse_info.set_literal(literal); |
| 1502 parse_info.set_shared_info(result); | 1510 parse_info.set_shared_info(result); |
| 1503 parse_info.set_scope(literal->scope()); | 1511 parse_info.set_scope(literal->scope()); |
| 1504 parse_info.set_language_mode(literal->scope()->language_mode()); | 1512 parse_info.set_language_mode(literal->scope()->language_mode()); |
| 1505 if (outer_info->will_serialize()) info.PrepareForSerializing(); | 1513 if (outer_info->will_serialize()) info.PrepareForSerializing(); |
| 1506 if (outer_info->is_first_compile()) info.MarkAsFirstCompile(); | |
| 1507 if (outer_info->is_debug()) info.MarkAsDebug(); | 1514 if (outer_info->is_debug()) info.MarkAsDebug(); |
| 1508 | 1515 |
| 1509 LiveEditFunctionTracker live_edit_tracker(isolate, literal); | 1516 LiveEditFunctionTracker live_edit_tracker(isolate, literal); |
| 1510 // Determine if the function can be lazily compiled. This is necessary to | 1517 // Determine if the function can be lazily compiled. This is necessary to |
| 1511 // allow some of our builtin JS files to be lazily compiled. These | 1518 // allow some of our builtin JS files to be lazily compiled. These |
| 1512 // builtins cannot be handled lazily by the parser, since we have to know | 1519 // builtins cannot be handled lazily by the parser, since we have to know |
| 1513 // if a function uses the special natives syntax, which is something the | 1520 // if a function uses the special natives syntax, which is something the |
| 1514 // parser records. | 1521 // parser records. |
| 1515 // If the debugger requests compilation for break points, we cannot be | 1522 // If the debugger requests compilation for break points, we cannot be |
| 1516 // aggressive about lazy compilation, because it might trigger compilation | 1523 // aggressive about lazy compilation, because it might trigger compilation |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1547 literal->should_be_used_once_hint()) { | 1554 literal->should_be_used_once_hint()) { |
| 1548 info.code()->MarkToBeExecutedOnce(isolate); | 1555 info.code()->MarkToBeExecutedOnce(isolate); |
| 1549 } | 1556 } |
| 1550 // Install compilation result on the shared function info. | 1557 // Install compilation result on the shared function info. |
| 1551 InstallBaselineCompilationResult(&info, result, scope_info); | 1558 InstallBaselineCompilationResult(&info, result, scope_info); |
| 1552 } else { | 1559 } else { |
| 1553 return Handle<SharedFunctionInfo>::null(); | 1560 return Handle<SharedFunctionInfo>::null(); |
| 1554 } | 1561 } |
| 1555 | 1562 |
| 1556 if (maybe_existing.is_null()) { | 1563 if (maybe_existing.is_null()) { |
| 1557 // If the outer function has been compiled before, we cannot be sure that | |
| 1558 // shared function info for this function literal has been created for the | |
| 1559 // first time. It may have already been compiled previously. | |
| 1560 result->set_never_compiled(outer_info->is_first_compile() && lazy); | |
| 1561 | |
| 1562 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result); | 1564 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result); |
| 1563 live_edit_tracker.RecordFunctionInfo(result, literal, info.zone()); | 1565 live_edit_tracker.RecordFunctionInfo(result, literal, info.zone()); |
| 1564 } | 1566 } |
| 1565 | 1567 |
| 1566 return result; | 1568 return result; |
| 1567 } | 1569 } |
| 1568 | 1570 |
| 1569 Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForNative( | 1571 Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForNative( |
| 1570 v8::Extension* extension, Handle<String> name) { | 1572 v8::Extension* extension, Handle<String> name) { |
| 1571 Isolate* isolate = name->GetIsolate(); | 1573 Isolate* isolate = name->GetIsolate(); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1688 MaybeHandle<Code> code; | 1690 MaybeHandle<Code> code; |
| 1689 if (cached.code != nullptr) code = handle(cached.code); | 1691 if (cached.code != nullptr) code = handle(cached.code); |
| 1690 Handle<Context> native_context(function->context()->native_context()); | 1692 Handle<Context> native_context(function->context()->native_context()); |
| 1691 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, | 1693 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, |
| 1692 literals, BailoutId::None()); | 1694 literals, BailoutId::None()); |
| 1693 } | 1695 } |
| 1694 } | 1696 } |
| 1695 | 1697 |
| 1696 } // namespace internal | 1698 } // namespace internal |
| 1697 } // namespace v8 | 1699 } // namespace v8 |
| OLD | NEW |