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 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
699 if (!isolate->has_pending_exception()) isolate->StackOverflow(); | 699 if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
700 return false; | 700 return false; |
701 } | 701 } |
702 return true; | 702 return true; |
703 } | 703 } |
704 | 704 |
705 | 705 |
706 // TODO(rmcilroy): Remove this temporary work-around when ignition supports | 706 // TODO(rmcilroy): Remove this temporary work-around when ignition supports |
707 // catch and eval. | 707 // catch and eval. |
708 static bool IgnitionShouldFallbackToFullCodeGen(Scope* scope) { | 708 static bool IgnitionShouldFallbackToFullCodeGen(Scope* scope) { |
709 if (!FLAG_ignition_fallback_on_eval_and_catch) return false; | |
710 | |
711 if (scope->is_eval_scope() || scope->is_catch_scope() || | 709 if (scope->is_eval_scope() || scope->is_catch_scope() || |
712 scope->calls_eval()) { | 710 scope->calls_eval()) { |
713 return true; | 711 return true; |
714 } | 712 } |
715 for (auto inner_scope : *scope->inner_scopes()) { | 713 for (auto inner_scope : *scope->inner_scopes()) { |
716 if (IgnitionShouldFallbackToFullCodeGen(inner_scope)) return true; | 714 if (IgnitionShouldFallbackToFullCodeGen(inner_scope)) return true; |
717 } | 715 } |
718 return false; | 716 return false; |
719 } | 717 } |
720 | 718 |
721 | 719 |
722 static bool GenerateBytecode(CompilationInfo* info) { | 720 static bool UseIgnition(CompilationInfo* info) { |
723 DCHECK(AllowCompilation::IsAllowed(info->isolate())); | 721 // Cannot use Ignition when the {function_data} is already used. |
724 bool success = false; | 722 if (info->has_shared_info() && info->shared_info()->HasBuiltinFunctionId()) { |
725 if (Compiler::Analyze(info->parse_info())) { | 723 return false; |
726 if (IgnitionShouldFallbackToFullCodeGen(info->scope())) { | |
727 success = FullCodeGenerator::MakeCode(info); | |
728 } else { | |
729 success = interpreter::Interpreter::MakeBytecode(info); | |
730 } | |
731 } | 724 } |
732 if (!success) { | 725 |
733 Isolate* isolate = info->isolate(); | 726 // Checks whether the scope chain is supported. |
734 if (!isolate->has_pending_exception()) isolate->StackOverflow(); | 727 if (FLAG_ignition_fallback_on_eval_and_catch && |
728 !IgnitionShouldFallbackToFullCodeGen(info->scope())) { | |
rmcilroy
2015/12/14 18:09:35
I think this should not have the "!"
Michael Starzinger
2015/12/14 18:21:24
Done.
| |
729 return false; | |
735 } | 730 } |
736 return success; | 731 |
732 // Checks whether top level functions should be passed by the filter. | |
733 if (info->closure().is_null()) { | |
734 Vector<const char> filter = CStrVector(FLAG_ignition_filter); | |
735 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*'); | |
736 } | |
737 | |
738 // Finally respect the filter. | |
739 return info->closure()->PassesFilter(FLAG_ignition_filter); | |
737 } | 740 } |
738 | 741 |
739 | 742 |
743 static bool GenerateFullCodeOrBytecode(CompilationInfo* info) { | |
rmcilroy
2015/12/14 18:09:35
Nit - GenerateBaselineCode(..) ? The current name
Michael Starzinger
2015/12/14 18:21:24
Done.
| |
744 if (FLAG_ignition && UseIgnition(info)) { | |
745 return interpreter::Interpreter::MakeBytecode(info); | |
746 } else { | |
747 return FullCodeGenerator::MakeCode(info); | |
748 } | |
749 } | |
750 | |
751 | |
752 static bool CompileBaselineCode(CompilationInfo* info) { | |
753 DCHECK(AllowCompilation::IsAllowed(info->isolate())); | |
754 if (!Compiler::Analyze(info->parse_info()) || | |
755 !GenerateFullCodeOrBytecode(info)) { | |
756 Isolate* isolate = info->isolate(); | |
757 if (!isolate->has_pending_exception()) isolate->StackOverflow(); | |
758 return false; | |
759 } | |
760 return true; | |
761 } | |
762 | |
763 | |
740 MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon( | 764 MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon( |
741 CompilationInfo* info) { | 765 CompilationInfo* info) { |
742 VMState<COMPILER> state(info->isolate()); | 766 VMState<COMPILER> state(info->isolate()); |
743 PostponeInterruptsScope postpone(info->isolate()); | 767 PostponeInterruptsScope postpone(info->isolate()); |
744 | 768 |
745 // Parse and update CompilationInfo with the results. | 769 // Parse and update CompilationInfo with the results. |
746 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>(); | 770 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>(); |
747 Handle<SharedFunctionInfo> shared = info->shared_info(); | 771 Handle<SharedFunctionInfo> shared = info->shared_info(); |
748 FunctionLiteral* lit = info->literal(); | 772 FunctionLiteral* lit = info->literal(); |
749 DCHECK_EQ(shared->language_mode(), lit->language_mode()); | 773 DCHECK_EQ(shared->language_mode(), lit->language_mode()); |
750 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count()); | 774 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count()); |
751 MaybeDisableOptimization(shared, lit->dont_optimize_reason()); | 775 MaybeDisableOptimization(shared, lit->dont_optimize_reason()); |
752 | 776 |
753 if (FLAG_ignition && !shared->HasBuiltinFunctionId() && | 777 // Compile either unoptimized code or bytecode for the interpreter. |
754 info->closure()->PassesFilter(FLAG_ignition_filter)) { | 778 if (!CompileBaselineCode(info)) return MaybeHandle<Code>(); |
755 // Compile bytecode for the interpreter. | 779 if (info->code()->kind() == Code::FUNCTION) { // Only for full code. |
756 if (!GenerateBytecode(info)) return MaybeHandle<Code>(); | |
757 } else { | |
758 // Compile unoptimized code. | |
759 if (!CompileUnoptimizedCode(info)) return MaybeHandle<Code>(); | |
760 | |
761 CHECK_EQ(Code::FUNCTION, info->code()->kind()); | |
762 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared); | 780 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared); |
763 } | 781 } |
764 | 782 |
765 // Update the shared function info with the scope info. Allocating the | 783 // Update the shared function info with the scope info. Allocating the |
766 // ScopeInfo object may cause a GC. | 784 // ScopeInfo object may cause a GC. |
767 Handle<ScopeInfo> scope_info = | 785 Handle<ScopeInfo> scope_info = |
768 ScopeInfo::Create(info->isolate(), info->zone(), info->scope()); | 786 ScopeInfo::Create(info->isolate(), info->zone(), info->scope()); |
769 shared->set_scope_info(*scope_info); | 787 shared->set_scope_info(*scope_info); |
770 | 788 |
771 // Update the code and feedback vector for the shared function info. | 789 // Update the code and feedback vector for the shared function info. |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1170 if (!CompileUnoptimizedCode(&info)) return; | 1188 if (!CompileUnoptimizedCode(&info)) return; |
1171 if (info.has_shared_info()) { | 1189 if (info.has_shared_info()) { |
1172 Handle<ScopeInfo> scope_info = | 1190 Handle<ScopeInfo> scope_info = |
1173 ScopeInfo::Create(info.isolate(), info.zone(), info.scope()); | 1191 ScopeInfo::Create(info.isolate(), info.zone(), info.scope()); |
1174 info.shared_info()->set_scope_info(*scope_info); | 1192 info.shared_info()->set_scope_info(*scope_info); |
1175 } | 1193 } |
1176 tracker.RecordRootFunctionInfo(info.code()); | 1194 tracker.RecordRootFunctionInfo(info.code()); |
1177 } | 1195 } |
1178 | 1196 |
1179 | 1197 |
1180 // Checks whether top level functions should be passed by {raw_filter}. | |
1181 static bool TopLevelFunctionPassesFilter(const char* raw_filter) { | |
1182 Vector<const char> filter = CStrVector(raw_filter); | |
1183 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*'); | |
1184 } | |
1185 | |
1186 | |
1187 static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) { | 1198 static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) { |
1188 Isolate* isolate = info->isolate(); | 1199 Isolate* isolate = info->isolate(); |
1189 PostponeInterruptsScope postpone(isolate); | 1200 PostponeInterruptsScope postpone(isolate); |
1190 DCHECK(!isolate->native_context().is_null()); | 1201 DCHECK(!isolate->native_context().is_null()); |
1191 ParseInfo* parse_info = info->parse_info(); | 1202 ParseInfo* parse_info = info->parse_info(); |
1192 Handle<Script> script = parse_info->script(); | 1203 Handle<Script> script = parse_info->script(); |
1193 | 1204 |
1194 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile? | 1205 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile? |
1195 FixedArray* array = isolate->native_context()->embedder_data(); | 1206 FixedArray* array = isolate->native_context()->embedder_data(); |
1196 script->set_context_data(array->get(v8::Context::kDebugIdIndex)); | 1207 script->set_context_data(array->get(v8::Context::kDebugIdIndex)); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1240 | 1251 |
1241 // Measure how long it takes to do the compilation; only take the | 1252 // Measure how long it takes to do the compilation; only take the |
1242 // rest of the function into account to avoid overlap with the | 1253 // rest of the function into account to avoid overlap with the |
1243 // parsing statistics. | 1254 // parsing statistics. |
1244 HistogramTimer* rate = info->is_eval() | 1255 HistogramTimer* rate = info->is_eval() |
1245 ? info->isolate()->counters()->compile_eval() | 1256 ? info->isolate()->counters()->compile_eval() |
1246 : info->isolate()->counters()->compile(); | 1257 : info->isolate()->counters()->compile(); |
1247 HistogramTimerScope timer(rate); | 1258 HistogramTimerScope timer(rate); |
1248 | 1259 |
1249 // Compile the code. | 1260 // Compile the code. |
1250 if (FLAG_ignition && TopLevelFunctionPassesFilter(FLAG_ignition_filter)) { | 1261 if (!CompileBaselineCode(info)) { |
1251 if (!GenerateBytecode(info)) { | 1262 return Handle<SharedFunctionInfo>::null(); |
1252 return Handle<SharedFunctionInfo>::null(); | |
1253 } | |
1254 } else { | |
1255 if (!CompileUnoptimizedCode(info)) { | |
1256 return Handle<SharedFunctionInfo>::null(); | |
1257 } | |
1258 } | 1263 } |
1259 | 1264 |
1260 // Allocate function. | 1265 // Allocate function. |
1261 DCHECK(!info->code().is_null()); | 1266 DCHECK(!info->code().is_null()); |
1262 result = isolate->factory()->NewSharedFunctionInfo( | 1267 result = isolate->factory()->NewSharedFunctionInfo( |
1263 lit->name(), lit->materialized_literal_count(), lit->kind(), | 1268 lit->name(), lit->materialized_literal_count(), lit->kind(), |
1264 info->code(), | 1269 info->code(), |
1265 ScopeInfo::Create(info->isolate(), info->zone(), info->scope()), | 1270 ScopeInfo::Create(info->isolate(), info->zone(), info->scope()), |
1266 info->feedback_vector()); | 1271 info->feedback_vector()); |
1267 if (info->has_bytecode_array()) { | 1272 if (info->has_bytecode_array()) { |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1592 info.SetCode(code); | 1597 info.SetCode(code); |
1593 // There's no need in theory for a lazy-compiled function to have a type | 1598 // There's no need in theory for a lazy-compiled function to have a type |
1594 // feedback vector, but some parts of the system expect all | 1599 // feedback vector, but some parts of the system expect all |
1595 // SharedFunctionInfo instances to have one. The size of the vector depends | 1600 // SharedFunctionInfo instances to have one. The size of the vector depends |
1596 // on how many feedback-needing nodes are in the tree, and when lazily | 1601 // on how many feedback-needing nodes are in the tree, and when lazily |
1597 // parsing we might not know that, if this function was never parsed before. | 1602 // parsing we might not know that, if this function was never parsed before. |
1598 // In that case the vector will be replaced the next time MakeCode is | 1603 // In that case the vector will be replaced the next time MakeCode is |
1599 // called. | 1604 // called. |
1600 info.EnsureFeedbackVector(); | 1605 info.EnsureFeedbackVector(); |
1601 scope_info = Handle<ScopeInfo>(ScopeInfo::Empty(isolate)); | 1606 scope_info = Handle<ScopeInfo>(ScopeInfo::Empty(isolate)); |
1602 } else if (Renumber(info.parse_info()) && | 1607 } else if (Renumber(info.parse_info()) && GenerateFullCodeOrBytecode(&info)) { |
1603 FullCodeGenerator::MakeCode(&info)) { | 1608 // Code generation will ensure that the feedback vector is present and |
1604 // MakeCode will ensure that the feedback vector is present and | |
1605 // appropriately sized. | 1609 // appropriately sized. |
1606 DCHECK(!info.code().is_null()); | 1610 DCHECK(!info.code().is_null()); |
1607 scope_info = ScopeInfo::Create(info.isolate(), info.zone(), info.scope()); | 1611 scope_info = ScopeInfo::Create(info.isolate(), info.zone(), info.scope()); |
1608 if (literal->should_eager_compile() && | 1612 if (literal->should_eager_compile() && |
1609 literal->should_be_used_once_hint()) { | 1613 literal->should_be_used_once_hint()) { |
1610 info.code()->MarkToBeExecutedOnce(isolate); | 1614 info.code()->MarkToBeExecutedOnce(isolate); |
1611 } | 1615 } |
1612 } else { | 1616 } else { |
1613 return Handle<SharedFunctionInfo>::null(); | 1617 return Handle<SharedFunctionInfo>::null(); |
1614 } | 1618 } |
1615 | 1619 |
1616 if (maybe_existing.is_null()) { | 1620 if (maybe_existing.is_null()) { |
1617 // Create a shared function info object. | 1621 // Create a shared function info object. |
1618 Handle<SharedFunctionInfo> result = | 1622 Handle<SharedFunctionInfo> result = |
1619 isolate->factory()->NewSharedFunctionInfo( | 1623 isolate->factory()->NewSharedFunctionInfo( |
1620 literal->name(), literal->materialized_literal_count(), | 1624 literal->name(), literal->materialized_literal_count(), |
1621 literal->kind(), info.code(), scope_info, info.feedback_vector()); | 1625 literal->kind(), info.code(), scope_info, info.feedback_vector()); |
1626 if (info.has_bytecode_array()) { | |
1627 DCHECK(result->function_data()->IsUndefined()); | |
1628 result->set_function_data(*info.bytecode_array()); | |
1629 } | |
1622 | 1630 |
1623 SharedFunctionInfo::InitFromFunctionLiteral(result, literal); | 1631 SharedFunctionInfo::InitFromFunctionLiteral(result, literal); |
1624 SharedFunctionInfo::SetScript(result, script); | 1632 SharedFunctionInfo::SetScript(result, script); |
1625 result->set_is_toplevel(false); | 1633 result->set_is_toplevel(false); |
1626 // If the outer function has been compiled before, we cannot be sure that | 1634 // If the outer function has been compiled before, we cannot be sure that |
1627 // shared function info for this function literal has been created for the | 1635 // shared function info for this function literal has been created for the |
1628 // first time. It may have already been compiled previously. | 1636 // first time. It may have already been compiled previously. |
1629 result->set_never_compiled(outer_info->is_first_compile() && lazy); | 1637 result->set_never_compiled(outer_info->is_first_compile() && lazy); |
1630 | 1638 |
1631 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result); | 1639 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result); |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1803 } | 1811 } |
1804 | 1812 |
1805 #if DEBUG | 1813 #if DEBUG |
1806 void CompilationInfo::PrintAstForTesting() { | 1814 void CompilationInfo::PrintAstForTesting() { |
1807 PrintF("--- Source from AST ---\n%s\n", | 1815 PrintF("--- Source from AST ---\n%s\n", |
1808 PrettyPrinter(isolate()).PrintProgram(literal())); | 1816 PrettyPrinter(isolate()).PrintProgram(literal())); |
1809 } | 1817 } |
1810 #endif | 1818 #endif |
1811 } // namespace internal | 1819 } // namespace internal |
1812 } // namespace v8 | 1820 } // namespace v8 |
OLD | NEW |