| 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 20 matching lines...) Expand all Loading... |
| 31 #include "src/parsing/parsing.h" | 31 #include "src/parsing/parsing.h" |
| 32 #include "src/parsing/rewriter.h" | 32 #include "src/parsing/rewriter.h" |
| 33 #include "src/parsing/scanner-character-streams.h" | 33 #include "src/parsing/scanner-character-streams.h" |
| 34 #include "src/runtime-profiler.h" | 34 #include "src/runtime-profiler.h" |
| 35 #include "src/snapshot/code-serializer.h" | 35 #include "src/snapshot/code-serializer.h" |
| 36 #include "src/vm-state-inl.h" | 36 #include "src/vm-state-inl.h" |
| 37 | 37 |
| 38 namespace v8 { | 38 namespace v8 { |
| 39 namespace internal { | 39 namespace internal { |
| 40 | 40 |
| 41 | |
| 42 | |
| 43 // A wrapper around a CompilationInfo that detaches the Handles from | 41 // A wrapper around a CompilationInfo that detaches the Handles from |
| 44 // the underlying DeferredHandleScope and stores them in info_ on | 42 // the underlying DeferredHandleScope and stores them in info_ on |
| 45 // destruction. | 43 // destruction. |
| 46 class CompilationHandleScope final { | 44 class CompilationHandleScope final { |
| 47 public: | 45 public: |
| 48 explicit CompilationHandleScope(CompilationInfo* info) | 46 explicit CompilationHandleScope(CompilationInfo* info) |
| 49 : deferred_(info->isolate()), info_(info) {} | 47 : deferred_(info->isolate()), info_(info) {} |
| 50 ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); } | 48 ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); } |
| 51 | 49 |
| 52 private: | 50 private: |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 // Checks whether top level functions should be passed by the filter. | 368 // Checks whether top level functions should be passed by the filter. |
| 371 if (shared->is_toplevel()) { | 369 if (shared->is_toplevel()) { |
| 372 Vector<const char> filter = CStrVector(FLAG_ignition_filter); | 370 Vector<const char> filter = CStrVector(FLAG_ignition_filter); |
| 373 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*'); | 371 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*'); |
| 374 } | 372 } |
| 375 | 373 |
| 376 // Finally respect the filter. | 374 // Finally respect the filter. |
| 377 return shared->PassesFilter(FLAG_ignition_filter); | 375 return shared->PassesFilter(FLAG_ignition_filter); |
| 378 } | 376 } |
| 379 | 377 |
| 380 CompilationJob* GetUnoptimizedCompilationJob(CompilationInfo* info, | 378 CompilationJob* GetUnoptimizedCompilationJob(CompilationInfo* info) { |
| 381 LazyCompilationMode mode) { | |
| 382 // Function should have been parsed and analyzed before creating a compilation | 379 // Function should have been parsed and analyzed before creating a compilation |
| 383 // job. | 380 // job. |
| 384 DCHECK_NOT_NULL(info->literal()); | 381 DCHECK_NOT_NULL(info->literal()); |
| 385 DCHECK_NOT_NULL(info->scope()); | 382 DCHECK_NOT_NULL(info->scope()); |
| 386 | 383 |
| 387 EnsureFeedbackMetadata(info); | 384 EnsureFeedbackMetadata(info); |
| 388 if (ShouldUseIgnition(info)) { | 385 if (ShouldUseIgnition(info)) { |
| 389 return interpreter::Interpreter::NewCompilationJob(info, mode); | 386 return interpreter::Interpreter::NewCompilationJob(info); |
| 390 } else { | 387 } else { |
| 391 return FullCodeGenerator::NewCompilationJob(info, mode); | 388 return FullCodeGenerator::NewCompilationJob(info); |
| 392 } | 389 } |
| 393 } | 390 } |
| 394 | 391 |
| 395 void InstallSharedScopeInfo(CompilationInfo* info, | 392 void InstallSharedScopeInfo(CompilationInfo* info, |
| 396 Handle<SharedFunctionInfo> shared) { | 393 Handle<SharedFunctionInfo> shared) { |
| 397 Handle<ScopeInfo> scope_info = info->scope()->scope_info(); | 394 Handle<ScopeInfo> scope_info = info->scope()->scope_info(); |
| 398 shared->set_scope_info(*scope_info); | 395 shared->set_scope_info(*scope_info); |
| 399 Scope* outer_scope = info->scope()->GetOuterScopeWithContext(); | 396 Scope* outer_scope = info->scope()->GetOuterScopeWithContext(); |
| 400 if (outer_scope) { | 397 if (outer_scope) { |
| 401 shared->set_outer_scope_info(*outer_scope->scope_info()); | 398 shared->set_outer_scope_info(*outer_scope->scope_info()); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 430 | 427 |
| 431 CompilationJob::Status FinalizeUnoptimizedCompilationJob(CompilationJob* job) { | 428 CompilationJob::Status FinalizeUnoptimizedCompilationJob(CompilationJob* job) { |
| 432 CompilationJob::Status status = job->FinalizeJob(); | 429 CompilationJob::Status status = job->FinalizeJob(); |
| 433 if (status == CompilationJob::SUCCEEDED) { | 430 if (status == CompilationJob::SUCCEEDED) { |
| 434 InstallUnoptimizedCode(job->info()); | 431 InstallUnoptimizedCode(job->info()); |
| 435 job->RecordUnoptimizedCompilationStats(); | 432 job->RecordUnoptimizedCompilationStats(); |
| 436 } | 433 } |
| 437 return status; | 434 return status; |
| 438 } | 435 } |
| 439 | 436 |
| 437 bool Renumber(ParseInfo* parse_info, |
| 438 Compiler::EagerInnerFunctionLiterals* eager_literals) { |
| 439 RuntimeCallTimerScope runtimeTimer(parse_info->isolate(), |
| 440 &RuntimeCallStats::CompileRenumber); |
| 441 if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(), |
| 442 parse_info->literal(), eager_literals)) { |
| 443 return false; |
| 444 } |
| 445 Handle<SharedFunctionInfo> shared_info = parse_info->shared_info(); |
| 446 if (!shared_info.is_null()) { |
| 447 FunctionLiteral* lit = parse_info->literal(); |
| 448 shared_info->set_ast_node_count(lit->ast_node_count()); |
| 449 if (lit->dont_optimize_reason() != kNoReason) { |
| 450 shared_info->DisableOptimization(lit->dont_optimize_reason()); |
| 451 } |
| 452 if (lit->flags() & AstProperties::kMustUseIgnitionTurbo) { |
| 453 shared_info->set_must_use_ignition_turbo(true); |
| 454 } |
| 455 } |
| 456 return true; |
| 457 } |
| 458 |
| 440 bool GenerateUnoptimizedCode(CompilationInfo* info) { | 459 bool GenerateUnoptimizedCode(CompilationInfo* info) { |
| 441 if (FLAG_validate_asm && info->scope()->asm_module() && | 460 if (FLAG_validate_asm && info->scope()->asm_module() && |
| 442 !info->shared_info()->is_asm_wasm_broken() && !info->is_debug()) { | 461 !info->shared_info()->is_asm_wasm_broken() && !info->is_debug()) { |
| 443 EnsureFeedbackMetadata(info); | 462 EnsureFeedbackMetadata(info); |
| 444 MaybeHandle<FixedArray> wasm_data; | 463 MaybeHandle<FixedArray> wasm_data; |
| 445 wasm_data = AsmJs::CompileAsmViaWasm(info); | 464 wasm_data = AsmJs::CompileAsmViaWasm(info); |
| 446 if (!wasm_data.is_null()) { | 465 if (!wasm_data.is_null()) { |
| 447 info->shared_info()->set_asm_wasm_data(*wasm_data.ToHandleChecked()); | 466 info->shared_info()->set_asm_wasm_data(*wasm_data.ToHandleChecked()); |
| 448 info->SetCode(info->isolate()->builtins()->InstantiateAsmJs()); | 467 info->SetCode(info->isolate()->builtins()->InstantiateAsmJs()); |
| 449 InstallUnoptimizedCode(info); | 468 InstallUnoptimizedCode(info); |
| 450 return true; | 469 return true; |
| 451 } | 470 } |
| 452 } | 471 } |
| 453 | 472 |
| 454 std::unique_ptr<CompilationJob> job( | 473 std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info)); |
| 455 GetUnoptimizedCompilationJob(info, LazyCompilationMode::kIfRequested)); | |
| 456 if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false; | 474 if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false; |
| 457 if (job->ExecuteJob() != CompilationJob::SUCCEEDED) return false; | 475 if (job->ExecuteJob() != CompilationJob::SUCCEEDED) return false; |
| 458 if (FinalizeUnoptimizedCompilationJob(job.get()) != | 476 if (FinalizeUnoptimizedCompilationJob(job.get()) != |
| 459 CompilationJob::SUCCEEDED) { | 477 CompilationJob::SUCCEEDED) { |
| 460 return false; | 478 return false; |
| 461 } | 479 } |
| 462 return true; | 480 return true; |
| 463 } | 481 } |
| 464 | 482 |
| 483 bool CompileUnoptimizedInnerFunctionsRecursively( |
| 484 ThreadedList<ThreadedListZoneEntry<FunctionLiteral*>>* literals, |
| 485 CompilationInfo* outer_info) { |
| 486 Isolate* isolate = outer_info->isolate(); |
| 487 Handle<Script> script = outer_info->script(); |
| 488 RuntimeCallTimerScope runtimeTimer(isolate, |
| 489 &RuntimeCallStats::CompileInnerFunction); |
| 490 |
| 491 for (auto it : *literals) { |
| 492 FunctionLiteral* literal = it->value(); |
| 493 |
| 494 // Find any previously allocated shared function info for the given literal. |
| 495 Handle<SharedFunctionInfo> shared; |
| 496 MaybeHandle<SharedFunctionInfo> maybe_existing = |
| 497 script->FindSharedFunctionInfo(isolate, literal); |
| 498 if (maybe_existing.ToHandle(&shared)) { |
| 499 DCHECK(!shared->is_toplevel()); |
| 500 // If we found an existing shared function info with compiled code, |
| 501 // we are done. |
| 502 if (shared->is_compiled()) continue; |
| 503 } else { |
| 504 shared = |
| 505 isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script); |
| 506 shared->set_is_toplevel(false); |
| 507 } |
| 508 |
| 509 Zone zone(isolate->allocator(), ZONE_NAME); |
| 510 ParseInfo parse_info(&zone, script); |
| 511 parse_info.set_literal(literal); |
| 512 parse_info.set_shared_info(shared); |
| 513 parse_info.set_function_literal_id(shared->function_literal_id()); |
| 514 parse_info.set_language_mode(literal->scope()->language_mode()); |
| 515 parse_info.set_ast_value_factory( |
| 516 outer_info->parse_info()->ast_value_factory()); |
| 517 parse_info.set_ast_value_factory_owned(false); |
| 518 |
| 519 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); |
| 520 if (outer_info->will_serialize()) info.PrepareForSerializing(); |
| 521 if (outer_info->is_debug()) info.MarkAsDebug(); |
| 522 |
| 523 Compiler::EagerInnerFunctionLiterals inner_literals; |
| 524 if (!Renumber(&parse_info, &inner_literals) || |
| 525 !CompileUnoptimizedInnerFunctionsRecursively(&inner_literals, |
| 526 outer_info) || |
| 527 !GenerateUnoptimizedCode(&info)) { |
| 528 if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
| 529 return false; |
| 530 } |
| 531 |
| 532 DCHECK(!info.code().is_null()); |
| 533 RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, &info); |
| 534 if (literal->should_be_used_once_hint()) { |
| 535 info.code()->MarkToBeExecutedOnce(isolate); |
| 536 } |
| 537 } |
| 538 return true; |
| 539 } |
| 540 |
| 465 bool CompileUnoptimizedCode(CompilationInfo* info) { | 541 bool CompileUnoptimizedCode(CompilationInfo* info) { |
| 466 DCHECK(AllowCompilation::IsAllowed(info->isolate())); | 542 Isolate* isolate = info->isolate(); |
| 467 if (!Compiler::Analyze(info->parse_info()) || | 543 DCHECK(AllowCompilation::IsAllowed(isolate)); |
| 544 |
| 545 Compiler::EagerInnerFunctionLiterals inner_literals; |
| 546 if (!Compiler::Analyze(info->parse_info(), &inner_literals) || |
| 547 !CompileUnoptimizedInnerFunctionsRecursively(&inner_literals, info) || |
| 468 !GenerateUnoptimizedCode(info)) { | 548 !GenerateUnoptimizedCode(info)) { |
| 469 Isolate* isolate = info->isolate(); | |
| 470 if (!isolate->has_pending_exception()) isolate->StackOverflow(); | 549 if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
| 471 return false; | 550 return false; |
| 472 } | 551 } |
| 552 |
| 473 return true; | 553 return true; |
| 474 } | 554 } |
| 475 | 555 |
| 476 void EnsureSharedFunctionInfosArrayOnScript(ParseInfo* info) { | 556 void EnsureSharedFunctionInfosArrayOnScript(ParseInfo* info) { |
| 477 DCHECK(info->is_toplevel()); | 557 DCHECK(info->is_toplevel()); |
| 478 DCHECK(!info->script().is_null()); | 558 DCHECK(!info->script().is_null()); |
| 479 if (info->script()->shared_function_infos()->length() > 0) { | 559 if (info->script()->shared_function_infos()->length() > 0) { |
| 480 DCHECK_EQ(info->script()->shared_function_infos()->length(), | 560 DCHECK_EQ(info->script()->shared_function_infos()->length(), |
| 481 info->max_function_literal_id() + 1); | 561 info->max_function_literal_id() + 1); |
| 482 return; | 562 return; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 | 625 |
| 546 // Cache optimized context-specific code. | 626 // Cache optimized context-specific code. |
| 547 Handle<JSFunction> function = info->closure(); | 627 Handle<JSFunction> function = info->closure(); |
| 548 Handle<SharedFunctionInfo> shared(function->shared()); | 628 Handle<SharedFunctionInfo> shared(function->shared()); |
| 549 Handle<LiteralsArray> literals(function->literals()); | 629 Handle<LiteralsArray> literals(function->literals()); |
| 550 Handle<Context> native_context(function->context()->native_context()); | 630 Handle<Context> native_context(function->context()->native_context()); |
| 551 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, | 631 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, |
| 552 literals, info->osr_ast_id()); | 632 literals, info->osr_ast_id()); |
| 553 } | 633 } |
| 554 | 634 |
| 555 bool Renumber(ParseInfo* parse_info) { | |
| 556 RuntimeCallTimerScope runtimeTimer(parse_info->isolate(), | |
| 557 &RuntimeCallStats::CompileRenumber); | |
| 558 if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(), | |
| 559 parse_info->literal())) { | |
| 560 return false; | |
| 561 } | |
| 562 Handle<SharedFunctionInfo> shared_info = parse_info->shared_info(); | |
| 563 if (!shared_info.is_null()) { | |
| 564 FunctionLiteral* lit = parse_info->literal(); | |
| 565 shared_info->set_ast_node_count(lit->ast_node_count()); | |
| 566 if (lit->dont_optimize_reason() != kNoReason) { | |
| 567 shared_info->DisableOptimization(lit->dont_optimize_reason()); | |
| 568 } | |
| 569 if (lit->flags() & AstProperties::kMustUseIgnitionTurbo) { | |
| 570 shared_info->set_must_use_ignition_turbo(true); | |
| 571 } | |
| 572 } | |
| 573 return true; | |
| 574 } | |
| 575 | |
| 576 bool GetOptimizedCodeNow(CompilationJob* job) { | 635 bool GetOptimizedCodeNow(CompilationJob* job) { |
| 577 CompilationInfo* info = job->info(); | 636 CompilationInfo* info = job->info(); |
| 578 Isolate* isolate = info->isolate(); | 637 Isolate* isolate = info->isolate(); |
| 579 | 638 |
| 580 // Parsing is not required when optimizing from existing bytecode. | 639 // Parsing is not required when optimizing from existing bytecode. |
| 581 if (!info->is_optimizing_from_bytecode()) { | 640 if (!info->is_optimizing_from_bytecode()) { |
| 582 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; | 641 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; |
| 583 EnsureFeedbackMetadata(info); | 642 EnsureFeedbackMetadata(info); |
| 584 } | 643 } |
| 585 | 644 |
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1009 Handle<SharedFunctionInfo> result; | 1068 Handle<SharedFunctionInfo> result; |
| 1010 | 1069 |
| 1011 { VMState<COMPILER> state(info->isolate()); | 1070 { VMState<COMPILER> state(info->isolate()); |
| 1012 if (parse_info->literal() == nullptr && | 1071 if (parse_info->literal() == nullptr && |
| 1013 !parsing::ParseProgram(parse_info)) { | 1072 !parsing::ParseProgram(parse_info)) { |
| 1014 return Handle<SharedFunctionInfo>::null(); | 1073 return Handle<SharedFunctionInfo>::null(); |
| 1015 } | 1074 } |
| 1016 | 1075 |
| 1017 EnsureSharedFunctionInfosArrayOnScript(parse_info); | 1076 EnsureSharedFunctionInfosArrayOnScript(parse_info); |
| 1018 | 1077 |
| 1019 FunctionLiteral* lit = parse_info->literal(); | |
| 1020 | |
| 1021 // Measure how long it takes to do the compilation; only take the | 1078 // Measure how long it takes to do the compilation; only take the |
| 1022 // rest of the function into account to avoid overlap with the | 1079 // rest of the function into account to avoid overlap with the |
| 1023 // parsing statistics. | 1080 // parsing statistics. |
| 1024 HistogramTimer* rate = parse_info->is_eval() | 1081 HistogramTimer* rate = parse_info->is_eval() |
| 1025 ? info->isolate()->counters()->compile_eval() | 1082 ? info->isolate()->counters()->compile_eval() |
| 1026 : info->isolate()->counters()->compile(); | 1083 : info->isolate()->counters()->compile(); |
| 1027 HistogramTimerScope timer(rate); | 1084 HistogramTimerScope timer(rate); |
| 1028 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), | 1085 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), |
| 1029 parse_info->is_eval() ? "V8.CompileEval" : "V8.Compile"); | 1086 parse_info->is_eval() ? "V8.CompileEval" : "V8.Compile"); |
| 1030 | 1087 |
| 1031 // Allocate a shared function info object. | 1088 // Allocate a shared function info object. |
| 1089 FunctionLiteral* lit = parse_info->literal(); |
| 1032 DCHECK_EQ(kNoSourcePosition, lit->function_token_position()); | 1090 DCHECK_EQ(kNoSourcePosition, lit->function_token_position()); |
| 1033 result = isolate->factory()->NewSharedFunctionInfoForLiteral(lit, script); | 1091 result = isolate->factory()->NewSharedFunctionInfoForLiteral(lit, script); |
| 1034 result->set_is_toplevel(true); | 1092 result->set_is_toplevel(true); |
| 1035 parse_info->set_shared_info(result); | 1093 parse_info->set_shared_info(result); |
| 1036 parse_info->set_function_literal_id(result->function_literal_id()); | 1094 parse_info->set_function_literal_id(result->function_literal_id()); |
| 1037 | 1095 |
| 1038 // Compile the code. | 1096 // Compile the code. |
| 1039 if (!CompileUnoptimizedCode(info)) { | 1097 if (!CompileUnoptimizedCode(info)) { |
| 1040 return Handle<SharedFunctionInfo>::null(); | 1098 return Handle<SharedFunctionInfo>::null(); |
| 1041 } | 1099 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1057 } | 1115 } |
| 1058 | 1116 |
| 1059 return result; | 1117 return result; |
| 1060 } | 1118 } |
| 1061 | 1119 |
| 1062 } // namespace | 1120 } // namespace |
| 1063 | 1121 |
| 1064 // ---------------------------------------------------------------------------- | 1122 // ---------------------------------------------------------------------------- |
| 1065 // Implementation of Compiler | 1123 // Implementation of Compiler |
| 1066 | 1124 |
| 1067 bool Compiler::Analyze(ParseInfo* info) { | 1125 bool Compiler::Analyze(ParseInfo* info, |
| 1126 EagerInnerFunctionLiterals* eager_literals) { |
| 1068 DCHECK_NOT_NULL(info->literal()); | 1127 DCHECK_NOT_NULL(info->literal()); |
| 1069 RuntimeCallTimerScope runtimeTimer(info->isolate(), | 1128 RuntimeCallTimerScope runtimeTimer(info->isolate(), |
| 1070 &RuntimeCallStats::CompileAnalyse); | 1129 &RuntimeCallStats::CompileAnalyse); |
| 1071 if (!Rewriter::Rewrite(info)) return false; | 1130 if (!Rewriter::Rewrite(info)) return false; |
| 1072 DeclarationScope::Analyze(info, AnalyzeMode::kRegular); | 1131 DeclarationScope::Analyze(info, AnalyzeMode::kRegular); |
| 1073 if (!Renumber(info)) return false; | 1132 if (!Renumber(info, eager_literals)) return false; |
| 1074 DCHECK_NOT_NULL(info->scope()); | 1133 DCHECK_NOT_NULL(info->scope()); |
| 1075 return true; | 1134 return true; |
| 1076 } | 1135 } |
| 1077 | 1136 |
| 1078 bool Compiler::ParseAndAnalyze(ParseInfo* info) { | 1137 bool Compiler::ParseAndAnalyze(ParseInfo* info) { |
| 1079 if (!parsing::ParseAny(info)) return false; | 1138 if (!parsing::ParseAny(info)) return false; |
| 1080 if (info->is_toplevel()) EnsureSharedFunctionInfosArrayOnScript(info); | 1139 if (info->is_toplevel()) EnsureSharedFunctionInfosArrayOnScript(info); |
| 1081 if (!Compiler::Analyze(info)) return false; | 1140 if (!Compiler::Analyze(info)) return false; |
| 1082 DCHECK_NOT_NULL(info->literal()); | 1141 DCHECK_NOT_NULL(info->literal()); |
| 1083 DCHECK_NOT_NULL(info->scope()); | 1142 DCHECK_NOT_NULL(info->scope()); |
| (...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1585 // The source was parsed lazily, so compiling for debugging is not possible. | 1644 // The source was parsed lazily, so compiling for debugging is not possible. |
| 1586 DCHECK(!compile_info.is_debug()); | 1645 DCHECK(!compile_info.is_debug()); |
| 1587 | 1646 |
| 1588 Handle<SharedFunctionInfo> result = CompileToplevel(&compile_info); | 1647 Handle<SharedFunctionInfo> result = CompileToplevel(&compile_info); |
| 1589 if (!result.is_null()) isolate->debug()->OnAfterCompile(script); | 1648 if (!result.is_null()) isolate->debug()->OnAfterCompile(script); |
| 1590 return result; | 1649 return result; |
| 1591 } | 1650 } |
| 1592 | 1651 |
| 1593 Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo( | 1652 Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo( |
| 1594 FunctionLiteral* literal, Handle<Script> script, | 1653 FunctionLiteral* literal, Handle<Script> script, |
| 1595 CompilationInfo* outer_info, LazyCompilationMode mode) { | 1654 CompilationInfo* outer_info) { |
| 1596 // Precondition: code has been parsed and scopes have been analyzed. | 1655 // Precondition: code has been parsed and scopes have been analyzed. |
| 1597 Isolate* isolate = outer_info->isolate(); | 1656 Isolate* isolate = outer_info->isolate(); |
| 1598 MaybeHandle<SharedFunctionInfo> maybe_existing; | 1657 MaybeHandle<SharedFunctionInfo> maybe_existing; |
| 1599 | 1658 |
| 1600 // Find any previously allocated shared function info for the given literal. | 1659 // Find any previously allocated shared function info for the given literal. |
| 1601 maybe_existing = script->FindSharedFunctionInfo(isolate, literal); | 1660 maybe_existing = script->FindSharedFunctionInfo(isolate, literal); |
| 1602 | 1661 |
| 1603 // We found an existing shared function info. If it has any sort of code | 1662 // If we found an existing shared function info, return it. |
| 1604 // attached, don't worry about compiling and simply return it. Otherwise, | |
| 1605 // continue to decide whether to eagerly compile. | |
| 1606 // Note that we also carry on if we are compiling eager to obtain code for | |
| 1607 // debugging, unless we already have code with debug break slots. | |
| 1608 Handle<SharedFunctionInfo> existing; | 1663 Handle<SharedFunctionInfo> existing; |
| 1609 if (maybe_existing.ToHandle(&existing)) { | 1664 if (maybe_existing.ToHandle(&existing)) { |
| 1610 DCHECK(!existing->is_toplevel()); | 1665 DCHECK(!existing->is_toplevel()); |
| 1611 if (existing->HasBaselineCode() || existing->HasBytecodeArray()) { | 1666 return existing; |
| 1612 if (!outer_info->is_debug() || existing->HasDebugCode()) { | |
| 1613 return existing; | |
| 1614 } | |
| 1615 } | |
| 1616 } | 1667 } |
| 1617 | 1668 |
| 1618 // Allocate a shared function info object. | 1669 // Allocate a shared function info object which will be compiled lazily. |
| 1619 Handle<SharedFunctionInfo> result; | 1670 Handle<SharedFunctionInfo> result = |
| 1620 if (!maybe_existing.ToHandle(&result)) { | 1671 isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script); |
| 1621 result = | 1672 result->set_is_toplevel(false); |
| 1622 isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script); | 1673 Scope* outer_scope = literal->scope()->GetOuterScopeWithContext(); |
| 1623 result->set_is_toplevel(false); | 1674 if (outer_scope) { |
| 1675 result->set_outer_scope_info(*outer_scope->scope_info()); |
| 1624 } | 1676 } |
| 1625 | |
| 1626 Zone zone(isolate->allocator(), ZONE_NAME); | |
| 1627 ParseInfo parse_info(&zone, script); | |
| 1628 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); | |
| 1629 parse_info.set_literal(literal); | |
| 1630 parse_info.set_shared_info(result); | |
| 1631 parse_info.set_function_literal_id(result->function_literal_id()); | |
| 1632 parse_info.set_language_mode(literal->scope()->language_mode()); | |
| 1633 parse_info.set_ast_value_factory( | |
| 1634 outer_info->parse_info()->ast_value_factory()); | |
| 1635 parse_info.set_ast_value_factory_owned(false); | |
| 1636 | |
| 1637 if (outer_info->will_serialize()) info.PrepareForSerializing(); | |
| 1638 if (outer_info->is_debug()) info.MarkAsDebug(); | |
| 1639 | |
| 1640 // If this inner function is already compiled, we don't need to compile | |
| 1641 // again. When compiling for debug, we are not interested in having debug | |
| 1642 // break slots in inner functions, neither for setting break points nor | |
| 1643 // for revealing inner functions. | |
| 1644 // This is especially important for generators. We must not replace the | |
| 1645 // code for generators, as there may be suspended generator objects. | |
| 1646 if (!result->is_compiled()) { | |
| 1647 if (mode == LazyCompilationMode::kAlways || | |
| 1648 !literal->ShouldEagerCompile()) { | |
| 1649 info.SetCode(isolate->builtins()->CompileLazy()); | |
| 1650 Scope* outer_scope = literal->scope()->GetOuterScopeWithContext(); | |
| 1651 if (outer_scope) { | |
| 1652 result->set_outer_scope_info(*outer_scope->scope_info()); | |
| 1653 } | |
| 1654 } else { | |
| 1655 // Generate code | |
| 1656 TimerEventScope<TimerEventCompileCode> timer(isolate); | |
| 1657 RuntimeCallTimerScope runtimeTimer( | |
| 1658 isolate, &RuntimeCallStats::CompileInnerFunction); | |
| 1659 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode"); | |
| 1660 if (Renumber(info.parse_info()) && GenerateUnoptimizedCode(&info)) { | |
| 1661 // Code generation will ensure that the feedback vector is present and | |
| 1662 // appropriately sized. | |
| 1663 DCHECK(!info.code().is_null()); | |
| 1664 if (literal->should_be_used_once_hint()) { | |
| 1665 info.code()->MarkToBeExecutedOnce(isolate); | |
| 1666 } | |
| 1667 } else { | |
| 1668 return Handle<SharedFunctionInfo>::null(); | |
| 1669 } | |
| 1670 } | |
| 1671 } | |
| 1672 | |
| 1673 if (maybe_existing.is_null()) { | |
| 1674 RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, &info); | |
| 1675 } | |
| 1676 | |
| 1677 return result; | 1677 return result; |
| 1678 } | 1678 } |
| 1679 | 1679 |
| 1680 Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForNative( | 1680 Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForNative( |
| 1681 v8::Extension* extension, Handle<String> name) { | 1681 v8::Extension* extension, Handle<String> name) { |
| 1682 Isolate* isolate = name->GetIsolate(); | 1682 Isolate* isolate = name->GetIsolate(); |
| 1683 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate); | 1683 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate); |
| 1684 | 1684 |
| 1685 // Compute the function template for the native function. | 1685 // Compute the function template for the native function. |
| 1686 v8::Local<v8::FunctionTemplate> fun_template = | 1686 v8::Local<v8::FunctionTemplate> fun_template = |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1711 | 1711 |
| 1712 MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function, | 1712 MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function, |
| 1713 BailoutId osr_ast_id, | 1713 BailoutId osr_ast_id, |
| 1714 JavaScriptFrame* osr_frame) { | 1714 JavaScriptFrame* osr_frame) { |
| 1715 DCHECK(!osr_ast_id.IsNone()); | 1715 DCHECK(!osr_ast_id.IsNone()); |
| 1716 DCHECK_NOT_NULL(osr_frame); | 1716 DCHECK_NOT_NULL(osr_frame); |
| 1717 return GetOptimizedCode(function, NOT_CONCURRENT, osr_ast_id, osr_frame); | 1717 return GetOptimizedCode(function, NOT_CONCURRENT, osr_ast_id, osr_frame); |
| 1718 } | 1718 } |
| 1719 | 1719 |
| 1720 CompilationJob* Compiler::PrepareUnoptimizedCompilationJob( | 1720 CompilationJob* Compiler::PrepareUnoptimizedCompilationJob( |
| 1721 CompilationInfo* info, LazyCompilationMode mode) { | 1721 CompilationInfo* info) { |
| 1722 VMState<COMPILER> state(info->isolate()); | 1722 VMState<COMPILER> state(info->isolate()); |
| 1723 std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info, mode)); | 1723 std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info)); |
| 1724 if (job->PrepareJob() != CompilationJob::SUCCEEDED) { | 1724 if (job->PrepareJob() != CompilationJob::SUCCEEDED) { |
| 1725 return nullptr; | 1725 return nullptr; |
| 1726 } | 1726 } |
| 1727 return job.release(); | 1727 return job.release(); |
| 1728 } | 1728 } |
| 1729 | 1729 |
| 1730 bool Compiler::FinalizeCompilationJob(CompilationJob* raw_job) { | 1730 bool Compiler::FinalizeCompilationJob(CompilationJob* raw_job) { |
| 1731 // Take ownership of compilation job. Deleting job also tears down the zone. | 1731 // Take ownership of compilation job. Deleting job also tears down the zone. |
| 1732 std::unique_ptr<CompilationJob> job(raw_job); | 1732 std::unique_ptr<CompilationJob> job(raw_job); |
| 1733 | 1733 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1769 DCHECK(shared->is_compiled()); | 1769 DCHECK(shared->is_compiled()); |
| 1770 function->set_literals(cached.literals); | 1770 function->set_literals(cached.literals); |
| 1771 } else if (shared->is_compiled()) { | 1771 } else if (shared->is_compiled()) { |
| 1772 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. | 1772 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. |
| 1773 JSFunction::EnsureLiterals(function); | 1773 JSFunction::EnsureLiterals(function); |
| 1774 } | 1774 } |
| 1775 } | 1775 } |
| 1776 | 1776 |
| 1777 } // namespace internal | 1777 } // namespace internal |
| 1778 } // namespace v8 | 1778 } // namespace v8 |
| OLD | NEW |