| 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 #include <memory> | 8 #include <memory> |
| 9 | 9 |
| 10 #include "src/asmjs/asm-js.h" | 10 #include "src/asmjs/asm-js.h" |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 // Local helper methods that make up the compilation pipeline. | 250 // Local helper methods that make up the compilation pipeline. |
| 251 | 251 |
| 252 namespace { | 252 namespace { |
| 253 | 253 |
| 254 bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) { | 254 bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) { |
| 255 return shared->is_toplevel() && shared->script()->IsScript() && | 255 return shared->is_toplevel() && shared->script()->IsScript() && |
| 256 Script::cast(shared->script())->compilation_type() == | 256 Script::cast(shared->script())->compilation_type() == |
| 257 Script::COMPILATION_TYPE_EVAL; | 257 Script::COMPILATION_TYPE_EVAL; |
| 258 } | 258 } |
| 259 | 259 |
| 260 bool Parse(ParseInfo* info) { |
| 261 // Create a canonical handle scope if compiling ignition bytecode. This is |
| 262 // required by the constant array builder to de-duplicate objects without |
| 263 // dereferencing handles. |
| 264 std::unique_ptr<CanonicalHandleScope> canonical; |
| 265 if (FLAG_ignition) canonical.reset(new CanonicalHandleScope(info->isolate())); |
| 266 |
| 267 return Parser::ParseStatic(info); |
| 268 } |
| 269 |
| 260 void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag, | 270 void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag, |
| 261 CompilationInfo* info) { | 271 CompilationInfo* info) { |
| 262 // Log the code generation. If source information is available include | 272 // Log the code generation. If source information is available include |
| 263 // script name and line number. Check explicitly whether logging is | 273 // script name and line number. Check explicitly whether logging is |
| 264 // enabled as finding the line number is not free. | 274 // enabled as finding the line number is not free. |
| 265 if (info->isolate()->logger()->is_logging_code_events() || | 275 if (info->isolate()->logger()->is_logging_code_events() || |
| 266 info->isolate()->is_profiling()) { | 276 info->isolate()->is_profiling()) { |
| 267 Handle<SharedFunctionInfo> shared = info->shared_info(); | 277 Handle<SharedFunctionInfo> shared = info->shared_info(); |
| 268 Handle<Script> script = info->parse_info()->script(); | 278 Handle<Script> script = info->parse_info()->script(); |
| 269 Handle<AbstractCode> abstract_code = | 279 Handle<AbstractCode> abstract_code = |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 InstallSharedCompilationResult(info, shared); | 424 InstallSharedCompilationResult(info, shared); |
| 415 | 425 |
| 416 // Record the function compilation event. | 426 // Record the function compilation event. |
| 417 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); | 427 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); |
| 418 } | 428 } |
| 419 | 429 |
| 420 MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode(CompilationInfo* info) { | 430 MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode(CompilationInfo* info) { |
| 421 VMState<COMPILER> state(info->isolate()); | 431 VMState<COMPILER> state(info->isolate()); |
| 422 PostponeInterruptsScope postpone(info->isolate()); | 432 PostponeInterruptsScope postpone(info->isolate()); |
| 423 | 433 |
| 424 // Create a canonical handle scope before internalizing parsed values if | |
| 425 // compiling bytecode. This is required for off-thread bytecode generation. | |
| 426 std::unique_ptr<CanonicalHandleScope> canonical; | |
| 427 if (FLAG_ignition) canonical.reset(new CanonicalHandleScope(info->isolate())); | |
| 428 | |
| 429 // Parse and update CompilationInfo with the results. | 434 // Parse and update CompilationInfo with the results. |
| 430 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>(); | 435 if (!Parse(info->parse_info())) return MaybeHandle<Code>(); |
| 431 DCHECK_EQ(info->shared_info()->language_mode(), | 436 DCHECK_EQ(info->shared_info()->language_mode(), |
| 432 info->literal()->language_mode()); | 437 info->literal()->language_mode()); |
| 433 | 438 |
| 434 // Compile either unoptimized code or bytecode for the interpreter. | 439 // Compile either unoptimized code or bytecode for the interpreter. |
| 435 if (!CompileUnoptimizedCode(info)) return MaybeHandle<Code>(); | 440 if (!CompileUnoptimizedCode(info)) return MaybeHandle<Code>(); |
| 436 | 441 |
| 437 InstallUnoptimizedCode(info); | 442 InstallUnoptimizedCode(info); |
| 438 | 443 |
| 439 return info->code(); | 444 return info->code(); |
| 440 } | 445 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 494 if (FLAG_turbo_cache_shared_code && code->is_turbofanned() && | 499 if (FLAG_turbo_cache_shared_code && code->is_turbofanned() && |
| 495 !info->is_native_context_specializing()) { | 500 !info->is_native_context_specializing()) { |
| 496 DCHECK(!info->is_function_context_specializing()); | 501 DCHECK(!info->is_function_context_specializing()); |
| 497 DCHECK(info->osr_ast_id().IsNone()); | 502 DCHECK(info->osr_ast_id().IsNone()); |
| 498 Handle<SharedFunctionInfo> shared(function->shared()); | 503 Handle<SharedFunctionInfo> shared(function->shared()); |
| 499 SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap(shared, code); | 504 SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap(shared, code); |
| 500 } | 505 } |
| 501 } | 506 } |
| 502 | 507 |
| 503 bool Renumber(ParseInfo* parse_info) { | 508 bool Renumber(ParseInfo* parse_info) { |
| 509 // Create a canonical handle scope if compiling ignition bytecode. This is |
| 510 // required by the constant array builder to de-duplicate objects without |
| 511 // dereferencing handles. |
| 512 std::unique_ptr<CanonicalHandleScope> canonical; |
| 513 if (FLAG_ignition) { |
| 514 canonical.reset(new CanonicalHandleScope(parse_info->isolate())); |
| 515 } |
| 516 |
| 504 if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(), | 517 if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(), |
| 505 parse_info->literal())) { | 518 parse_info->literal())) { |
| 506 return false; | 519 return false; |
| 507 } | 520 } |
| 508 Handle<SharedFunctionInfo> shared_info = parse_info->shared_info(); | 521 Handle<SharedFunctionInfo> shared_info = parse_info->shared_info(); |
| 509 if (!shared_info.is_null()) { | 522 if (!shared_info.is_null()) { |
| 510 FunctionLiteral* lit = parse_info->literal(); | 523 FunctionLiteral* lit = parse_info->literal(); |
| 511 shared_info->set_ast_node_count(lit->ast_node_count()); | 524 shared_info->set_ast_node_count(lit->ast_node_count()); |
| 512 if (lit->dont_optimize_reason() != kNoReason) { | 525 if (lit->dont_optimize_reason() != kNoReason) { |
| 513 shared_info->DisableOptimization(lit->dont_optimize_reason()); | 526 shared_info->DisableOptimization(lit->dont_optimize_reason()); |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 917 } | 930 } |
| 918 } | 931 } |
| 919 | 932 |
| 920 if (FLAG_trace_opt) { | 933 if (FLAG_trace_opt) { |
| 921 OFStream os(stdout); | 934 OFStream os(stdout); |
| 922 os << "[switching method " << Brief(*function) << " to baseline code]" | 935 os << "[switching method " << Brief(*function) << " to baseline code]" |
| 923 << std::endl; | 936 << std::endl; |
| 924 } | 937 } |
| 925 | 938 |
| 926 // Parse and update CompilationInfo with the results. | 939 // Parse and update CompilationInfo with the results. |
| 927 if (!Parser::ParseStatic(info.parse_info())) return MaybeHandle<Code>(); | 940 if (!Parse(info.parse_info())) return MaybeHandle<Code>(); |
| 928 Handle<SharedFunctionInfo> shared = info.shared_info(); | 941 Handle<SharedFunctionInfo> shared = info.shared_info(); |
| 929 DCHECK_EQ(shared->language_mode(), info.literal()->language_mode()); | 942 DCHECK_EQ(shared->language_mode(), info.literal()->language_mode()); |
| 930 | 943 |
| 931 // Compile baseline code using the full code generator. | 944 // Compile baseline code using the full code generator. |
| 932 if (!Compiler::Analyze(info.parse_info()) || | 945 if (!Compiler::Analyze(info.parse_info()) || |
| 933 !FullCodeGenerator::MakeCode(&info)) { | 946 !FullCodeGenerator::MakeCode(&info)) { |
| 934 if (!isolate->has_pending_exception()) isolate->StackOverflow(); | 947 if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
| 935 return MaybeHandle<Code>(); | 948 return MaybeHandle<Code>(); |
| 936 } | 949 } |
| 937 | 950 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1020 Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) { | 1033 Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) { |
| 1021 Isolate* isolate = info->isolate(); | 1034 Isolate* isolate = info->isolate(); |
| 1022 TimerEventScope<TimerEventCompileCode> timer(isolate); | 1035 TimerEventScope<TimerEventCompileCode> timer(isolate); |
| 1023 RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::CompileCode); | 1036 RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::CompileCode); |
| 1024 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode"); | 1037 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode"); |
| 1025 PostponeInterruptsScope postpone(isolate); | 1038 PostponeInterruptsScope postpone(isolate); |
| 1026 DCHECK(!isolate->native_context().is_null()); | 1039 DCHECK(!isolate->native_context().is_null()); |
| 1027 ParseInfo* parse_info = info->parse_info(); | 1040 ParseInfo* parse_info = info->parse_info(); |
| 1028 Handle<Script> script = parse_info->script(); | 1041 Handle<Script> script = parse_info->script(); |
| 1029 | 1042 |
| 1030 // Create a canonical handle scope before internalizing parsed values if | |
| 1031 // compiling bytecode. This is required for off-thread bytecode generation. | |
| 1032 std::unique_ptr<CanonicalHandleScope> canonical; | |
| 1033 if (FLAG_ignition) canonical.reset(new CanonicalHandleScope(isolate)); | |
| 1034 | |
| 1035 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile? | 1043 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile? |
| 1036 FixedArray* array = isolate->native_context()->embedder_data(); | 1044 FixedArray* array = isolate->native_context()->embedder_data(); |
| 1037 script->set_context_data(array->get(v8::Context::kDebugIdIndex)); | 1045 script->set_context_data(array->get(v8::Context::kDebugIdIndex)); |
| 1038 | 1046 |
| 1039 isolate->debug()->OnBeforeCompile(script); | 1047 isolate->debug()->OnBeforeCompile(script); |
| 1040 | 1048 |
| 1041 DCHECK(parse_info->is_eval() || parse_info->is_global() || | 1049 DCHECK(parse_info->is_eval() || parse_info->is_global() || |
| 1042 parse_info->is_module()); | 1050 parse_info->is_module()); |
| 1043 | 1051 |
| 1044 parse_info->set_toplevel(); | 1052 parse_info->set_toplevel(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1068 (options == ScriptCompiler::kProduceParserCache || | 1076 (options == ScriptCompiler::kProduceParserCache || |
| 1069 options == ScriptCompiler::kConsumeParserCache)) { | 1077 options == ScriptCompiler::kConsumeParserCache)) { |
| 1070 // We are going to parse eagerly, but we either 1) have cached data | 1078 // We are going to parse eagerly, but we either 1) have cached data |
| 1071 // produced by lazy parsing or 2) are asked to generate cached data. | 1079 // produced by lazy parsing or 2) are asked to generate cached data. |
| 1072 // Eager parsing cannot benefit from cached data, and producing cached | 1080 // Eager parsing cannot benefit from cached data, and producing cached |
| 1073 // data while parsing eagerly is not implemented. | 1081 // data while parsing eagerly is not implemented. |
| 1074 parse_info->set_cached_data(nullptr); | 1082 parse_info->set_cached_data(nullptr); |
| 1075 parse_info->set_compile_options(ScriptCompiler::kNoCompileOptions); | 1083 parse_info->set_compile_options(ScriptCompiler::kNoCompileOptions); |
| 1076 } | 1084 } |
| 1077 | 1085 |
| 1078 if (!Parser::ParseStatic(parse_info)) { | 1086 if (!Parse(parse_info)) { |
| 1079 return Handle<SharedFunctionInfo>::null(); | 1087 return Handle<SharedFunctionInfo>::null(); |
| 1080 } | 1088 } |
| 1081 } | 1089 } |
| 1082 | 1090 |
| 1083 DCHECK(!info->is_debug() || !parse_info->allow_lazy_parsing()); | 1091 DCHECK(!info->is_debug() || !parse_info->allow_lazy_parsing()); |
| 1084 | 1092 |
| 1085 FunctionLiteral* lit = parse_info->literal(); | 1093 FunctionLiteral* lit = parse_info->literal(); |
| 1086 | 1094 |
| 1087 // Measure how long it takes to do the compilation; only take the | 1095 // Measure how long it takes to do the compilation; only take the |
| 1088 // rest of the function into account to avoid overlap with the | 1096 // rest of the function into account to avoid overlap with the |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1145 bool Compiler::Analyze(ParseInfo* info) { | 1153 bool Compiler::Analyze(ParseInfo* info) { |
| 1146 DCHECK_NOT_NULL(info->literal()); | 1154 DCHECK_NOT_NULL(info->literal()); |
| 1147 if (!Rewriter::Rewrite(info)) return false; | 1155 if (!Rewriter::Rewrite(info)) return false; |
| 1148 DeclarationScope::Analyze(info, AnalyzeMode::kRegular); | 1156 DeclarationScope::Analyze(info, AnalyzeMode::kRegular); |
| 1149 if (!Renumber(info)) return false; | 1157 if (!Renumber(info)) return false; |
| 1150 DCHECK_NOT_NULL(info->scope()); | 1158 DCHECK_NOT_NULL(info->scope()); |
| 1151 return true; | 1159 return true; |
| 1152 } | 1160 } |
| 1153 | 1161 |
| 1154 bool Compiler::ParseAndAnalyze(ParseInfo* info) { | 1162 bool Compiler::ParseAndAnalyze(ParseInfo* info) { |
| 1155 if (!Parser::ParseStatic(info)) return false; | 1163 if (!Parse(info)) return false; |
| 1156 if (!Compiler::Analyze(info)) return false; | 1164 if (!Compiler::Analyze(info)) return false; |
| 1157 DCHECK_NOT_NULL(info->literal()); | 1165 DCHECK_NOT_NULL(info->literal()); |
| 1158 DCHECK_NOT_NULL(info->scope()); | 1166 DCHECK_NOT_NULL(info->scope()); |
| 1159 return true; | 1167 return true; |
| 1160 } | 1168 } |
| 1161 | 1169 |
| 1162 bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) { | 1170 bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) { |
| 1163 if (function->is_compiled()) return true; | 1171 if (function->is_compiled()) return true; |
| 1164 Isolate* isolate = function->GetIsolate(); | 1172 Isolate* isolate = function->GetIsolate(); |
| 1165 DCHECK(AllowCompilation::IsAllowed(isolate)); | 1173 DCHECK(AllowCompilation::IsAllowed(isolate)); |
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1767 | 1775 |
| 1768 // Consider compiling eagerly when compiling bytecode for Ignition. | 1776 // Consider compiling eagerly when compiling bytecode for Ignition. |
| 1769 lazy &= | 1777 lazy &= |
| 1770 !(FLAG_ignition && FLAG_ignition_eager && !isolate->serializer_enabled()); | 1778 !(FLAG_ignition && FLAG_ignition_eager && !isolate->serializer_enabled()); |
| 1771 | 1779 |
| 1772 // Generate code | 1780 // Generate code |
| 1773 TimerEventScope<TimerEventCompileCode> timer(isolate); | 1781 TimerEventScope<TimerEventCompileCode> timer(isolate); |
| 1774 RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::CompileCode); | 1782 RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::CompileCode); |
| 1775 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode"); | 1783 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode"); |
| 1776 | 1784 |
| 1777 // Create a canonical handle scope if compiling ignition bytecode. This is | |
| 1778 // required by the constant array builder to de-duplicate common objects | |
| 1779 // without dereferencing handles. | |
| 1780 std::unique_ptr<CanonicalHandleScope> canonical; | |
| 1781 if (FLAG_ignition) canonical.reset(new CanonicalHandleScope(info.isolate())); | |
| 1782 | |
| 1783 if (lazy) { | 1785 if (lazy) { |
| 1784 info.SetCode(isolate->builtins()->CompileLazy()); | 1786 info.SetCode(isolate->builtins()->CompileLazy()); |
| 1785 } else if (Renumber(info.parse_info()) && GenerateUnoptimizedCode(&info)) { | 1787 } else if (Renumber(info.parse_info()) && GenerateUnoptimizedCode(&info)) { |
| 1786 // Code generation will ensure that the feedback vector is present and | 1788 // Code generation will ensure that the feedback vector is present and |
| 1787 // appropriately sized. | 1789 // appropriately sized. |
| 1788 DCHECK(!info.code().is_null()); | 1790 DCHECK(!info.code().is_null()); |
| 1789 if (literal->should_eager_compile() && | 1791 if (literal->should_eager_compile() && |
| 1790 literal->should_be_used_once_hint()) { | 1792 literal->should_be_used_once_hint()) { |
| 1791 info.code()->MarkToBeExecutedOnce(isolate); | 1793 info.code()->MarkToBeExecutedOnce(isolate); |
| 1792 } | 1794 } |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1889 DCHECK(shared->is_compiled()); | 1891 DCHECK(shared->is_compiled()); |
| 1890 function->set_literals(cached.literals); | 1892 function->set_literals(cached.literals); |
| 1891 } else if (shared->is_compiled()) { | 1893 } else if (shared->is_compiled()) { |
| 1892 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. | 1894 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. |
| 1893 JSFunction::EnsureLiterals(function); | 1895 JSFunction::EnsureLiterals(function); |
| 1894 } | 1896 } |
| 1895 } | 1897 } |
| 1896 | 1898 |
| 1897 } // namespace internal | 1899 } // namespace internal |
| 1898 } // namespace v8 | 1900 } // namespace v8 |
| OLD | NEW |