Chromium Code Reviews| 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 // Checks whether top level functions should be passed by the filter. | 437 // Checks whether top level functions should be passed by the filter. |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 457 size += code->CodeSize(); | 457 size += code->CodeSize(); |
| 458 size += code->relocation_info()->Size(); | 458 size += code->relocation_info()->Size(); |
| 459 size += code->deoptimization_data()->Size(); | 459 size += code->deoptimization_data()->Size(); |
| 460 size += code->handler_table()->Size(); | 460 size += code->handler_table()->Size(); |
| 461 } | 461 } |
| 462 return size; | 462 return size; |
| 463 } | 463 } |
| 464 | 464 |
| 465 bool GenerateUnoptimizedCode(CompilationInfo* info) { | 465 bool GenerateUnoptimizedCode(CompilationInfo* info) { |
| 466 bool success; | 466 bool success; |
| 467 EnsureFeedbackVector(info); | 467 EnsureFeedbackMetadata(info); |
| 468 if (FLAG_validate_asm && info->scope()->asm_module()) { | 468 if (FLAG_validate_asm && info->scope()->asm_module()) { |
| 469 AsmTyper typer(info->isolate(), info->zone(), *(info->script()), | 469 AsmTyper typer(info->isolate(), info->zone(), *(info->script()), |
| 470 info->literal()); | 470 info->literal()); |
| 471 if (FLAG_enable_simd_asmjs) { | 471 if (FLAG_enable_simd_asmjs) { |
| 472 typer.set_allow_simd(true); | 472 typer.set_allow_simd(true); |
| 473 } | 473 } |
| 474 if (!typer.Validate()) { | 474 if (!typer.Validate()) { |
| 475 DCHECK(!info->isolate()->has_pending_exception()); | 475 DCHECK(!info->isolate()->has_pending_exception()); |
| 476 PrintF("Validation of asm.js module failed: %s", typer.error_message()); | 476 PrintF("Validation of asm.js module failed: %s", typer.error_message()); |
| 477 } | 477 } |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 632 passes_turbo_filter; | 632 passes_turbo_filter; |
| 633 } | 633 } |
| 634 | 634 |
| 635 bool GetOptimizedCodeNow(CompilationJob* job) { | 635 bool GetOptimizedCodeNow(CompilationJob* job) { |
| 636 CompilationInfo* info = job->info(); | 636 CompilationInfo* info = job->info(); |
| 637 Isolate* isolate = info->isolate(); | 637 Isolate* isolate = info->isolate(); |
| 638 | 638 |
| 639 // Parsing is not required when optimizing from existing bytecode. | 639 // Parsing is not required when optimizing from existing bytecode. |
| 640 if (!info->is_optimizing_from_bytecode()) { | 640 if (!info->is_optimizing_from_bytecode()) { |
| 641 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; | 641 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; |
| 642 EnsureFeedbackMetadata(info); | |
| 642 } | 643 } |
| 643 | 644 |
| 645 JSFunction::EnsureLiterals(info->closure()); | |
| 646 | |
| 644 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate); | 647 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate); |
| 645 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); | 648 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); |
| 646 | 649 |
| 647 if (job->CreateGraph() != CompilationJob::SUCCEEDED || | 650 if (job->CreateGraph() != CompilationJob::SUCCEEDED || |
| 648 job->OptimizeGraph() != CompilationJob::SUCCEEDED || | 651 job->OptimizeGraph() != CompilationJob::SUCCEEDED || |
| 649 job->GenerateCode() != CompilationJob::SUCCEEDED) { | 652 job->GenerateCode() != CompilationJob::SUCCEEDED) { |
| 650 if (FLAG_trace_opt) { | 653 if (FLAG_trace_opt) { |
| 651 PrintF("[aborted optimizing "); | 654 PrintF("[aborted optimizing "); |
| 652 info->closure()->ShortPrint(); | 655 info->closure()->ShortPrint(); |
| 653 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); | 656 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 675 } | 678 } |
| 676 return false; | 679 return false; |
| 677 } | 680 } |
| 678 | 681 |
| 679 // All handles below this point will be allocated in a deferred handle scope | 682 // All handles below this point will be allocated in a deferred handle scope |
| 680 // that is detached and handed off to the background thread when we return. | 683 // that is detached and handed off to the background thread when we return. |
| 681 CompilationHandleScope handle_scope(info); | 684 CompilationHandleScope handle_scope(info); |
| 682 | 685 |
| 683 // Parsing is not required when optimizing from existing bytecode. | 686 // Parsing is not required when optimizing from existing bytecode. |
| 684 if (!info->is_optimizing_from_bytecode()) { | 687 if (!info->is_optimizing_from_bytecode()) { |
| 685 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; | 688 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; |
|
Michael Starzinger
2016/05/25 11:20:18
If the call to EnsureFeedbackMetadata is needed fo
mvstanton
2016/05/25 12:57:07
Done.
| |
| 686 } | 689 } |
| 687 | 690 |
| 691 JSFunction::EnsureLiterals(info->closure()); | |
| 692 | |
| 688 // Reopen handles in the new CompilationHandleScope. | 693 // Reopen handles in the new CompilationHandleScope. |
| 689 info->ReopenHandlesInNewHandleScope(); | 694 info->ReopenHandlesInNewHandleScope(); |
| 690 info->parse_info()->ReopenHandlesInNewHandleScope(); | 695 info->parse_info()->ReopenHandlesInNewHandleScope(); |
| 691 | 696 |
| 692 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); | 697 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); |
| 693 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); | 698 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); |
| 694 | 699 |
| 695 if (job->CreateGraph() != CompilationJob::SUCCEEDED) return false; | 700 if (job->CreateGraph() != CompilationJob::SUCCEEDED) return false; |
| 696 isolate->optimizing_compile_dispatcher()->QueueForOptimization(job); | 701 isolate->optimizing_compile_dispatcher()->QueueForOptimization(job); |
| 697 | 702 |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1138 Handle<Code> code; | 1143 Handle<Code> code; |
| 1139 if (!GetLazyCode(function).ToHandle(&code)) { | 1144 if (!GetLazyCode(function).ToHandle(&code)) { |
| 1140 if (flag == CLEAR_EXCEPTION) { | 1145 if (flag == CLEAR_EXCEPTION) { |
| 1141 isolate->clear_pending_exception(); | 1146 isolate->clear_pending_exception(); |
| 1142 } | 1147 } |
| 1143 return false; | 1148 return false; |
| 1144 } | 1149 } |
| 1145 | 1150 |
| 1146 // Install code on closure. | 1151 // Install code on closure. |
| 1147 function->ReplaceCode(*code); | 1152 function->ReplaceCode(*code); |
| 1153 JSFunction::EnsureLiterals(function); | |
| 1148 | 1154 |
| 1149 // Check postconditions on success. | 1155 // Check postconditions on success. |
| 1150 DCHECK(!isolate->has_pending_exception()); | 1156 DCHECK(!isolate->has_pending_exception()); |
| 1151 DCHECK(function->shared()->is_compiled()); | 1157 DCHECK(function->shared()->is_compiled()); |
| 1152 DCHECK(function->is_compiled()); | 1158 DCHECK(function->is_compiled()); |
| 1153 return true; | 1159 return true; |
| 1154 } | 1160 } |
| 1155 | 1161 |
| 1156 bool Compiler::CompileBaseline(Handle<JSFunction> function) { | 1162 bool Compiler::CompileBaseline(Handle<JSFunction> function) { |
| 1157 Isolate* isolate = function->GetIsolate(); | 1163 Isolate* isolate = function->GetIsolate(); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1194 ParseInfo parse_info(&zone, function); | 1200 ParseInfo parse_info(&zone, function); |
| 1195 CompilationInfo info(&parse_info, function); | 1201 CompilationInfo info(&parse_info, function); |
| 1196 if (!GetUnoptimizedCode(&info).ToHandle(&code)) { | 1202 if (!GetUnoptimizedCode(&info).ToHandle(&code)) { |
| 1197 return false; | 1203 return false; |
| 1198 } | 1204 } |
| 1199 } | 1205 } |
| 1200 } | 1206 } |
| 1201 | 1207 |
| 1202 // Install code on closure. | 1208 // Install code on closure. |
| 1203 function->ReplaceCode(*code); | 1209 function->ReplaceCode(*code); |
| 1210 JSFunction::EnsureLiterals(function); | |
| 1204 | 1211 |
| 1205 // Check postconditions on success. | 1212 // Check postconditions on success. |
| 1206 DCHECK(!isolate->has_pending_exception()); | 1213 DCHECK(!isolate->has_pending_exception()); |
| 1207 DCHECK(function->shared()->is_compiled()); | 1214 DCHECK(function->shared()->is_compiled()); |
| 1208 DCHECK(function->is_compiled()); | 1215 DCHECK(function->is_compiled()); |
| 1209 return true; | 1216 return true; |
| 1210 } | 1217 } |
| 1211 | 1218 |
| 1212 bool Compiler::CompileDebugCode(Handle<JSFunction> function) { | 1219 bool Compiler::CompileDebugCode(Handle<JSFunction> function) { |
| 1213 Isolate* isolate = function->GetIsolate(); | 1220 Isolate* isolate = function->GetIsolate(); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1324 } | 1331 } |
| 1325 } | 1332 } |
| 1326 | 1333 |
| 1327 // If the current code has reloc info for serialization, also include | 1334 // If the current code has reloc info for serialization, also include |
| 1328 // reloc info for serialization for the new code, so that deopt support | 1335 // reloc info for serialization for the new code, so that deopt support |
| 1329 // can be added without losing IC state. | 1336 // can be added without losing IC state. |
| 1330 if (shared->code()->kind() == Code::FUNCTION && | 1337 if (shared->code()->kind() == Code::FUNCTION && |
| 1331 shared->code()->has_reloc_info_for_serialization()) { | 1338 shared->code()->has_reloc_info_for_serialization()) { |
| 1332 unoptimized.PrepareForSerializing(); | 1339 unoptimized.PrepareForSerializing(); |
| 1333 } | 1340 } |
| 1334 EnsureFeedbackVector(&unoptimized); | 1341 EnsureFeedbackMetadata(&unoptimized); |
| 1335 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false; | 1342 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false; |
| 1336 | 1343 |
| 1337 // TODO(4280): For now we play it safe and remove the bytecode array when we | 1344 // TODO(4280): For now we play it safe and remove the bytecode array when we |
| 1338 // switch to baseline code. We might consider keeping around the bytecode so | 1345 // switch to baseline code. We might consider keeping around the bytecode so |
| 1339 // that it can be used as the "source of truth" eventually. | 1346 // that it can be used as the "source of truth" eventually. |
| 1340 shared->ClearBytecodeArray(); | 1347 shared->ClearBytecodeArray(); |
| 1341 | 1348 |
| 1342 // The scope info might not have been set if a lazily compiled | 1349 // The scope info might not have been set if a lazily compiled |
| 1343 // function is inlined before being called for the first time. | 1350 // function is inlined before being called for the first time. |
| 1344 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) { | 1351 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) { |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1685 // Instantiate the function and create a shared function info from it. | 1692 // Instantiate the function and create a shared function info from it. |
| 1686 Handle<JSFunction> fun = Handle<JSFunction>::cast(Utils::OpenHandle( | 1693 Handle<JSFunction> fun = Handle<JSFunction>::cast(Utils::OpenHandle( |
| 1687 *fun_template->GetFunction(v8_isolate->GetCurrentContext()) | 1694 *fun_template->GetFunction(v8_isolate->GetCurrentContext()) |
| 1688 .ToLocalChecked())); | 1695 .ToLocalChecked())); |
| 1689 Handle<Code> code = Handle<Code>(fun->shared()->code()); | 1696 Handle<Code> code = Handle<Code>(fun->shared()->code()); |
| 1690 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub()); | 1697 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub()); |
| 1691 Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo( | 1698 Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo( |
| 1692 name, fun->shared()->num_literals(), FunctionKind::kNormalFunction, code, | 1699 name, fun->shared()->num_literals(), FunctionKind::kNormalFunction, code, |
| 1693 Handle<ScopeInfo>(fun->shared()->scope_info())); | 1700 Handle<ScopeInfo>(fun->shared()->scope_info())); |
| 1694 shared->set_construct_stub(*construct_stub); | 1701 shared->set_construct_stub(*construct_stub); |
| 1695 shared->set_feedback_vector(fun->shared()->feedback_vector()); | 1702 shared->set_feedback_metadata(fun->shared()->feedback_metadata()); |
| 1696 | 1703 |
| 1697 // Copy the function data to the shared function info. | 1704 // Copy the function data to the shared function info. |
| 1698 shared->set_function_data(fun->shared()->function_data()); | 1705 shared->set_function_data(fun->shared()->function_data()); |
| 1699 int parameters = fun->shared()->internal_formal_parameter_count(); | 1706 int parameters = fun->shared()->internal_formal_parameter_count(); |
| 1700 shared->set_internal_formal_parameter_count(parameters); | 1707 shared->set_internal_formal_parameter_count(parameters); |
| 1701 | 1708 |
| 1702 return shared; | 1709 return shared; |
| 1703 } | 1710 } |
| 1704 | 1711 |
| 1705 MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function, | 1712 MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function, |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1772 CodeAndLiterals cached = shared->SearchOptimizedCodeMap( | 1779 CodeAndLiterals cached = shared->SearchOptimizedCodeMap( |
| 1773 function->context()->native_context(), BailoutId::None()); | 1780 function->context()->native_context(), BailoutId::None()); |
| 1774 if (cached.code != nullptr) { | 1781 if (cached.code != nullptr) { |
| 1775 // Caching of optimized code enabled and optimized code found. | 1782 // Caching of optimized code enabled and optimized code found. |
| 1776 DCHECK(!cached.code->marked_for_deoptimization()); | 1783 DCHECK(!cached.code->marked_for_deoptimization()); |
| 1777 DCHECK(function->shared()->is_compiled()); | 1784 DCHECK(function->shared()->is_compiled()); |
| 1778 function->ReplaceCode(cached.code); | 1785 function->ReplaceCode(cached.code); |
| 1779 } | 1786 } |
| 1780 | 1787 |
| 1781 if (cached.literals != nullptr) { | 1788 if (cached.literals != nullptr) { |
| 1789 DCHECK(shared->is_compiled()); | |
| 1782 function->set_literals(cached.literals); | 1790 function->set_literals(cached.literals); |
| 1783 } else { | 1791 } else if (shared->is_compiled()) { |
| 1784 Isolate* isolate = function->GetIsolate(); | 1792 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. |
| 1785 int number_of_literals = shared->num_literals(); | 1793 JSFunction::EnsureLiterals(function); |
| 1786 Handle<LiteralsArray> literals = | |
| 1787 LiteralsArray::New(isolate, handle(shared->feedback_vector()), | |
| 1788 number_of_literals, pretenure); | |
| 1789 function->set_literals(*literals); | |
| 1790 | |
| 1791 // Cache context-specific literals. | |
| 1792 MaybeHandle<Code> code; | |
| 1793 if (cached.code != nullptr) code = handle(cached.code); | |
| 1794 Handle<Context> native_context(function->context()->native_context()); | |
| 1795 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, | |
| 1796 literals, BailoutId::None()); | |
| 1797 } | 1794 } |
| 1798 } | 1795 } |
| 1799 | 1796 |
| 1800 } // namespace internal | 1797 } // namespace internal |
| 1801 } // namespace v8 | 1798 } // namespace v8 |
| OLD | NEW |