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 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 String* script_name = script->name()->IsString() | 399 String* script_name = script->name()->IsString() |
400 ? String::cast(script->name()) | 400 ? String::cast(script->name()) |
401 : info->isolate()->heap()->empty_string(); | 401 : info->isolate()->heap()->empty_string(); |
402 Logger::LogEventsAndTags log_tag = Logger::ToNativeByScript(tag, *script); | 402 Logger::LogEventsAndTags log_tag = Logger::ToNativeByScript(tag, *script); |
403 PROFILE(info->isolate(), | 403 PROFILE(info->isolate(), |
404 CodeCreateEvent(log_tag, *abstract_code, *shared, script_name, | 404 CodeCreateEvent(log_tag, *abstract_code, *shared, script_name, |
405 line_num, column_num)); | 405 line_num, column_num)); |
406 } | 406 } |
407 } | 407 } |
408 | 408 |
409 void EnsureFeedbackVector(CompilationInfo* info) { | 409 void EnsureFeedbackMetadata(CompilationInfo* info) { |
410 DCHECK(info->has_shared_info()); | 410 DCHECK(info->has_shared_info()); |
411 | 411 |
412 // If no type feedback vector exists, we create one now. At this point the | 412 // If no type feedback metadata exists, we create it now. At this point the |
413 // AstNumbering pass has already run. Note the snapshot can contain outdated | 413 // AstNumbering pass has already run. Note the snapshot can contain outdated |
414 // vectors for a different configuration, hence we also recreate a new vector | 414 // vectors for a different configuration, hence we also recreate a new vector |
415 // when the function is not compiled (i.e. no code was serialized). | 415 // when the function is not compiled (i.e. no code was serialized). |
416 if (info->shared_info()->feedback_vector()->is_empty() || | 416 |
| 417 // TODO(mvstanton): reintroduce is_empty() predicate to feedback_metadata(). |
| 418 if (info->shared_info()->feedback_metadata()->length() == 0 || |
417 !info->shared_info()->is_compiled()) { | 419 !info->shared_info()->is_compiled()) { |
418 Handle<TypeFeedbackMetadata> feedback_metadata = TypeFeedbackMetadata::New( | 420 Handle<TypeFeedbackMetadata> feedback_metadata = TypeFeedbackMetadata::New( |
419 info->isolate(), info->literal()->feedback_vector_spec()); | 421 info->isolate(), info->literal()->feedback_vector_spec()); |
420 Handle<TypeFeedbackVector> feedback_vector = | 422 info->shared_info()->set_feedback_metadata(*feedback_metadata); |
421 TypeFeedbackVector::New(info->isolate(), feedback_metadata); | |
422 info->shared_info()->set_feedback_vector(*feedback_vector); | |
423 } | 423 } |
424 | 424 |
425 // It's very important that recompiles do not alter the structure of the type | 425 // It's very important that recompiles do not alter the structure of the type |
426 // feedback vector. Verify that the structure fits the function literal. | 426 // feedback vector. Verify that the structure fits the function literal. |
427 CHECK(!info->shared_info()->feedback_vector()->metadata()->SpecDiffersFrom( | 427 CHECK(!info->shared_info()->feedback_metadata()->SpecDiffersFrom( |
428 info->literal()->feedback_vector_spec())); | 428 info->literal()->feedback_vector_spec())); |
429 } | 429 } |
430 | 430 |
431 bool UseIgnition(CompilationInfo* info) { | 431 bool UseIgnition(CompilationInfo* info) { |
432 if (info->is_debug()) return false; | 432 if (info->is_debug()) return false; |
433 if (info->shared_info()->is_resumable() && !FLAG_ignition_generators) { | 433 if (info->shared_info()->is_resumable() && !FLAG_ignition_generators) { |
434 return false; | 434 return false; |
435 } | 435 } |
436 | 436 |
437 // Since we can't OSR from Ignition, skip Ignition for asm.js functions. | 437 // Since we can't OSR from Ignition, skip Ignition for asm.js functions. |
(...skipping 13 matching lines...) Expand all Loading... |
451 | 451 |
452 int CodeAndMetadataSize(CompilationInfo* info) { | 452 int CodeAndMetadataSize(CompilationInfo* info) { |
453 if (info->has_bytecode_array()) { | 453 if (info->has_bytecode_array()) { |
454 return info->bytecode_array()->SizeIncludingMetadata(); | 454 return info->bytecode_array()->SizeIncludingMetadata(); |
455 } | 455 } |
456 return info->code()->SizeIncludingMetadata(); | 456 return info->code()->SizeIncludingMetadata(); |
457 } | 457 } |
458 | 458 |
459 bool GenerateUnoptimizedCode(CompilationInfo* info) { | 459 bool GenerateUnoptimizedCode(CompilationInfo* info) { |
460 bool success; | 460 bool success; |
461 EnsureFeedbackVector(info); | 461 EnsureFeedbackMetadata(info); |
462 if (FLAG_validate_asm && info->scope()->asm_module()) { | 462 if (FLAG_validate_asm && info->scope()->asm_module()) { |
463 AsmTyper typer(info->isolate(), info->zone(), *(info->script()), | 463 AsmTyper typer(info->isolate(), info->zone(), *(info->script()), |
464 info->literal()); | 464 info->literal()); |
465 if (FLAG_enable_simd_asmjs) { | 465 if (FLAG_enable_simd_asmjs) { |
466 typer.set_allow_simd(true); | 466 typer.set_allow_simd(true); |
467 } | 467 } |
468 if (!typer.Validate()) { | 468 if (!typer.Validate()) { |
469 DCHECK(!info->isolate()->has_pending_exception()); | 469 DCHECK(!info->isolate()->has_pending_exception()); |
470 PrintF("Validation of asm.js module failed: %s", typer.error_message()); | 470 PrintF("Validation of asm.js module failed: %s", typer.error_message()); |
471 } | 471 } |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
626 passes_turbo_filter; | 626 passes_turbo_filter; |
627 } | 627 } |
628 | 628 |
629 bool GetOptimizedCodeNow(CompilationJob* job) { | 629 bool GetOptimizedCodeNow(CompilationJob* job) { |
630 CompilationInfo* info = job->info(); | 630 CompilationInfo* info = job->info(); |
631 Isolate* isolate = info->isolate(); | 631 Isolate* isolate = info->isolate(); |
632 | 632 |
633 // Parsing is not required when optimizing from existing bytecode. | 633 // Parsing is not required when optimizing from existing bytecode. |
634 if (!info->is_optimizing_from_bytecode()) { | 634 if (!info->is_optimizing_from_bytecode()) { |
635 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; | 635 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; |
| 636 EnsureFeedbackMetadata(info); |
636 } | 637 } |
637 | 638 |
| 639 JSFunction::EnsureLiterals(info->closure()); |
| 640 |
638 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate); | 641 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate); |
639 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); | 642 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); |
640 | 643 |
641 if (job->CreateGraph() != CompilationJob::SUCCEEDED || | 644 if (job->CreateGraph() != CompilationJob::SUCCEEDED || |
642 job->OptimizeGraph() != CompilationJob::SUCCEEDED || | 645 job->OptimizeGraph() != CompilationJob::SUCCEEDED || |
643 job->GenerateCode() != CompilationJob::SUCCEEDED) { | 646 job->GenerateCode() != CompilationJob::SUCCEEDED) { |
644 if (FLAG_trace_opt) { | 647 if (FLAG_trace_opt) { |
645 PrintF("[aborted optimizing "); | 648 PrintF("[aborted optimizing "); |
646 info->closure()->ShortPrint(); | 649 info->closure()->ShortPrint(); |
647 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); | 650 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); |
(...skipping 22 matching lines...) Expand all Loading... |
670 return false; | 673 return false; |
671 } | 674 } |
672 | 675 |
673 // All handles below this point will be allocated in a deferred handle scope | 676 // All handles below this point will be allocated in a deferred handle scope |
674 // that is detached and handed off to the background thread when we return. | 677 // that is detached and handed off to the background thread when we return. |
675 CompilationHandleScope handle_scope(info); | 678 CompilationHandleScope handle_scope(info); |
676 | 679 |
677 // Parsing is not required when optimizing from existing bytecode. | 680 // Parsing is not required when optimizing from existing bytecode. |
678 if (!info->is_optimizing_from_bytecode()) { | 681 if (!info->is_optimizing_from_bytecode()) { |
679 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; | 682 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; |
| 683 EnsureFeedbackMetadata(info); |
680 } | 684 } |
681 | 685 |
| 686 JSFunction::EnsureLiterals(info->closure()); |
| 687 |
682 // Reopen handles in the new CompilationHandleScope. | 688 // Reopen handles in the new CompilationHandleScope. |
683 info->ReopenHandlesInNewHandleScope(); | 689 info->ReopenHandlesInNewHandleScope(); |
684 info->parse_info()->ReopenHandlesInNewHandleScope(); | 690 info->parse_info()->ReopenHandlesInNewHandleScope(); |
685 | 691 |
686 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); | 692 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); |
687 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); | 693 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); |
688 | 694 |
689 if (job->CreateGraph() != CompilationJob::SUCCEEDED) return false; | 695 if (job->CreateGraph() != CompilationJob::SUCCEEDED) return false; |
690 isolate->optimizing_compile_dispatcher()->QueueForOptimization(job); | 696 isolate->optimizing_compile_dispatcher()->QueueForOptimization(job); |
691 | 697 |
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1132 Handle<Code> code; | 1138 Handle<Code> code; |
1133 if (!GetLazyCode(function).ToHandle(&code)) { | 1139 if (!GetLazyCode(function).ToHandle(&code)) { |
1134 if (flag == CLEAR_EXCEPTION) { | 1140 if (flag == CLEAR_EXCEPTION) { |
1135 isolate->clear_pending_exception(); | 1141 isolate->clear_pending_exception(); |
1136 } | 1142 } |
1137 return false; | 1143 return false; |
1138 } | 1144 } |
1139 | 1145 |
1140 // Install code on closure. | 1146 // Install code on closure. |
1141 function->ReplaceCode(*code); | 1147 function->ReplaceCode(*code); |
| 1148 JSFunction::EnsureLiterals(function); |
1142 | 1149 |
1143 // Check postconditions on success. | 1150 // Check postconditions on success. |
1144 DCHECK(!isolate->has_pending_exception()); | 1151 DCHECK(!isolate->has_pending_exception()); |
1145 DCHECK(function->shared()->is_compiled()); | 1152 DCHECK(function->shared()->is_compiled()); |
1146 DCHECK(function->is_compiled()); | 1153 DCHECK(function->is_compiled()); |
1147 return true; | 1154 return true; |
1148 } | 1155 } |
1149 | 1156 |
1150 bool Compiler::CompileBaseline(Handle<JSFunction> function) { | 1157 bool Compiler::CompileBaseline(Handle<JSFunction> function) { |
1151 Isolate* isolate = function->GetIsolate(); | 1158 Isolate* isolate = function->GetIsolate(); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1188 ParseInfo parse_info(&zone, function); | 1195 ParseInfo parse_info(&zone, function); |
1189 CompilationInfo info(&parse_info, function); | 1196 CompilationInfo info(&parse_info, function); |
1190 if (!GetUnoptimizedCode(&info).ToHandle(&code)) { | 1197 if (!GetUnoptimizedCode(&info).ToHandle(&code)) { |
1191 return false; | 1198 return false; |
1192 } | 1199 } |
1193 } | 1200 } |
1194 } | 1201 } |
1195 | 1202 |
1196 // Install code on closure. | 1203 // Install code on closure. |
1197 function->ReplaceCode(*code); | 1204 function->ReplaceCode(*code); |
| 1205 JSFunction::EnsureLiterals(function); |
1198 | 1206 |
1199 // Check postconditions on success. | 1207 // Check postconditions on success. |
1200 DCHECK(!isolate->has_pending_exception()); | 1208 DCHECK(!isolate->has_pending_exception()); |
1201 DCHECK(function->shared()->is_compiled()); | 1209 DCHECK(function->shared()->is_compiled()); |
1202 DCHECK(function->is_compiled()); | 1210 DCHECK(function->is_compiled()); |
1203 return true; | 1211 return true; |
1204 } | 1212 } |
1205 | 1213 |
1206 bool Compiler::CompileDebugCode(Handle<JSFunction> function) { | 1214 bool Compiler::CompileDebugCode(Handle<JSFunction> function) { |
1207 Isolate* isolate = function->GetIsolate(); | 1215 Isolate* isolate = function->GetIsolate(); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1318 } | 1326 } |
1319 } | 1327 } |
1320 | 1328 |
1321 // If the current code has reloc info for serialization, also include | 1329 // If the current code has reloc info for serialization, also include |
1322 // reloc info for serialization for the new code, so that deopt support | 1330 // reloc info for serialization for the new code, so that deopt support |
1323 // can be added without losing IC state. | 1331 // can be added without losing IC state. |
1324 if (shared->code()->kind() == Code::FUNCTION && | 1332 if (shared->code()->kind() == Code::FUNCTION && |
1325 shared->code()->has_reloc_info_for_serialization()) { | 1333 shared->code()->has_reloc_info_for_serialization()) { |
1326 unoptimized.PrepareForSerializing(); | 1334 unoptimized.PrepareForSerializing(); |
1327 } | 1335 } |
1328 EnsureFeedbackVector(&unoptimized); | 1336 EnsureFeedbackMetadata(&unoptimized); |
1329 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false; | 1337 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false; |
1330 | 1338 |
1331 // TODO(4280): For now we play it safe and remove the bytecode array when we | 1339 // TODO(4280): For now we play it safe and remove the bytecode array when we |
1332 // switch to baseline code. We might consider keeping around the bytecode so | 1340 // switch to baseline code. We might consider keeping around the bytecode so |
1333 // that it can be used as the "source of truth" eventually. | 1341 // that it can be used as the "source of truth" eventually. |
1334 shared->ClearBytecodeArray(); | 1342 shared->ClearBytecodeArray(); |
1335 | 1343 |
1336 // The scope info might not have been set if a lazily compiled | 1344 // The scope info might not have been set if a lazily compiled |
1337 // function is inlined before being called for the first time. | 1345 // function is inlined before being called for the first time. |
1338 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) { | 1346 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) { |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1679 // Instantiate the function and create a shared function info from it. | 1687 // Instantiate the function and create a shared function info from it. |
1680 Handle<JSFunction> fun = Handle<JSFunction>::cast(Utils::OpenHandle( | 1688 Handle<JSFunction> fun = Handle<JSFunction>::cast(Utils::OpenHandle( |
1681 *fun_template->GetFunction(v8_isolate->GetCurrentContext()) | 1689 *fun_template->GetFunction(v8_isolate->GetCurrentContext()) |
1682 .ToLocalChecked())); | 1690 .ToLocalChecked())); |
1683 Handle<Code> code = Handle<Code>(fun->shared()->code()); | 1691 Handle<Code> code = Handle<Code>(fun->shared()->code()); |
1684 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub()); | 1692 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub()); |
1685 Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo( | 1693 Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo( |
1686 name, fun->shared()->num_literals(), FunctionKind::kNormalFunction, code, | 1694 name, fun->shared()->num_literals(), FunctionKind::kNormalFunction, code, |
1687 Handle<ScopeInfo>(fun->shared()->scope_info())); | 1695 Handle<ScopeInfo>(fun->shared()->scope_info())); |
1688 shared->set_construct_stub(*construct_stub); | 1696 shared->set_construct_stub(*construct_stub); |
1689 shared->set_feedback_vector(fun->shared()->feedback_vector()); | 1697 shared->set_feedback_metadata(fun->shared()->feedback_metadata()); |
1690 | 1698 |
1691 // Copy the function data to the shared function info. | 1699 // Copy the function data to the shared function info. |
1692 shared->set_function_data(fun->shared()->function_data()); | 1700 shared->set_function_data(fun->shared()->function_data()); |
1693 int parameters = fun->shared()->internal_formal_parameter_count(); | 1701 int parameters = fun->shared()->internal_formal_parameter_count(); |
1694 shared->set_internal_formal_parameter_count(parameters); | 1702 shared->set_internal_formal_parameter_count(parameters); |
1695 | 1703 |
1696 return shared; | 1704 return shared; |
1697 } | 1705 } |
1698 | 1706 |
1699 MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function, | 1707 MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function, |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1766 CodeAndLiterals cached = shared->SearchOptimizedCodeMap( | 1774 CodeAndLiterals cached = shared->SearchOptimizedCodeMap( |
1767 function->context()->native_context(), BailoutId::None()); | 1775 function->context()->native_context(), BailoutId::None()); |
1768 if (cached.code != nullptr) { | 1776 if (cached.code != nullptr) { |
1769 // Caching of optimized code enabled and optimized code found. | 1777 // Caching of optimized code enabled and optimized code found. |
1770 DCHECK(!cached.code->marked_for_deoptimization()); | 1778 DCHECK(!cached.code->marked_for_deoptimization()); |
1771 DCHECK(function->shared()->is_compiled()); | 1779 DCHECK(function->shared()->is_compiled()); |
1772 function->ReplaceCode(cached.code); | 1780 function->ReplaceCode(cached.code); |
1773 } | 1781 } |
1774 | 1782 |
1775 if (cached.literals != nullptr) { | 1783 if (cached.literals != nullptr) { |
| 1784 DCHECK(shared->is_compiled()); |
1776 function->set_literals(cached.literals); | 1785 function->set_literals(cached.literals); |
1777 } else { | 1786 } else if (shared->is_compiled()) { |
1778 Isolate* isolate = function->GetIsolate(); | 1787 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. |
1779 int number_of_literals = shared->num_literals(); | 1788 JSFunction::EnsureLiterals(function); |
1780 Handle<LiteralsArray> literals = | |
1781 LiteralsArray::New(isolate, handle(shared->feedback_vector()), | |
1782 number_of_literals, pretenure); | |
1783 function->set_literals(*literals); | |
1784 | |
1785 // Cache context-specific literals. | |
1786 MaybeHandle<Code> code; | |
1787 if (cached.code != nullptr) code = handle(cached.code); | |
1788 Handle<Context> native_context(function->context()->native_context()); | |
1789 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, | |
1790 literals, BailoutId::None()); | |
1791 } | 1789 } |
1792 } | 1790 } |
1793 | 1791 |
1794 } // namespace internal | 1792 } // namespace internal |
1795 } // namespace v8 | 1793 } // namespace v8 |
OLD | NEW |