| 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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 DisableFutureOptimization(); | 94 DisableFutureOptimization(); |
| 95 dependencies()->Rollback(); | 95 dependencies()->Rollback(); |
| 96 delete parse_info_; | 96 delete parse_info_; |
| 97 parse_info_ = nullptr; | 97 parse_info_ = nullptr; |
| 98 } | 98 } |
| 99 | 99 |
| 100 private: | 100 private: |
| 101 Zone zone_; | 101 Zone zone_; |
| 102 }; | 102 }; |
| 103 | 103 |
| 104 // ---------------------------------------------------------------------------- |
| 105 // Implementation of CompilationInfo |
| 104 | 106 |
| 105 bool CompilationInfo::has_shared_info() const { | 107 bool CompilationInfo::has_shared_info() const { |
| 106 return parse_info_ && !parse_info_->shared_info().is_null(); | 108 return parse_info_ && !parse_info_->shared_info().is_null(); |
| 107 } | 109 } |
| 108 | 110 |
| 109 | 111 |
| 110 bool CompilationInfo::has_context() const { | 112 bool CompilationInfo::has_context() const { |
| 111 return parse_info_ && !parse_info_->context().is_null(); | 113 return parse_info_ && !parse_info_->context().is_null(); |
| 112 } | 114 } |
| 113 | 115 |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 default: | 324 default: |
| 323 UNIMPLEMENTED(); | 325 UNIMPLEMENTED(); |
| 324 return StackFrame::NONE; | 326 return StackFrame::NONE; |
| 325 } | 327 } |
| 326 } | 328 } |
| 327 | 329 |
| 328 bool CompilationInfo::ExpectsJSReceiverAsReceiver() { | 330 bool CompilationInfo::ExpectsJSReceiverAsReceiver() { |
| 329 return is_sloppy(language_mode()) && !is_native(); | 331 return is_sloppy(language_mode()) && !is_native(); |
| 330 } | 332 } |
| 331 | 333 |
| 334 #if DEBUG |
| 335 void CompilationInfo::PrintAstForTesting() { |
| 336 PrintF("--- Source from AST ---\n%s\n", |
| 337 PrettyPrinter(isolate()).PrintProgram(literal())); |
| 338 } |
| 339 #endif |
| 340 |
| 341 // ---------------------------------------------------------------------------- |
| 342 // Implementation of OptimizedCompileJob |
| 332 | 343 |
| 333 class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder { | 344 class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder { |
| 334 public: | 345 public: |
| 335 explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info) | 346 explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info) |
| 336 : HOptimizedGraphBuilder(info) { | 347 : HOptimizedGraphBuilder(info) { |
| 337 } | 348 } |
| 338 | 349 |
| 339 #define DEF_VISIT(type) \ | 350 #define DEF_VISIT(type) \ |
| 340 void Visit##type(type* node) override { \ | 351 void Visit##type(type* node) override { \ |
| 341 SourcePosition old_position = SourcePosition::Unknown(); \ | 352 SourcePosition old_position = SourcePosition::Unknown(); \ |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 706 code_size, | 717 code_size, |
| 707 compilation_time); | 718 compilation_time); |
| 708 } | 719 } |
| 709 if (FLAG_hydrogen_stats) { | 720 if (FLAG_hydrogen_stats) { |
| 710 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_, | 721 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_, |
| 711 time_taken_to_optimize_, | 722 time_taken_to_optimize_, |
| 712 time_taken_to_codegen_); | 723 time_taken_to_codegen_); |
| 713 } | 724 } |
| 714 } | 725 } |
| 715 | 726 |
| 727 // ---------------------------------------------------------------------------- |
| 728 // Local helper methods that make up the compilation pipeline. |
| 729 |
| 730 namespace { |
| 716 | 731 |
| 717 // Sets the expected number of properties based on estimate from compiler. | 732 // Sets the expected number of properties based on estimate from compiler. |
| 718 void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared, | 733 void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared, |
| 719 int estimate) { | 734 int estimate) { |
| 720 // If no properties are added in the constructor, they are more likely | 735 // If no properties are added in the constructor, they are more likely |
| 721 // to be added later. | 736 // to be added later. |
| 722 if (estimate == 0) estimate = 2; | 737 if (estimate == 0) estimate = 2; |
| 723 | 738 |
| 724 // TODO(yangguo): check whether those heuristics are still up-to-date. | 739 // TODO(yangguo): check whether those heuristics are still up-to-date. |
| 725 // We do not shrink objects that go into a snapshot (yet), so we adjust | 740 // We do not shrink objects that go into a snapshot (yet), so we adjust |
| 726 // the estimate conservatively. | 741 // the estimate conservatively. |
| 727 if (shared->GetIsolate()->serializer_enabled()) { | 742 if (shared->GetIsolate()->serializer_enabled()) { |
| 728 estimate += 2; | 743 estimate += 2; |
| 729 } else { | 744 } else { |
| 730 // Inobject slack tracking will reclaim redundant inobject space later, | 745 // Inobject slack tracking will reclaim redundant inobject space later, |
| 731 // so we can afford to adjust the estimate generously. | 746 // so we can afford to adjust the estimate generously. |
| 732 estimate += 8; | 747 estimate += 8; |
| 733 } | 748 } |
| 734 | 749 |
| 735 shared->set_expected_nof_properties(estimate); | 750 shared->set_expected_nof_properties(estimate); |
| 736 } | 751 } |
| 737 | 752 |
| 738 | 753 void MaybeDisableOptimization(Handle<SharedFunctionInfo> shared_info, |
| 739 static void MaybeDisableOptimization(Handle<SharedFunctionInfo> shared_info, | 754 BailoutReason bailout_reason) { |
| 740 BailoutReason bailout_reason) { | |
| 741 if (bailout_reason != kNoReason) { | 755 if (bailout_reason != kNoReason) { |
| 742 shared_info->DisableOptimization(bailout_reason); | 756 shared_info->DisableOptimization(bailout_reason); |
| 743 } | 757 } |
| 744 } | 758 } |
| 745 | 759 |
| 746 | 760 void RecordFunctionCompilation(Logger::LogEventsAndTags tag, |
| 747 static void RecordFunctionCompilation(Logger::LogEventsAndTags tag, | 761 CompilationInfo* info, |
| 748 CompilationInfo* info, | 762 Handle<SharedFunctionInfo> shared) { |
| 749 Handle<SharedFunctionInfo> shared) { | |
| 750 // SharedFunctionInfo is passed separately, because if CompilationInfo | 763 // SharedFunctionInfo is passed separately, because if CompilationInfo |
| 751 // was created using Script object, it will not have it. | 764 // was created using Script object, it will not have it. |
| 752 | 765 |
| 753 // Log the code generation. If source information is available include | 766 // Log the code generation. If source information is available include |
| 754 // script name and line number. Check explicitly whether logging is | 767 // script name and line number. Check explicitly whether logging is |
| 755 // enabled as finding the line number is not free. | 768 // enabled as finding the line number is not free. |
| 756 if (info->isolate()->logger()->is_logging_code_events() || | 769 if (info->isolate()->logger()->is_logging_code_events() || |
| 757 info->isolate()->cpu_profiler()->is_profiling()) { | 770 info->isolate()->cpu_profiler()->is_profiling()) { |
| 758 Handle<Script> script = info->parse_info()->script(); | 771 Handle<Script> script = info->parse_info()->script(); |
| 759 Handle<AbstractCode> abstract_code = info->abstract_code(); | 772 Handle<AbstractCode> abstract_code = info->abstract_code(); |
| 760 if (abstract_code.is_identical_to( | 773 if (abstract_code.is_identical_to( |
| 761 info->isolate()->builtins()->CompileLazy())) { | 774 info->isolate()->builtins()->CompileLazy())) { |
| 762 return; | 775 return; |
| 763 } | 776 } |
| 764 int line_num = Script::GetLineNumber(script, shared->start_position()) + 1; | 777 int line_num = Script::GetLineNumber(script, shared->start_position()) + 1; |
| 765 int column_num = | 778 int column_num = |
| 766 Script::GetColumnNumber(script, shared->start_position()) + 1; | 779 Script::GetColumnNumber(script, shared->start_position()) + 1; |
| 767 String* script_name = script->name()->IsString() | 780 String* script_name = script->name()->IsString() |
| 768 ? String::cast(script->name()) | 781 ? String::cast(script->name()) |
| 769 : info->isolate()->heap()->empty_string(); | 782 : info->isolate()->heap()->empty_string(); |
| 770 Logger::LogEventsAndTags log_tag = Logger::ToNativeByScript(tag, *script); | 783 Logger::LogEventsAndTags log_tag = Logger::ToNativeByScript(tag, *script); |
| 771 PROFILE(info->isolate(), | 784 PROFILE(info->isolate(), |
| 772 CodeCreateEvent(log_tag, *abstract_code, *shared, info, script_name, | 785 CodeCreateEvent(log_tag, *abstract_code, *shared, info, script_name, |
| 773 line_num, column_num)); | 786 line_num, column_num)); |
| 774 } | 787 } |
| 775 } | 788 } |
| 776 | 789 |
| 777 static bool CompileUnoptimizedCode(CompilationInfo* info) { | 790 bool CompileUnoptimizedCode(CompilationInfo* info) { |
| 778 DCHECK(AllowCompilation::IsAllowed(info->isolate())); | 791 DCHECK(AllowCompilation::IsAllowed(info->isolate())); |
| 779 if (!Compiler::Analyze(info->parse_info()) || | 792 if (!Compiler::Analyze(info->parse_info()) || |
| 780 !FullCodeGenerator::MakeCode(info)) { | 793 !FullCodeGenerator::MakeCode(info)) { |
| 781 Isolate* isolate = info->isolate(); | 794 Isolate* isolate = info->isolate(); |
| 782 if (!isolate->has_pending_exception()) isolate->StackOverflow(); | 795 if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
| 783 return false; | 796 return false; |
| 784 } | 797 } |
| 785 return true; | 798 return true; |
| 786 } | 799 } |
| 787 | 800 |
| 788 static bool UseIgnition(CompilationInfo* info) { | 801 bool UseIgnition(CompilationInfo* info) { |
| 789 // TODO(4681): Generator functions are not yet supported. | 802 // TODO(4681): Generator functions are not yet supported. |
| 790 if ((info->has_shared_info() && info->shared_info()->is_generator()) || | 803 if ((info->has_shared_info() && info->shared_info()->is_generator()) || |
| 791 (info->has_literal() && IsGeneratorFunction(info->literal()->kind()))) { | 804 (info->has_literal() && IsGeneratorFunction(info->literal()->kind()))) { |
| 792 return false; | 805 return false; |
| 793 } | 806 } |
| 794 | 807 |
| 795 // TODO(4681): Resuming a suspended frame is not supported. | 808 // TODO(4681): Resuming a suspended frame is not supported. |
| 796 if (info->has_shared_info() && info->shared_info()->HasBuiltinFunctionId() && | 809 if (info->has_shared_info() && info->shared_info()->HasBuiltinFunctionId() && |
| 797 (info->shared_info()->builtin_function_id() == kGeneratorObjectNext || | 810 (info->shared_info()->builtin_function_id() == kGeneratorObjectNext || |
| 798 info->shared_info()->builtin_function_id() == kGeneratorObjectReturn || | 811 info->shared_info()->builtin_function_id() == kGeneratorObjectReturn || |
| 799 info->shared_info()->builtin_function_id() == kGeneratorObjectThrow)) { | 812 info->shared_info()->builtin_function_id() == kGeneratorObjectThrow)) { |
| 800 return false; | 813 return false; |
| 801 } | 814 } |
| 802 | 815 |
| 803 // Checks whether top level functions should be passed by the filter. | 816 // Checks whether top level functions should be passed by the filter. |
| 804 if (info->closure().is_null()) { | 817 if (info->closure().is_null()) { |
| 805 Vector<const char> filter = CStrVector(FLAG_ignition_filter); | 818 Vector<const char> filter = CStrVector(FLAG_ignition_filter); |
| 806 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*'); | 819 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*'); |
| 807 } | 820 } |
| 808 | 821 |
| 809 // Finally respect the filter. | 822 // Finally respect the filter. |
| 810 return info->closure()->PassesFilter(FLAG_ignition_filter); | 823 return info->closure()->PassesFilter(FLAG_ignition_filter); |
| 811 } | 824 } |
| 812 | 825 |
| 813 static int CodeAndMetadataSize(CompilationInfo* info) { | 826 int CodeAndMetadataSize(CompilationInfo* info) { |
| 814 int size = 0; | 827 int size = 0; |
| 815 if (info->has_bytecode_array()) { | 828 if (info->has_bytecode_array()) { |
| 816 Handle<BytecodeArray> bytecode_array = info->bytecode_array(); | 829 Handle<BytecodeArray> bytecode_array = info->bytecode_array(); |
| 817 size += bytecode_array->BytecodeArraySize(); | 830 size += bytecode_array->BytecodeArraySize(); |
| 818 size += bytecode_array->constant_pool()->Size(); | 831 size += bytecode_array->constant_pool()->Size(); |
| 819 size += bytecode_array->handler_table()->Size(); | 832 size += bytecode_array->handler_table()->Size(); |
| 820 size += bytecode_array->source_position_table()->Size(); | 833 size += bytecode_array->source_position_table()->Size(); |
| 821 } else { | 834 } else { |
| 822 Handle<Code> code = info->code(); | 835 Handle<Code> code = info->code(); |
| 823 size += code->CodeSize(); | 836 size += code->CodeSize(); |
| 824 size += code->relocation_info()->Size(); | 837 size += code->relocation_info()->Size(); |
| 825 size += code->deoptimization_data()->Size(); | 838 size += code->deoptimization_data()->Size(); |
| 826 size += code->handler_table()->Size(); | 839 size += code->handler_table()->Size(); |
| 827 } | 840 } |
| 828 return size; | 841 return size; |
| 829 } | 842 } |
| 830 | 843 |
| 831 | 844 bool GenerateBaselineCode(CompilationInfo* info) { |
| 832 static bool GenerateBaselineCode(CompilationInfo* info) { | |
| 833 bool success; | 845 bool success; |
| 834 if (FLAG_ignition && UseIgnition(info)) { | 846 if (FLAG_ignition && UseIgnition(info)) { |
| 835 success = interpreter::Interpreter::MakeBytecode(info); | 847 success = interpreter::Interpreter::MakeBytecode(info); |
| 836 } else { | 848 } else { |
| 837 success = FullCodeGenerator::MakeCode(info); | 849 success = FullCodeGenerator::MakeCode(info); |
| 838 } | 850 } |
| 839 if (success) { | 851 if (success) { |
| 840 Isolate* isolate = info->isolate(); | 852 Isolate* isolate = info->isolate(); |
| 841 Counters* counters = isolate->counters(); | 853 Counters* counters = isolate->counters(); |
| 842 counters->total_baseline_code_size()->Increment(CodeAndMetadataSize(info)); | 854 counters->total_baseline_code_size()->Increment(CodeAndMetadataSize(info)); |
| 843 counters->total_baseline_compile_count()->Increment(1); | 855 counters->total_baseline_compile_count()->Increment(1); |
| 844 } | 856 } |
| 845 return success; | 857 return success; |
| 846 } | 858 } |
| 847 | 859 |
| 848 | 860 bool CompileBaselineCode(CompilationInfo* info) { |
| 849 static bool CompileBaselineCode(CompilationInfo* info) { | |
| 850 DCHECK(AllowCompilation::IsAllowed(info->isolate())); | 861 DCHECK(AllowCompilation::IsAllowed(info->isolate())); |
| 851 if (!Compiler::Analyze(info->parse_info()) || !GenerateBaselineCode(info)) { | 862 if (!Compiler::Analyze(info->parse_info()) || !GenerateBaselineCode(info)) { |
| 852 Isolate* isolate = info->isolate(); | 863 Isolate* isolate = info->isolate(); |
| 853 if (!isolate->has_pending_exception()) isolate->StackOverflow(); | 864 if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
| 854 return false; | 865 return false; |
| 855 } | 866 } |
| 856 return true; | 867 return true; |
| 857 } | 868 } |
| 858 | 869 |
| 859 static void InstallBaselineCompilationResult(CompilationInfo* info, | 870 void InstallBaselineCompilationResult(CompilationInfo* info, |
| 860 Handle<SharedFunctionInfo> shared, | 871 Handle<SharedFunctionInfo> shared, |
| 861 Handle<ScopeInfo> scope_info) { | 872 Handle<ScopeInfo> scope_info) { |
| 862 // Assert that we are not overwriting (possibly patched) debug code. | 873 // Assert that we are not overwriting (possibly patched) debug code. |
| 863 DCHECK(!shared->HasDebugCode()); | 874 DCHECK(!shared->HasDebugCode()); |
| 864 DCHECK(!info->code().is_null()); | 875 DCHECK(!info->code().is_null()); |
| 865 shared->ReplaceCode(*info->code()); | 876 shared->ReplaceCode(*info->code()); |
| 866 shared->set_scope_info(*scope_info); | 877 shared->set_scope_info(*scope_info); |
| 867 shared->set_feedback_vector(*info->feedback_vector()); | 878 shared->set_feedback_vector(*info->feedback_vector()); |
| 868 if (info->has_bytecode_array()) { | 879 if (info->has_bytecode_array()) { |
| 869 DCHECK(!shared->HasBytecodeArray()); // Only compiled once. | 880 DCHECK(!shared->HasBytecodeArray()); // Only compiled once. |
| 870 shared->set_bytecode_array(*info->bytecode_array()); | 881 shared->set_bytecode_array(*info->bytecode_array()); |
| 871 } | 882 } |
| 872 } | 883 } |
| 873 | 884 |
| 874 MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon( | 885 MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCodeCommon( |
| 875 CompilationInfo* info) { | 886 CompilationInfo* info) { |
| 876 VMState<COMPILER> state(info->isolate()); | 887 VMState<COMPILER> state(info->isolate()); |
| 877 PostponeInterruptsScope postpone(info->isolate()); | 888 PostponeInterruptsScope postpone(info->isolate()); |
| 878 | 889 |
| 879 // Parse and update CompilationInfo with the results. | 890 // Parse and update CompilationInfo with the results. |
| 880 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>(); | 891 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>(); |
| 881 Handle<SharedFunctionInfo> shared = info->shared_info(); | 892 Handle<SharedFunctionInfo> shared = info->shared_info(); |
| 882 FunctionLiteral* lit = info->literal(); | 893 FunctionLiteral* lit = info->literal(); |
| 883 DCHECK_EQ(shared->language_mode(), lit->language_mode()); | 894 DCHECK_EQ(shared->language_mode(), lit->language_mode()); |
| 884 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count()); | 895 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count()); |
| 885 MaybeDisableOptimization(shared, lit->dont_optimize_reason()); | 896 MaybeDisableOptimization(shared, lit->dont_optimize_reason()); |
| 886 | 897 |
| 887 // Compile either unoptimized code or bytecode for the interpreter. | 898 // Compile either unoptimized code or bytecode for the interpreter. |
| 888 if (!CompileBaselineCode(info)) return MaybeHandle<Code>(); | 899 if (!CompileBaselineCode(info)) return MaybeHandle<Code>(); |
| 889 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared); | 900 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared); |
| 890 | 901 |
| 891 // Update the shared function info with the scope info. Allocating the | 902 // Update the shared function info with the scope info. Allocating the |
| 892 // ScopeInfo object may cause a GC. | 903 // ScopeInfo object may cause a GC. |
| 893 Handle<ScopeInfo> scope_info = | 904 Handle<ScopeInfo> scope_info = |
| 894 ScopeInfo::Create(info->isolate(), info->zone(), info->scope()); | 905 ScopeInfo::Create(info->isolate(), info->zone(), info->scope()); |
| 895 | 906 |
| 896 // Install compilation result on the shared function info | 907 // Install compilation result on the shared function info |
| 897 InstallBaselineCompilationResult(info, shared, scope_info); | 908 InstallBaselineCompilationResult(info, shared, scope_info); |
| 898 | 909 |
| 899 return info->code(); | 910 return info->code(); |
| 900 } | 911 } |
| 901 | 912 |
| 902 | 913 MUST_USE_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeMap( |
| 903 MUST_USE_RESULT static MaybeHandle<Code> GetCodeFromOptimizedCodeMap( | |
| 904 Handle<JSFunction> function, BailoutId osr_ast_id) { | 914 Handle<JSFunction> function, BailoutId osr_ast_id) { |
| 905 Handle<SharedFunctionInfo> shared(function->shared()); | 915 Handle<SharedFunctionInfo> shared(function->shared()); |
| 906 DisallowHeapAllocation no_gc; | 916 DisallowHeapAllocation no_gc; |
| 907 CodeAndLiterals cached = shared->SearchOptimizedCodeMap( | 917 CodeAndLiterals cached = shared->SearchOptimizedCodeMap( |
| 908 function->context()->native_context(), osr_ast_id); | 918 function->context()->native_context(), osr_ast_id); |
| 909 if (cached.code != nullptr) { | 919 if (cached.code != nullptr) { |
| 910 // Caching of optimized code enabled and optimized code found. | 920 // Caching of optimized code enabled and optimized code found. |
| 911 if (cached.literals != nullptr) function->set_literals(cached.literals); | 921 if (cached.literals != nullptr) function->set_literals(cached.literals); |
| 912 DCHECK(!cached.code->marked_for_deoptimization()); | 922 DCHECK(!cached.code->marked_for_deoptimization()); |
| 913 DCHECK(function->shared()->is_compiled()); | 923 DCHECK(function->shared()->is_compiled()); |
| 914 return Handle<Code>(cached.code); | 924 return Handle<Code>(cached.code); |
| 915 } | 925 } |
| 916 return MaybeHandle<Code>(); | 926 return MaybeHandle<Code>(); |
| 917 } | 927 } |
| 918 | 928 |
| 919 | 929 void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) { |
| 920 static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) { | |
| 921 Handle<Code> code = info->code(); | 930 Handle<Code> code = info->code(); |
| 922 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do. | 931 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do. |
| 923 | 932 |
| 924 // Function context specialization folds-in the function context, | 933 // Function context specialization folds-in the function context, |
| 925 // so no sharing can occur. | 934 // so no sharing can occur. |
| 926 if (info->is_function_context_specializing()) return; | 935 if (info->is_function_context_specializing()) return; |
| 927 // Frame specialization implies function context specialization. | 936 // Frame specialization implies function context specialization. |
| 928 DCHECK(!info->is_frame_specializing()); | 937 DCHECK(!info->is_frame_specializing()); |
| 929 | 938 |
| 930 // Cache optimized context-specific code. | 939 // Cache optimized context-specific code. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 941 // Cache optimized (native) context-independent code. | 950 // Cache optimized (native) context-independent code. |
| 942 if (FLAG_turbo_cache_shared_code && code->is_turbofanned() && | 951 if (FLAG_turbo_cache_shared_code && code->is_turbofanned() && |
| 943 !info->is_native_context_specializing()) { | 952 !info->is_native_context_specializing()) { |
| 944 DCHECK(!info->is_function_context_specializing()); | 953 DCHECK(!info->is_function_context_specializing()); |
| 945 DCHECK(info->osr_ast_id().IsNone()); | 954 DCHECK(info->osr_ast_id().IsNone()); |
| 946 Handle<SharedFunctionInfo> shared(function->shared()); | 955 Handle<SharedFunctionInfo> shared(function->shared()); |
| 947 SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap(shared, code); | 956 SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap(shared, code); |
| 948 } | 957 } |
| 949 } | 958 } |
| 950 | 959 |
| 951 | 960 bool Renumber(ParseInfo* parse_info) { |
| 952 static bool Renumber(ParseInfo* parse_info) { | |
| 953 if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(), | 961 if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(), |
| 954 parse_info->literal())) { | 962 parse_info->literal())) { |
| 955 return false; | 963 return false; |
| 956 } | 964 } |
| 957 Handle<SharedFunctionInfo> shared_info = parse_info->shared_info(); | 965 Handle<SharedFunctionInfo> shared_info = parse_info->shared_info(); |
| 958 if (!shared_info.is_null()) { | 966 if (!shared_info.is_null()) { |
| 959 FunctionLiteral* lit = parse_info->literal(); | 967 FunctionLiteral* lit = parse_info->literal(); |
| 960 shared_info->set_ast_node_count(lit->ast_node_count()); | 968 shared_info->set_ast_node_count(lit->ast_node_count()); |
| 961 MaybeDisableOptimization(shared_info, lit->dont_optimize_reason()); | 969 MaybeDisableOptimization(shared_info, lit->dont_optimize_reason()); |
| 962 shared_info->set_dont_crankshaft( | 970 shared_info->set_dont_crankshaft( |
| 963 shared_info->dont_crankshaft() || | 971 shared_info->dont_crankshaft() || |
| 964 (lit->flags() & AstProperties::kDontCrankshaft)); | 972 (lit->flags() & AstProperties::kDontCrankshaft)); |
| 965 } | 973 } |
| 966 return true; | 974 return true; |
| 967 } | 975 } |
| 968 | 976 |
| 969 | |
| 970 bool Compiler::Analyze(ParseInfo* info) { | |
| 971 DCHECK_NOT_NULL(info->literal()); | |
| 972 if (!Rewriter::Rewrite(info)) return false; | |
| 973 if (!Scope::Analyze(info)) return false; | |
| 974 if (!Renumber(info)) return false; | |
| 975 DCHECK_NOT_NULL(info->scope()); | |
| 976 return true; | |
| 977 } | |
| 978 | |
| 979 | |
| 980 bool Compiler::ParseAndAnalyze(ParseInfo* info) { | |
| 981 if (!Parser::ParseStatic(info)) return false; | |
| 982 return Compiler::Analyze(info); | |
| 983 } | |
| 984 | |
| 985 namespace { | |
| 986 | |
| 987 bool GetOptimizedCodeNow(CompilationInfo* info) { | 977 bool GetOptimizedCodeNow(CompilationInfo* info) { |
| 988 Isolate* isolate = info->isolate(); | 978 Isolate* isolate = info->isolate(); |
| 989 CanonicalHandleScope canonical(isolate); | 979 CanonicalHandleScope canonical(isolate); |
| 990 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate); | 980 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate); |
| 991 TRACE_EVENT0("v8", "V8.OptimizeCode"); | 981 TRACE_EVENT0("v8", "V8.OptimizeCode"); |
| 992 | 982 |
| 993 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; | 983 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; |
| 994 | 984 |
| 995 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate); | 985 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate); |
| 996 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); | 986 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1175 Handle<Code> opt_code; | 1165 Handle<Code> opt_code; |
| 1176 if (GetOptimizedCode(function, Compiler::NOT_CONCURRENT) | 1166 if (GetOptimizedCode(function, Compiler::NOT_CONCURRENT) |
| 1177 .ToHandle(&opt_code)) { | 1167 .ToHandle(&opt_code)) { |
| 1178 result = opt_code; | 1168 result = opt_code; |
| 1179 } | 1169 } |
| 1180 } | 1170 } |
| 1181 | 1171 |
| 1182 return result; | 1172 return result; |
| 1183 } | 1173 } |
| 1184 | 1174 |
| 1185 } // namespace | |
| 1186 | |
| 1187 bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) { | |
| 1188 if (function->is_compiled()) return true; | |
| 1189 MaybeHandle<Code> maybe_code = GetLazyCode(function); | |
| 1190 Handle<Code> code; | |
| 1191 if (!maybe_code.ToHandle(&code)) { | |
| 1192 if (flag == CLEAR_EXCEPTION) { | |
| 1193 function->GetIsolate()->clear_pending_exception(); | |
| 1194 } | |
| 1195 return false; | |
| 1196 } | |
| 1197 DCHECK(code->IsJavaScriptCode()); | |
| 1198 function->ReplaceCode(*code); | |
| 1199 DCHECK(function->is_compiled()); | |
| 1200 return true; | |
| 1201 } | |
| 1202 | |
| 1203 bool Compiler::CompileOptimized(Handle<JSFunction> function, | |
| 1204 ConcurrencyMode mode) { | |
| 1205 Handle<Code> code; | |
| 1206 if (GetOptimizedCode(function, mode).ToHandle(&code)) { | |
| 1207 // Optimization succeeded, return optimized code. | |
| 1208 function->ReplaceCode(*code); | |
| 1209 } else { | |
| 1210 // Optimization failed, get unoptimized code. | |
| 1211 Isolate* isolate = function->GetIsolate(); | |
| 1212 if (isolate->has_pending_exception()) { // Possible stack overflow. | |
| 1213 return false; | |
| 1214 } | |
| 1215 code = Handle<Code>(function->shared()->code(), isolate); | |
| 1216 if (code->kind() != Code::FUNCTION && | |
| 1217 code->kind() != Code::OPTIMIZED_FUNCTION) { | |
| 1218 if (!GetUnoptimizedCode(function).ToHandle(&code)) { | |
| 1219 return false; | |
| 1220 } | |
| 1221 } | |
| 1222 function->ReplaceCode(*code); | |
| 1223 } | |
| 1224 | |
| 1225 DCHECK(function->code()->kind() == Code::FUNCTION || | |
| 1226 function->code()->kind() == Code::OPTIMIZED_FUNCTION || | |
| 1227 (function->code()->is_interpreter_entry_trampoline() && | |
| 1228 function->shared()->HasBytecodeArray()) || | |
| 1229 function->IsInOptimizationQueue()); | |
| 1230 return true; | |
| 1231 } | |
| 1232 | |
| 1233 // TODO(turbofan): In the future, unoptimized code with deopt support could | |
| 1234 // be generated lazily once deopt is triggered. | |
| 1235 bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) { | |
| 1236 DCHECK_NOT_NULL(info->literal()); | |
| 1237 DCHECK(info->has_scope()); | |
| 1238 Handle<SharedFunctionInfo> shared = info->shared_info(); | |
| 1239 if (!shared->has_deoptimization_support()) { | |
| 1240 // TODO(titzer): just reuse the ParseInfo for the unoptimized compile. | |
| 1241 CompilationInfoWithZone unoptimized(info->closure()); | |
| 1242 // Note that we use the same AST that we will use for generating the | |
| 1243 // optimized code. | |
| 1244 ParseInfo* parse_info = unoptimized.parse_info(); | |
| 1245 parse_info->set_literal(info->literal()); | |
| 1246 parse_info->set_scope(info->scope()); | |
| 1247 parse_info->set_context(info->context()); | |
| 1248 unoptimized.EnableDeoptimizationSupport(); | |
| 1249 // If the current code has reloc info for serialization, also include | |
| 1250 // reloc info for serialization for the new code, so that deopt support | |
| 1251 // can be added without losing IC state. | |
| 1252 if (shared->code()->kind() == Code::FUNCTION && | |
| 1253 shared->code()->has_reloc_info_for_serialization()) { | |
| 1254 unoptimized.PrepareForSerializing(); | |
| 1255 } | |
| 1256 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false; | |
| 1257 | |
| 1258 shared->EnableDeoptimizationSupport(*unoptimized.code()); | |
| 1259 shared->set_feedback_vector(*unoptimized.feedback_vector()); | |
| 1260 | |
| 1261 info->MarkAsCompiled(); | |
| 1262 | |
| 1263 // The scope info might not have been set if a lazily compiled | |
| 1264 // function is inlined before being called for the first time. | |
| 1265 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) { | |
| 1266 Handle<ScopeInfo> target_scope_info = | |
| 1267 ScopeInfo::Create(info->isolate(), info->zone(), info->scope()); | |
| 1268 shared->set_scope_info(*target_scope_info); | |
| 1269 } | |
| 1270 | |
| 1271 // The existing unoptimized code was replaced with the new one. | |
| 1272 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized, shared); | |
| 1273 } | |
| 1274 return true; | |
| 1275 } | |
| 1276 | |
| 1277 | 1175 |
| 1278 bool CompileEvalForDebugging(Handle<JSFunction> function, | 1176 bool CompileEvalForDebugging(Handle<JSFunction> function, |
| 1279 Handle<SharedFunctionInfo> shared) { | 1177 Handle<SharedFunctionInfo> shared) { |
| 1280 Handle<Script> script(Script::cast(shared->script())); | 1178 Handle<Script> script(Script::cast(shared->script())); |
| 1281 Handle<Context> context(function->context()); | 1179 Handle<Context> context(function->context()); |
| 1282 | 1180 |
| 1283 Zone zone; | 1181 Zone zone; |
| 1284 ParseInfo parse_info(&zone, script); | 1182 ParseInfo parse_info(&zone, script); |
| 1285 CompilationInfo info(&parse_info); | 1183 CompilationInfo info(&parse_info); |
| 1286 Isolate* isolate = info.isolate(); | 1184 Isolate* isolate = info.isolate(); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1315 | 1213 |
| 1316 bool CompileForDebugging(CompilationInfo* info) { | 1214 bool CompileForDebugging(CompilationInfo* info) { |
| 1317 info->MarkAsDebug(); | 1215 info->MarkAsDebug(); |
| 1318 if (GetUnoptimizedCodeCommon(info).is_null()) { | 1216 if (GetUnoptimizedCodeCommon(info).is_null()) { |
| 1319 info->isolate()->clear_pending_exception(); | 1217 info->isolate()->clear_pending_exception(); |
| 1320 return false; | 1218 return false; |
| 1321 } | 1219 } |
| 1322 return true; | 1220 return true; |
| 1323 } | 1221 } |
| 1324 | 1222 |
| 1325 | 1223 inline bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) { |
| 1326 static inline bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) { | |
| 1327 return shared->is_toplevel() && shared->script()->IsScript() && | 1224 return shared->is_toplevel() && shared->script()->IsScript() && |
| 1328 Script::cast(shared->script())->compilation_type() == | 1225 Script::cast(shared->script())->compilation_type() == |
| 1329 Script::COMPILATION_TYPE_EVAL; | 1226 Script::COMPILATION_TYPE_EVAL; |
| 1330 } | 1227 } |
| 1331 | 1228 |
| 1332 | 1229 Handle<SharedFunctionInfo> NewSharedFunctionInfoForLiteral( |
| 1333 bool Compiler::CompileDebugCode(Handle<JSFunction> function) { | |
| 1334 Handle<SharedFunctionInfo> shared(function->shared()); | |
| 1335 if (IsEvalToplevel(shared)) { | |
| 1336 return CompileEvalForDebugging(function, shared); | |
| 1337 } else { | |
| 1338 CompilationInfoWithZone info(function); | |
| 1339 return CompileForDebugging(&info); | |
| 1340 } | |
| 1341 } | |
| 1342 | |
| 1343 | |
| 1344 bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) { | |
| 1345 DCHECK(shared->allows_lazy_compilation_without_context()); | |
| 1346 DCHECK(!IsEvalToplevel(shared)); | |
| 1347 Zone zone; | |
| 1348 ParseInfo parse_info(&zone, shared); | |
| 1349 CompilationInfo info(&parse_info); | |
| 1350 return CompileForDebugging(&info); | |
| 1351 } | |
| 1352 | |
| 1353 | |
| 1354 void Compiler::CompileForLiveEdit(Handle<Script> script) { | |
| 1355 // TODO(635): support extensions. | |
| 1356 Zone zone; | |
| 1357 ParseInfo parse_info(&zone, script); | |
| 1358 CompilationInfo info(&parse_info); | |
| 1359 PostponeInterruptsScope postpone(info.isolate()); | |
| 1360 VMState<COMPILER> state(info.isolate()); | |
| 1361 | |
| 1362 // Get rid of old list of shared function infos. | |
| 1363 info.MarkAsFirstCompile(); | |
| 1364 info.MarkAsDebug(); | |
| 1365 info.parse_info()->set_global(); | |
| 1366 if (!Parser::ParseStatic(info.parse_info())) return; | |
| 1367 | |
| 1368 LiveEditFunctionTracker tracker(info.isolate(), parse_info.literal()); | |
| 1369 if (!CompileUnoptimizedCode(&info)) return; | |
| 1370 if (info.has_shared_info()) { | |
| 1371 Handle<ScopeInfo> scope_info = | |
| 1372 ScopeInfo::Create(info.isolate(), info.zone(), info.scope()); | |
| 1373 info.shared_info()->set_scope_info(*scope_info); | |
| 1374 } | |
| 1375 tracker.RecordRootFunctionInfo(info.code()); | |
| 1376 } | |
| 1377 | |
| 1378 static Handle<SharedFunctionInfo> NewSharedFunctionInfoForLiteral( | |
| 1379 Isolate* isolate, FunctionLiteral* literal, Handle<Script> script) { | 1230 Isolate* isolate, FunctionLiteral* literal, Handle<Script> script) { |
| 1380 Handle<Code> code = isolate->builtins()->CompileLazy(); | 1231 Handle<Code> code = isolate->builtins()->CompileLazy(); |
| 1381 Handle<ScopeInfo> scope_info = handle(ScopeInfo::Empty(isolate)); | 1232 Handle<ScopeInfo> scope_info = handle(ScopeInfo::Empty(isolate)); |
| 1382 Handle<SharedFunctionInfo> result = isolate->factory()->NewSharedFunctionInfo( | 1233 Handle<SharedFunctionInfo> result = isolate->factory()->NewSharedFunctionInfo( |
| 1383 literal->name(), literal->materialized_literal_count(), literal->kind(), | 1234 literal->name(), literal->materialized_literal_count(), literal->kind(), |
| 1384 code, scope_info); | 1235 code, scope_info); |
| 1385 SharedFunctionInfo::InitFromFunctionLiteral(result, literal); | 1236 SharedFunctionInfo::InitFromFunctionLiteral(result, literal); |
| 1386 SharedFunctionInfo::SetScript(result, script); | 1237 SharedFunctionInfo::SetScript(result, script); |
| 1387 return result; | 1238 return result; |
| 1388 } | 1239 } |
| 1389 | 1240 |
| 1390 static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) { | 1241 Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) { |
| 1391 Isolate* isolate = info->isolate(); | 1242 Isolate* isolate = info->isolate(); |
| 1392 TimerEventScope<TimerEventCompileCode> timer(isolate); | 1243 TimerEventScope<TimerEventCompileCode> timer(isolate); |
| 1393 TRACE_EVENT0("v8", "V8.CompileCode"); | 1244 TRACE_EVENT0("v8", "V8.CompileCode"); |
| 1394 PostponeInterruptsScope postpone(isolate); | 1245 PostponeInterruptsScope postpone(isolate); |
| 1395 DCHECK(!isolate->native_context().is_null()); | 1246 DCHECK(!isolate->native_context().is_null()); |
| 1396 ParseInfo* parse_info = info->parse_info(); | 1247 ParseInfo* parse_info = info->parse_info(); |
| 1397 Handle<Script> script = parse_info->script(); | 1248 Handle<Script> script = parse_info->script(); |
| 1398 | 1249 |
| 1399 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile? | 1250 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile? |
| 1400 FixedArray* array = isolate->native_context()->embedder_data(); | 1251 FixedArray* array = isolate->native_context()->embedder_data(); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1493 | 1344 |
| 1494 if (!script.is_null()) | 1345 if (!script.is_null()) |
| 1495 script->set_compilation_state(Script::COMPILATION_STATE_COMPILED); | 1346 script->set_compilation_state(Script::COMPILATION_STATE_COMPILED); |
| 1496 | 1347 |
| 1497 live_edit_tracker.RecordFunctionInfo(result, lit, info->zone()); | 1348 live_edit_tracker.RecordFunctionInfo(result, lit, info->zone()); |
| 1498 } | 1349 } |
| 1499 | 1350 |
| 1500 return result; | 1351 return result; |
| 1501 } | 1352 } |
| 1502 | 1353 |
| 1354 } // namespace |
| 1355 |
| 1356 // ---------------------------------------------------------------------------- |
| 1357 // Implementation of Compiler |
| 1358 |
| 1359 bool Compiler::Analyze(ParseInfo* info) { |
| 1360 DCHECK_NOT_NULL(info->literal()); |
| 1361 if (!Rewriter::Rewrite(info)) return false; |
| 1362 if (!Scope::Analyze(info)) return false; |
| 1363 if (!Renumber(info)) return false; |
| 1364 DCHECK_NOT_NULL(info->scope()); |
| 1365 return true; |
| 1366 } |
| 1367 |
| 1368 bool Compiler::ParseAndAnalyze(ParseInfo* info) { |
| 1369 if (!Parser::ParseStatic(info)) return false; |
| 1370 return Compiler::Analyze(info); |
| 1371 } |
| 1372 |
| 1373 bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) { |
| 1374 if (function->is_compiled()) return true; |
| 1375 MaybeHandle<Code> maybe_code = GetLazyCode(function); |
| 1376 Handle<Code> code; |
| 1377 if (!maybe_code.ToHandle(&code)) { |
| 1378 if (flag == CLEAR_EXCEPTION) { |
| 1379 function->GetIsolate()->clear_pending_exception(); |
| 1380 } |
| 1381 return false; |
| 1382 } |
| 1383 DCHECK(code->IsJavaScriptCode()); |
| 1384 function->ReplaceCode(*code); |
| 1385 DCHECK(function->is_compiled()); |
| 1386 return true; |
| 1387 } |
| 1388 |
| 1389 bool Compiler::CompileOptimized(Handle<JSFunction> function, |
| 1390 ConcurrencyMode mode) { |
| 1391 Handle<Code> code; |
| 1392 if (GetOptimizedCode(function, mode).ToHandle(&code)) { |
| 1393 // Optimization succeeded, return optimized code. |
| 1394 function->ReplaceCode(*code); |
| 1395 } else { |
| 1396 // Optimization failed, get unoptimized code. |
| 1397 Isolate* isolate = function->GetIsolate(); |
| 1398 if (isolate->has_pending_exception()) { // Possible stack overflow. |
| 1399 return false; |
| 1400 } |
| 1401 code = Handle<Code>(function->shared()->code(), isolate); |
| 1402 if (code->kind() != Code::FUNCTION && |
| 1403 code->kind() != Code::OPTIMIZED_FUNCTION) { |
| 1404 if (!GetUnoptimizedCode(function).ToHandle(&code)) { |
| 1405 return false; |
| 1406 } |
| 1407 } |
| 1408 function->ReplaceCode(*code); |
| 1409 } |
| 1410 |
| 1411 DCHECK(function->code()->kind() == Code::FUNCTION || |
| 1412 function->code()->kind() == Code::OPTIMIZED_FUNCTION || |
| 1413 (function->code()->is_interpreter_entry_trampoline() && |
| 1414 function->shared()->HasBytecodeArray()) || |
| 1415 function->IsInOptimizationQueue()); |
| 1416 return true; |
| 1417 } |
| 1418 |
| 1419 bool Compiler::CompileDebugCode(Handle<JSFunction> function) { |
| 1420 Handle<SharedFunctionInfo> shared(function->shared()); |
| 1421 if (IsEvalToplevel(shared)) { |
| 1422 return CompileEvalForDebugging(function, shared); |
| 1423 } else { |
| 1424 CompilationInfoWithZone info(function); |
| 1425 return CompileForDebugging(&info); |
| 1426 } |
| 1427 } |
| 1428 |
| 1429 bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) { |
| 1430 DCHECK(shared->allows_lazy_compilation_without_context()); |
| 1431 DCHECK(!IsEvalToplevel(shared)); |
| 1432 Zone zone; |
| 1433 ParseInfo parse_info(&zone, shared); |
| 1434 CompilationInfo info(&parse_info); |
| 1435 return CompileForDebugging(&info); |
| 1436 } |
| 1437 |
| 1438 // TODO(turbofan): In the future, unoptimized code with deopt support could |
| 1439 // be generated lazily once deopt is triggered. |
| 1440 bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) { |
| 1441 DCHECK_NOT_NULL(info->literal()); |
| 1442 DCHECK(info->has_scope()); |
| 1443 Handle<SharedFunctionInfo> shared = info->shared_info(); |
| 1444 if (!shared->has_deoptimization_support()) { |
| 1445 // TODO(titzer): just reuse the ParseInfo for the unoptimized compile. |
| 1446 CompilationInfoWithZone unoptimized(info->closure()); |
| 1447 // Note that we use the same AST that we will use for generating the |
| 1448 // optimized code. |
| 1449 ParseInfo* parse_info = unoptimized.parse_info(); |
| 1450 parse_info->set_literal(info->literal()); |
| 1451 parse_info->set_scope(info->scope()); |
| 1452 parse_info->set_context(info->context()); |
| 1453 unoptimized.EnableDeoptimizationSupport(); |
| 1454 // If the current code has reloc info for serialization, also include |
| 1455 // reloc info for serialization for the new code, so that deopt support |
| 1456 // can be added without losing IC state. |
| 1457 if (shared->code()->kind() == Code::FUNCTION && |
| 1458 shared->code()->has_reloc_info_for_serialization()) { |
| 1459 unoptimized.PrepareForSerializing(); |
| 1460 } |
| 1461 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false; |
| 1462 |
| 1463 shared->EnableDeoptimizationSupport(*unoptimized.code()); |
| 1464 shared->set_feedback_vector(*unoptimized.feedback_vector()); |
| 1465 |
| 1466 info->MarkAsCompiled(); |
| 1467 |
| 1468 // The scope info might not have been set if a lazily compiled |
| 1469 // function is inlined before being called for the first time. |
| 1470 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) { |
| 1471 Handle<ScopeInfo> target_scope_info = |
| 1472 ScopeInfo::Create(info->isolate(), info->zone(), info->scope()); |
| 1473 shared->set_scope_info(*target_scope_info); |
| 1474 } |
| 1475 |
| 1476 // The existing unoptimized code was replaced with the new one. |
| 1477 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized, shared); |
| 1478 } |
| 1479 return true; |
| 1480 } |
| 1481 |
| 1482 void Compiler::CompileForLiveEdit(Handle<Script> script) { |
| 1483 // TODO(635): support extensions. |
| 1484 Zone zone; |
| 1485 ParseInfo parse_info(&zone, script); |
| 1486 CompilationInfo info(&parse_info); |
| 1487 PostponeInterruptsScope postpone(info.isolate()); |
| 1488 VMState<COMPILER> state(info.isolate()); |
| 1489 |
| 1490 // Get rid of old list of shared function infos. |
| 1491 info.MarkAsFirstCompile(); |
| 1492 info.MarkAsDebug(); |
| 1493 info.parse_info()->set_global(); |
| 1494 if (!Parser::ParseStatic(info.parse_info())) return; |
| 1495 |
| 1496 LiveEditFunctionTracker tracker(info.isolate(), parse_info.literal()); |
| 1497 if (!CompileUnoptimizedCode(&info)) return; |
| 1498 if (info.has_shared_info()) { |
| 1499 Handle<ScopeInfo> scope_info = |
| 1500 ScopeInfo::Create(info.isolate(), info.zone(), info.scope()); |
| 1501 info.shared_info()->set_scope_info(*scope_info); |
| 1502 } |
| 1503 tracker.RecordRootFunctionInfo(info.code()); |
| 1504 } |
| 1503 | 1505 |
| 1504 MaybeHandle<JSFunction> Compiler::GetFunctionFromEval( | 1506 MaybeHandle<JSFunction> Compiler::GetFunctionFromEval( |
| 1505 Handle<String> source, Handle<SharedFunctionInfo> outer_info, | 1507 Handle<String> source, Handle<SharedFunctionInfo> outer_info, |
| 1506 Handle<Context> context, LanguageMode language_mode, | 1508 Handle<Context> context, LanguageMode language_mode, |
| 1507 ParseRestriction restriction, int line_offset, int column_offset, | 1509 ParseRestriction restriction, int line_offset, int column_offset, |
| 1508 Handle<Object> script_name, ScriptOriginOptions options) { | 1510 Handle<Object> script_name, ScriptOriginOptions options) { |
| 1509 Isolate* isolate = source->GetIsolate(); | 1511 Isolate* isolate = source->GetIsolate(); |
| 1510 int source_length = source->length(); | 1512 int source_length = source->length(); |
| 1511 isolate->counters()->total_eval_size()->Increment(source_length); | 1513 isolate->counters()->total_eval_size()->Increment(source_length); |
| 1512 isolate->counters()->total_compile_size()->Increment(source_length); | 1514 isolate->counters()->total_compile_size()->Increment(source_length); |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1946 | 1948 |
| 1947 // Cache context-specific literals. | 1949 // Cache context-specific literals. |
| 1948 MaybeHandle<Code> code; | 1950 MaybeHandle<Code> code; |
| 1949 if (cached.code != nullptr) code = handle(cached.code); | 1951 if (cached.code != nullptr) code = handle(cached.code); |
| 1950 Handle<Context> native_context(function->context()->native_context()); | 1952 Handle<Context> native_context(function->context()->native_context()); |
| 1951 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, | 1953 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, |
| 1952 literals, BailoutId::None()); | 1954 literals, BailoutId::None()); |
| 1953 } | 1955 } |
| 1954 } | 1956 } |
| 1955 | 1957 |
| 1956 #if DEBUG | |
| 1957 void CompilationInfo::PrintAstForTesting() { | |
| 1958 PrintF("--- Source from AST ---\n%s\n", | |
| 1959 PrettyPrinter(isolate()).PrintProgram(literal())); | |
| 1960 } | |
| 1961 #endif | |
| 1962 | |
| 1963 } // namespace internal | 1958 } // namespace internal |
| 1964 } // namespace v8 | 1959 } // namespace v8 |
| OLD | NEW |