| 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 |