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 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
398 String* script_name = script->name()->IsString() | 398 String* script_name = script->name()->IsString() |
399 ? String::cast(script->name()) | 399 ? String::cast(script->name()) |
400 : info->isolate()->heap()->empty_string(); | 400 : info->isolate()->heap()->empty_string(); |
401 Logger::LogEventsAndTags log_tag = Logger::ToNativeByScript(tag, *script); | 401 Logger::LogEventsAndTags log_tag = Logger::ToNativeByScript(tag, *script); |
402 PROFILE(info->isolate(), | 402 PROFILE(info->isolate(), |
403 CodeCreateEvent(log_tag, *abstract_code, *shared, info, script_name, | 403 CodeCreateEvent(log_tag, *abstract_code, *shared, info, script_name, |
404 line_num, column_num)); | 404 line_num, column_num)); |
405 } | 405 } |
406 } | 406 } |
407 | 407 |
408 void EnsureFeedbackVector(CompilationInfo* info) { | 408 void EnsureFeedbackMetadata(CompilationInfo* info) { |
409 DCHECK(info->has_shared_info()); | 409 DCHECK(info->has_shared_info()); |
410 | 410 |
411 // If no type feedback vector exists, we create one now. At this point the | 411 // If no type feedback metadata exists, we create it now. At this point the |
412 // AstNumbering pass has already run. Note the snapshot can contain outdated | 412 // AstNumbering pass has already run. Note the snapshot can contain outdated |
413 // vectors for a different configuration, hence we also recreate a new vector | 413 // vectors for a different configuration, hence we also recreate a new vector |
414 // when the function is not compiled (i.e. no code was serialized). | 414 // when the function is not compiled (i.e. no code was serialized). |
415 if (info->shared_info()->feedback_vector()->is_empty() || | 415 |
416 // TODO(mvstanton): reintroduce is_empty() predicate to feedback_metadata(). | |
417 if (info->shared_info()->feedback_metadata()->length() == 0 || | |
416 !info->shared_info()->is_compiled()) { | 418 !info->shared_info()->is_compiled()) { |
417 Handle<TypeFeedbackMetadata> feedback_metadata = TypeFeedbackMetadata::New( | 419 Handle<TypeFeedbackMetadata> feedback_metadata = TypeFeedbackMetadata::New( |
418 info->isolate(), info->literal()->feedback_vector_spec()); | 420 info->isolate(), info->literal()->feedback_vector_spec()); |
419 Handle<TypeFeedbackVector> feedback_vector = | 421 info->shared_info()->set_feedback_metadata(*feedback_metadata); |
420 TypeFeedbackVector::New(info->isolate(), feedback_metadata); | |
421 info->shared_info()->set_feedback_vector(*feedback_vector); | |
422 } | 422 } |
423 | 423 |
424 // It's very important that recompiles do not alter the structure of the type | 424 // It's very important that recompiles do not alter the structure of the type |
425 // feedback vector. Verify that the structure fits the function literal. | 425 // feedback vector. Verify that the structure fits the function literal. |
426 CHECK(!info->shared_info()->feedback_vector()->metadata()->SpecDiffersFrom( | 426 CHECK(!info->shared_info()->feedback_metadata()->SpecDiffersFrom( |
427 info->literal()->feedback_vector_spec())); | 427 info->literal()->feedback_vector_spec())); |
428 } | 428 } |
429 | 429 |
430 bool UseIgnition(CompilationInfo* info) { | 430 bool UseIgnition(CompilationInfo* info) { |
431 if (info->is_debug()) return false; | 431 if (info->is_debug()) return false; |
432 if (info->shared_info()->is_generator() && !FLAG_ignition_generators) { | 432 if (info->shared_info()->is_generator() && !FLAG_ignition_generators) { |
433 return false; | 433 return false; |
434 } | 434 } |
435 | 435 |
436 // Checks whether top level functions should be passed by the filter. | 436 // Checks whether top level functions should be passed by the filter. |
(...skipping 19 matching lines...) Expand all Loading... | |
456 size += code->CodeSize(); | 456 size += code->CodeSize(); |
457 size += code->relocation_info()->Size(); | 457 size += code->relocation_info()->Size(); |
458 size += code->deoptimization_data()->Size(); | 458 size += code->deoptimization_data()->Size(); |
459 size += code->handler_table()->Size(); | 459 size += code->handler_table()->Size(); |
460 } | 460 } |
461 return size; | 461 return size; |
462 } | 462 } |
463 | 463 |
464 bool GenerateUnoptimizedCode(CompilationInfo* info) { | 464 bool GenerateUnoptimizedCode(CompilationInfo* info) { |
465 bool success; | 465 bool success; |
466 EnsureFeedbackVector(info); | 466 EnsureFeedbackMetadata(info); |
467 if (FLAG_ignition && UseIgnition(info)) { | 467 if (FLAG_ignition && UseIgnition(info)) { |
468 success = interpreter::Interpreter::MakeBytecode(info); | 468 success = interpreter::Interpreter::MakeBytecode(info); |
469 } else { | 469 } else { |
470 success = FullCodeGenerator::MakeCode(info); | 470 success = FullCodeGenerator::MakeCode(info); |
471 } | 471 } |
472 if (success) { | 472 if (success) { |
473 Isolate* isolate = info->isolate(); | 473 Isolate* isolate = info->isolate(); |
474 Counters* counters = isolate->counters(); | 474 Counters* counters = isolate->counters(); |
475 // TODO(4280): Rename counters from "baseline" to "unoptimized" eventually. | 475 // TODO(4280): Rename counters from "baseline" to "unoptimized" eventually. |
476 counters->total_baseline_code_size()->Increment(CodeAndMetadataSize(info)); | 476 counters->total_baseline_code_size()->Increment(CodeAndMetadataSize(info)); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
509 } | 509 } |
510 } | 510 } |
511 | 511 |
512 MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode(CompilationInfo* info) { | 512 MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode(CompilationInfo* info) { |
513 VMState<COMPILER> state(info->isolate()); | 513 VMState<COMPILER> state(info->isolate()); |
514 PostponeInterruptsScope postpone(info->isolate()); | 514 PostponeInterruptsScope postpone(info->isolate()); |
515 | 515 |
516 // Parse and update CompilationInfo with the results. | 516 // Parse and update CompilationInfo with the results. |
517 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>(); | 517 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>(); |
518 Handle<SharedFunctionInfo> shared = info->shared_info(); | 518 Handle<SharedFunctionInfo> shared = info->shared_info(); |
519 DCHECK_EQ(shared->language_mode(), info->literal()->language_mode()); | 519 |
520 // TODO(mvstanton): can I eliminate this? MStarzinger got rid of this | |
521 // boilerplate stuff before. | |
522 FunctionLiteral* lit = info->literal(); | |
523 DCHECK_EQ(shared->language_mode(), lit->language_mode()); | |
524 shared->set_num_literals(lit->materialized_literal_count()); | |
Michael Starzinger
2016/05/10 13:47:20
Depending on who computes the literals count for a
mvstanton
2016/05/24 16:31:49
Happily, I could eliminate this piece completely (
| |
520 | 525 |
521 // Compile either unoptimized code or bytecode for the interpreter. | 526 // Compile either unoptimized code or bytecode for the interpreter. |
522 if (!CompileUnoptimizedCode(info)) return MaybeHandle<Code>(); | 527 if (!CompileUnoptimizedCode(info)) return MaybeHandle<Code>(); |
523 | 528 |
524 // Update the shared function info with the scope info. | 529 // Update the shared function info with the scope info. |
525 InstallSharedScopeInfo(info, shared); | 530 InstallSharedScopeInfo(info, shared); |
526 | 531 |
527 // Install compilation result on the shared function info | 532 // Install compilation result on the shared function info |
528 InstallSharedCompilationResult(info, shared); | 533 InstallSharedCompilationResult(info, shared); |
529 | 534 |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
627 | 632 |
628 bool GetOptimizedCodeNow(CompilationJob* job) { | 633 bool GetOptimizedCodeNow(CompilationJob* job) { |
629 CompilationInfo* info = job->info(); | 634 CompilationInfo* info = job->info(); |
630 Isolate* isolate = info->isolate(); | 635 Isolate* isolate = info->isolate(); |
631 | 636 |
632 // Parsing is not required when optimizing from existing bytecode. | 637 // Parsing is not required when optimizing from existing bytecode. |
633 if (!info->is_optimizing_from_bytecode()) { | 638 if (!info->is_optimizing_from_bytecode()) { |
634 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; | 639 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; |
635 } | 640 } |
636 | 641 |
642 EnsureFeedbackMetadata(info); | |
643 JSFunction::EnsureLiterals(info->closure()); | |
644 | |
637 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate); | 645 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate); |
638 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); | 646 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); |
639 | 647 |
640 if (job->CreateGraph() != CompilationJob::SUCCEEDED || | 648 if (job->CreateGraph() != CompilationJob::SUCCEEDED || |
641 job->OptimizeGraph() != CompilationJob::SUCCEEDED || | 649 job->OptimizeGraph() != CompilationJob::SUCCEEDED || |
642 job->GenerateCode() != CompilationJob::SUCCEEDED) { | 650 job->GenerateCode() != CompilationJob::SUCCEEDED) { |
643 if (FLAG_trace_opt) { | 651 if (FLAG_trace_opt) { |
644 PrintF("[aborted optimizing "); | 652 PrintF("[aborted optimizing "); |
645 info->closure()->ShortPrint(); | 653 info->closure()->ShortPrint(); |
646 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); | 654 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); |
(...skipping 24 matching lines...) Expand all Loading... | |
671 | 679 |
672 // All handles below this point will be allocated in a deferred handle scope | 680 // All handles below this point will be allocated in a deferred handle scope |
673 // that is detached and handed off to the background thread when we return. | 681 // that is detached and handed off to the background thread when we return. |
674 CompilationHandleScope handle_scope(info); | 682 CompilationHandleScope handle_scope(info); |
675 | 683 |
676 // Parsing is not required when optimizing from existing bytecode. | 684 // Parsing is not required when optimizing from existing bytecode. |
677 if (!info->is_optimizing_from_bytecode()) { | 685 if (!info->is_optimizing_from_bytecode()) { |
678 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; | 686 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; |
679 } | 687 } |
680 | 688 |
689 JSFunction::EnsureLiterals(info->closure()); | |
690 | |
681 // Reopen handles in the new CompilationHandleScope. | 691 // Reopen handles in the new CompilationHandleScope. |
682 info->ReopenHandlesInNewHandleScope(); | 692 info->ReopenHandlesInNewHandleScope(); |
683 info->parse_info()->ReopenHandlesInNewHandleScope(); | 693 info->parse_info()->ReopenHandlesInNewHandleScope(); |
684 | 694 |
685 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); | 695 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); |
686 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); | 696 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); |
687 | 697 |
688 if (job->CreateGraph() != CompilationJob::SUCCEEDED) return false; | 698 if (job->CreateGraph() != CompilationJob::SUCCEEDED) return false; |
689 isolate->optimizing_compile_dispatcher()->QueueForOptimization(job); | 699 isolate->optimizing_compile_dispatcher()->QueueForOptimization(job); |
690 | 700 |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1116 Handle<Code> code; | 1126 Handle<Code> code; |
1117 if (!GetLazyCode(function).ToHandle(&code)) { | 1127 if (!GetLazyCode(function).ToHandle(&code)) { |
1118 if (flag == CLEAR_EXCEPTION) { | 1128 if (flag == CLEAR_EXCEPTION) { |
1119 isolate->clear_pending_exception(); | 1129 isolate->clear_pending_exception(); |
1120 } | 1130 } |
1121 return false; | 1131 return false; |
1122 } | 1132 } |
1123 | 1133 |
1124 // Install code on closure. | 1134 // Install code on closure. |
1125 function->ReplaceCode(*code); | 1135 function->ReplaceCode(*code); |
1136 JSFunction::EnsureLiterals(function); | |
1126 | 1137 |
1127 // Check postconditions on success. | 1138 // Check postconditions on success. |
1128 DCHECK(!isolate->has_pending_exception()); | 1139 DCHECK(!isolate->has_pending_exception()); |
1129 DCHECK(function->shared()->is_compiled()); | 1140 DCHECK(function->shared()->is_compiled()); |
1130 DCHECK(function->is_compiled()); | 1141 DCHECK(function->is_compiled()); |
1131 return true; | 1142 return true; |
1132 } | 1143 } |
1133 | 1144 |
1134 bool Compiler::CompileBaseline(Handle<JSFunction> function) { | 1145 bool Compiler::CompileBaseline(Handle<JSFunction> function) { |
1135 Isolate* isolate = function->GetIsolate(); | 1146 Isolate* isolate = function->GetIsolate(); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1172 ParseInfo parse_info(&zone, function); | 1183 ParseInfo parse_info(&zone, function); |
1173 CompilationInfo info(&parse_info, function); | 1184 CompilationInfo info(&parse_info, function); |
1174 if (!GetUnoptimizedCode(&info).ToHandle(&code)) { | 1185 if (!GetUnoptimizedCode(&info).ToHandle(&code)) { |
1175 return false; | 1186 return false; |
1176 } | 1187 } |
1177 } | 1188 } |
1178 } | 1189 } |
1179 | 1190 |
1180 // Install code on closure. | 1191 // Install code on closure. |
1181 function->ReplaceCode(*code); | 1192 function->ReplaceCode(*code); |
1193 JSFunction::EnsureLiterals(function); | |
1182 | 1194 |
1183 // Check postconditions on success. | 1195 // Check postconditions on success. |
1184 DCHECK(!isolate->has_pending_exception()); | 1196 DCHECK(!isolate->has_pending_exception()); |
1185 DCHECK(function->shared()->is_compiled()); | 1197 DCHECK(function->shared()->is_compiled()); |
1186 DCHECK(function->is_compiled()); | 1198 DCHECK(function->is_compiled()); |
1187 return true; | 1199 return true; |
1188 } | 1200 } |
1189 | 1201 |
1190 bool Compiler::CompileDebugCode(Handle<JSFunction> function) { | 1202 bool Compiler::CompileDebugCode(Handle<JSFunction> function) { |
1191 Isolate* isolate = function->GetIsolate(); | 1203 Isolate* isolate = function->GetIsolate(); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1278 HasInterpreterActivations(info->isolate(), *shared)) { | 1290 HasInterpreterActivations(info->isolate(), *shared)) { |
1279 return false; | 1291 return false; |
1280 } | 1292 } |
1281 // If the current code has reloc info for serialization, also include | 1293 // If the current code has reloc info for serialization, also include |
1282 // reloc info for serialization for the new code, so that deopt support | 1294 // reloc info for serialization for the new code, so that deopt support |
1283 // can be added without losing IC state. | 1295 // can be added without losing IC state. |
1284 if (shared->code()->kind() == Code::FUNCTION && | 1296 if (shared->code()->kind() == Code::FUNCTION && |
1285 shared->code()->has_reloc_info_for_serialization()) { | 1297 shared->code()->has_reloc_info_for_serialization()) { |
1286 unoptimized.PrepareForSerializing(); | 1298 unoptimized.PrepareForSerializing(); |
1287 } | 1299 } |
1288 EnsureFeedbackVector(&unoptimized); | 1300 EnsureFeedbackMetadata(&unoptimized); |
1289 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false; | 1301 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false; |
1290 | 1302 |
1291 // TODO(4280): For now we play it safe and remove the bytecode array when we | 1303 // TODO(4280): For now we play it safe and remove the bytecode array when we |
1292 // switch to baseline code. We might consider keeping around the bytecode so | 1304 // switch to baseline code. We might consider keeping around the bytecode so |
1293 // that it can be used as the "source of truth" eventually. | 1305 // that it can be used as the "source of truth" eventually. |
1294 shared->ClearBytecodeArray(); | 1306 shared->ClearBytecodeArray(); |
1295 | 1307 |
1296 // The scope info might not have been set if a lazily compiled | 1308 // The scope info might not have been set if a lazily compiled |
1297 // function is inlined before being called for the first time. | 1309 // function is inlined before being called for the first time. |
1298 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) { | 1310 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) { |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1653 Handle<JSFunction> fun = Handle<JSFunction>::cast(Utils::OpenHandle( | 1665 Handle<JSFunction> fun = Handle<JSFunction>::cast(Utils::OpenHandle( |
1654 *fun_template->GetFunction(v8_isolate->GetCurrentContext()) | 1666 *fun_template->GetFunction(v8_isolate->GetCurrentContext()) |
1655 .ToLocalChecked())); | 1667 .ToLocalChecked())); |
1656 const int literals = fun->NumberOfLiterals(); | 1668 const int literals = fun->NumberOfLiterals(); |
1657 Handle<Code> code = Handle<Code>(fun->shared()->code()); | 1669 Handle<Code> code = Handle<Code>(fun->shared()->code()); |
1658 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub()); | 1670 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub()); |
1659 Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo( | 1671 Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo( |
1660 name, literals, FunctionKind::kNormalFunction, code, | 1672 name, literals, FunctionKind::kNormalFunction, code, |
1661 Handle<ScopeInfo>(fun->shared()->scope_info())); | 1673 Handle<ScopeInfo>(fun->shared()->scope_info())); |
1662 shared->set_construct_stub(*construct_stub); | 1674 shared->set_construct_stub(*construct_stub); |
1663 shared->set_feedback_vector(fun->shared()->feedback_vector()); | 1675 shared->set_feedback_metadata(fun->shared()->feedback_metadata()); |
1664 | 1676 |
1665 // Copy the function data to the shared function info. | 1677 // Copy the function data to the shared function info. |
1666 shared->set_function_data(fun->shared()->function_data()); | 1678 shared->set_function_data(fun->shared()->function_data()); |
1667 int parameters = fun->shared()->internal_formal_parameter_count(); | 1679 int parameters = fun->shared()->internal_formal_parameter_count(); |
1668 shared->set_internal_formal_parameter_count(parameters); | 1680 shared->set_internal_formal_parameter_count(parameters); |
1669 | 1681 |
1670 return shared; | 1682 return shared; |
1671 } | 1683 } |
1672 | 1684 |
1673 MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function, | 1685 MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function, |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1740 CodeAndLiterals cached = shared->SearchOptimizedCodeMap( | 1752 CodeAndLiterals cached = shared->SearchOptimizedCodeMap( |
1741 function->context()->native_context(), BailoutId::None()); | 1753 function->context()->native_context(), BailoutId::None()); |
1742 if (cached.code != nullptr) { | 1754 if (cached.code != nullptr) { |
1743 // Caching of optimized code enabled and optimized code found. | 1755 // Caching of optimized code enabled and optimized code found. |
1744 DCHECK(!cached.code->marked_for_deoptimization()); | 1756 DCHECK(!cached.code->marked_for_deoptimization()); |
1745 DCHECK(function->shared()->is_compiled()); | 1757 DCHECK(function->shared()->is_compiled()); |
1746 function->ReplaceCode(cached.code); | 1758 function->ReplaceCode(cached.code); |
1747 } | 1759 } |
1748 | 1760 |
1749 if (cached.literals != nullptr) { | 1761 if (cached.literals != nullptr) { |
1762 DCHECK(shared->is_compiled()); | |
1750 function->set_literals(cached.literals); | 1763 function->set_literals(cached.literals); |
1751 } else { | 1764 } else if (shared->is_compiled()) { |
1752 Isolate* isolate = function->GetIsolate(); | 1765 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. |
1753 int number_of_literals = shared->num_literals(); | 1766 JSFunction::EnsureLiterals(function); |
1754 Handle<LiteralsArray> literals = | |
1755 LiteralsArray::New(isolate, handle(shared->feedback_vector()), | |
1756 number_of_literals, pretenure); | |
1757 function->set_literals(*literals); | |
1758 | |
1759 // Cache context-specific literals. | |
1760 MaybeHandle<Code> code; | |
1761 if (cached.code != nullptr) code = handle(cached.code); | |
1762 Handle<Context> native_context(function->context()->native_context()); | |
1763 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, | |
1764 literals, BailoutId::None()); | |
1765 } | 1767 } |
1766 } | 1768 } |
1767 | 1769 |
1768 } // namespace internal | 1770 } // namespace internal |
1769 } // namespace v8 | 1771 } // namespace v8 |
OLD | NEW |