| 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 |