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 |