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())) { |
| 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 GenerateBaselineCode(CompilationInfo* info) { |
| 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()) || !GenerateBaselineCode(info)) { |
| 755 Isolate* isolate = info->isolate(); |
| 756 if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
| 757 return false; |
| 758 } |
| 759 return true; |
| 760 } |
| 761 |
| 762 |
740 MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon( | 763 MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon( |
741 CompilationInfo* info) { | 764 CompilationInfo* info) { |
742 VMState<COMPILER> state(info->isolate()); | 765 VMState<COMPILER> state(info->isolate()); |
743 PostponeInterruptsScope postpone(info->isolate()); | 766 PostponeInterruptsScope postpone(info->isolate()); |
744 | 767 |
745 // Parse and update CompilationInfo with the results. | 768 // Parse and update CompilationInfo with the results. |
746 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>(); | 769 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>(); |
747 Handle<SharedFunctionInfo> shared = info->shared_info(); | 770 Handle<SharedFunctionInfo> shared = info->shared_info(); |
748 FunctionLiteral* lit = info->literal(); | 771 FunctionLiteral* lit = info->literal(); |
749 DCHECK_EQ(shared->language_mode(), lit->language_mode()); | 772 DCHECK_EQ(shared->language_mode(), lit->language_mode()); |
750 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count()); | 773 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count()); |
751 MaybeDisableOptimization(shared, lit->dont_optimize_reason()); | 774 MaybeDisableOptimization(shared, lit->dont_optimize_reason()); |
752 | 775 |
753 if (FLAG_ignition && !shared->HasBuiltinFunctionId() && | 776 // Compile either unoptimized code or bytecode for the interpreter. |
754 info->closure()->PassesFilter(FLAG_ignition_filter)) { | 777 if (!CompileBaselineCode(info)) return MaybeHandle<Code>(); |
755 // Compile bytecode for the interpreter. | 778 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); | 779 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared); |
763 } | 780 } |
764 | 781 |
765 // Update the shared function info with the scope info. Allocating the | 782 // Update the shared function info with the scope info. Allocating the |
766 // ScopeInfo object may cause a GC. | 783 // ScopeInfo object may cause a GC. |
767 Handle<ScopeInfo> scope_info = | 784 Handle<ScopeInfo> scope_info = |
768 ScopeInfo::Create(info->isolate(), info->zone(), info->scope()); | 785 ScopeInfo::Create(info->isolate(), info->zone(), info->scope()); |
769 shared->set_scope_info(*scope_info); | 786 shared->set_scope_info(*scope_info); |
770 | 787 |
771 // Update the code and feedback vector for the shared function info. | 788 // 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; | 1187 if (!CompileUnoptimizedCode(&info)) return; |
1171 if (info.has_shared_info()) { | 1188 if (info.has_shared_info()) { |
1172 Handle<ScopeInfo> scope_info = | 1189 Handle<ScopeInfo> scope_info = |
1173 ScopeInfo::Create(info.isolate(), info.zone(), info.scope()); | 1190 ScopeInfo::Create(info.isolate(), info.zone(), info.scope()); |
1174 info.shared_info()->set_scope_info(*scope_info); | 1191 info.shared_info()->set_scope_info(*scope_info); |
1175 } | 1192 } |
1176 tracker.RecordRootFunctionInfo(info.code()); | 1193 tracker.RecordRootFunctionInfo(info.code()); |
1177 } | 1194 } |
1178 | 1195 |
1179 | 1196 |
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) { | 1197 static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) { |
1188 Isolate* isolate = info->isolate(); | 1198 Isolate* isolate = info->isolate(); |
1189 PostponeInterruptsScope postpone(isolate); | 1199 PostponeInterruptsScope postpone(isolate); |
1190 DCHECK(!isolate->native_context().is_null()); | 1200 DCHECK(!isolate->native_context().is_null()); |
1191 ParseInfo* parse_info = info->parse_info(); | 1201 ParseInfo* parse_info = info->parse_info(); |
1192 Handle<Script> script = parse_info->script(); | 1202 Handle<Script> script = parse_info->script(); |
1193 | 1203 |
1194 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile? | 1204 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile? |
1195 FixedArray* array = isolate->native_context()->embedder_data(); | 1205 FixedArray* array = isolate->native_context()->embedder_data(); |
1196 script->set_context_data(array->get(v8::Context::kDebugIdIndex)); | 1206 script->set_context_data(array->get(v8::Context::kDebugIdIndex)); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1240 | 1250 |
1241 // Measure how long it takes to do the compilation; only take the | 1251 // Measure how long it takes to do the compilation; only take the |
1242 // rest of the function into account to avoid overlap with the | 1252 // rest of the function into account to avoid overlap with the |
1243 // parsing statistics. | 1253 // parsing statistics. |
1244 HistogramTimer* rate = info->is_eval() | 1254 HistogramTimer* rate = info->is_eval() |
1245 ? info->isolate()->counters()->compile_eval() | 1255 ? info->isolate()->counters()->compile_eval() |
1246 : info->isolate()->counters()->compile(); | 1256 : info->isolate()->counters()->compile(); |
1247 HistogramTimerScope timer(rate); | 1257 HistogramTimerScope timer(rate); |
1248 | 1258 |
1249 // Compile the code. | 1259 // Compile the code. |
1250 if (FLAG_ignition && TopLevelFunctionPassesFilter(FLAG_ignition_filter)) { | 1260 if (!CompileBaselineCode(info)) { |
1251 if (!GenerateBytecode(info)) { | 1261 return Handle<SharedFunctionInfo>::null(); |
1252 return Handle<SharedFunctionInfo>::null(); | |
1253 } | |
1254 } else { | |
1255 if (!CompileUnoptimizedCode(info)) { | |
1256 return Handle<SharedFunctionInfo>::null(); | |
1257 } | |
1258 } | 1262 } |
1259 | 1263 |
1260 // Allocate function. | 1264 // Allocate function. |
1261 DCHECK(!info->code().is_null()); | 1265 DCHECK(!info->code().is_null()); |
1262 result = isolate->factory()->NewSharedFunctionInfo( | 1266 result = isolate->factory()->NewSharedFunctionInfo( |
1263 lit->name(), lit->materialized_literal_count(), lit->kind(), | 1267 lit->name(), lit->materialized_literal_count(), lit->kind(), |
1264 info->code(), | 1268 info->code(), |
1265 ScopeInfo::Create(info->isolate(), info->zone(), info->scope()), | 1269 ScopeInfo::Create(info->isolate(), info->zone(), info->scope()), |
1266 info->feedback_vector()); | 1270 info->feedback_vector()); |
1267 if (info->has_bytecode_array()) { | 1271 if (info->has_bytecode_array()) { |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1594 // feedback vector, but some parts of the system expect all | 1598 // feedback vector, but some parts of the system expect all |
1595 // SharedFunctionInfo instances to have one. The size of the vector depends | 1599 // 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 | 1600 // 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. | 1601 // 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 | 1602 // In that case the vector will be replaced the next time MakeCode is |
1599 // called. | 1603 // called. |
1600 info.EnsureFeedbackVector(); | 1604 info.EnsureFeedbackVector(); |
1601 scope_info = Handle<ScopeInfo>(ScopeInfo::Empty(isolate)); | 1605 scope_info = Handle<ScopeInfo>(ScopeInfo::Empty(isolate)); |
1602 } else if (Renumber(info.parse_info()) && | 1606 } else if (Renumber(info.parse_info()) && |
1603 FullCodeGenerator::MakeCode(&info)) { | 1607 FullCodeGenerator::MakeCode(&info)) { |
1604 // MakeCode will ensure that the feedback vector is present and | 1608 // Code generation 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 |