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 |