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 3 // found in the LICENSE file. 4 5 #include "src/compiler.h" 6 7 #include <algorithm> 8 #include <memory> 9 10 #include "src/asmjs/asm-js.h" 11 #include "src/asmjs/asm-typer.h" 12 #include "src/ast/ast-numbering.h" 13 #include "src/ast/prettyprinter.h" 14 #include "src/ast/scopes.h" 15 #include "src/bootstrapper.h" 16 #include "src/codegen.h" 17 #include "src/compilation-cache.h" 18 #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h" 19 #include "src/compiler/pipeline.h" 20 #include "src/crankshaft/hydrogen.h" 21 #include "src/debug/debug.h" 22 #include "src/debug/liveedit.h" 23 #include "src/frames-inl.h" 24 #include "src/full-codegen/full-codegen.h" 25 #include "src/globals.h" 26 #include "src/heap/heap.h" 27 #include "src/interpreter/interpreter.h" 28 #include "src/isolate-inl.h" 29 #include "src/log-inl.h" 30 #include "src/messages.h" 31 #include "src/parsing/parser.h" 32 #include "src/parsing/rewriter.h" 33 #include "src/parsing/scanner-character-streams.h" 34 #include "src/runtime-profiler.h" 35 #include "src/snapshot/code-serializer.h" 36 #include "src/vm-state-inl.h" 37 38 namespace v8 { 39 namespace internal { 40 41 42 43 // A wrapper around a CompilationInfo that detaches the Handles from 44 // the underlying DeferredHandleScope and stores them in info_ on 45 // destruction. 46 class CompilationHandleScope final { 47 public: 48 explicit CompilationHandleScope(CompilationInfo* info) 49 : deferred_(info->isolate()), info_(info) {} 50 ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); } 51 52 private: 53 DeferredHandleScope deferred_; 54 CompilationInfo* info_; 55 }; 56 57 // Helper that times a scoped region and records the elapsed time. 58 struct ScopedTimer { 59 explicit ScopedTimer(base::TimeDelta* location) : location_(location) { 60 DCHECK(location_ != NULL); 61 timer_.Start(); 62 } 63 64 ~ScopedTimer() { *location_ += timer_.Elapsed(); } 65 66 base::ElapsedTimer timer_; 67 base::TimeDelta* location_; 68 }; 69 70 // ---------------------------------------------------------------------------- 71 // Implementation of CompilationJob 72 73 CompilationJob::Status CompilationJob::PrepareJob() { 74 DCHECK(ThreadId::Current().Equals(info()->isolate()->thread_id())); 75 DisallowJavascriptExecution no_js(isolate()); 76 77 if (FLAG_trace_opt && info()->IsOptimizing()) { 78 OFStream os(stdout); 79 os << "[compiling method " << Brief(*info()->closure()) << " using " 80 << compiler_name_; 81 if (info()->is_osr()) os << " OSR"; 82 os << "]" << std::endl; 83 } 84 85 // Delegate to the underlying implementation. 86 DCHECK(state() == State::kReadyToPrepare); 87 ScopedTimer t(&time_taken_to_prepare_); 88 return UpdateState(PrepareJobImpl(), State::kReadyToExecute); 89 } 90 91 CompilationJob::Status CompilationJob::ExecuteJob() { 92 std::unique_ptr<DisallowHeapAllocation> no_allocation; 93 std::unique_ptr<DisallowHandleAllocation> no_handles; 94 std::unique_ptr<DisallowHandleDereference> no_deref; 95 std::unique_ptr<DisallowCodeDependencyChange> no_dependency_change; 96 if (can_execute_on_background_thread()) { 97 no_allocation.reset(new DisallowHeapAllocation()); 98 no_handles.reset(new DisallowHandleAllocation()); 99 no_deref.reset(new DisallowHandleDereference()); 100 no_dependency_change.reset(new DisallowCodeDependencyChange()); 101 } else { 102 DCHECK(ThreadId::Current().Equals(info()->isolate()->thread_id())); 103 } 104 105 // Delegate to the underlying implementation. 106 DCHECK(state() == State::kReadyToExecute); 107 ScopedTimer t(&time_taken_to_execute_); 108 return UpdateState(ExecuteJobImpl(), State::kReadyToFinalize); 109 } 110 111 CompilationJob::Status CompilationJob::FinalizeJob() { 112 DCHECK(ThreadId::Current().Equals(info()->isolate()->thread_id())); 113 DisallowCodeDependencyChange no_dependency_change; 114 DisallowJavascriptExecution no_js(isolate()); 115 DCHECK(!info()->dependencies()->HasAborted()); 116 117 // Delegate to the underlying implementation. 118 DCHECK(state() == State::kReadyToFinalize); 119 ScopedTimer t(&time_taken_to_finalize_); 120 return UpdateState(FinalizeJobImpl(), State::kSucceeded); 121 } 122 123 CompilationJob::Status CompilationJob::RetryOptimization(BailoutReason reason) { 124 DCHECK(info_->IsOptimizing()); 125 info_->RetryOptimization(reason); 126 state_ = State::kFailed; 127 return FAILED; 128 } 129 130 CompilationJob::Status CompilationJob::AbortOptimization(BailoutReason reason) { 131 DCHECK(info_->IsOptimizing()); 132 info_->AbortOptimization(reason); 133 state_ = State::kFailed; 134 return FAILED; 135 } 136 137 void CompilationJob::RecordUnoptimizedCompilationStats() const { 138 int code_size; 139 if (info()->has_bytecode_array()) { 140 code_size = info()->bytecode_array()->SizeIncludingMetadata(); 141 } else { 142 code_size = info()->code()->SizeIncludingMetadata(); 143 } 144 145 Counters* counters = isolate()->counters(); 146 // TODO(4280): Rename counters from "baseline" to "unoptimized" eventually. 147 counters->total_baseline_code_size()->Increment(code_size); 148 counters->total_baseline_compile_count()->Increment(1); 149 150 // TODO(5203): Add timers for each phase of compilation. 151 } 152 153 void CompilationJob::RecordOptimizedCompilationStats() const { 154 DCHECK(info()->IsOptimizing()); 155 Handle<JSFunction> function = info()->closure(); 156 if (!function->IsOptimized()) { 157 // Concurrent recompilation and OSR may race. Increment only once. 158 int opt_count = function->shared()->opt_count(); 159 function->shared()->set_opt_count(opt_count + 1); 160 } 161 double ms_creategraph = time_taken_to_prepare_.InMillisecondsF(); 162 double ms_optimize = time_taken_to_execute_.InMillisecondsF(); 163 double ms_codegen = time_taken_to_finalize_.InMillisecondsF(); 164 if (FLAG_trace_opt) { 165 PrintF("[optimizing "); 166 function->ShortPrint(); 167 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize, 168 ms_codegen); 169 } 170 if (FLAG_trace_opt_stats) { 171 static double compilation_time = 0.0; 172 static int compiled_functions = 0; 173 static int code_size = 0; 174 175 compilation_time += (ms_creategraph + ms_optimize + ms_codegen); 176 compiled_functions++; 177 code_size += function->shared()->SourceSize(); 178 PrintF("Compiled: %d functions with %d byte source size in %fms.\n", 179 compiled_functions, code_size, compilation_time); 180 } 181 if (FLAG_hydrogen_stats) { 182 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_prepare_, 183 time_taken_to_execute_, 184 time_taken_to_finalize_); 185 } 186 } 187 188 Isolate* CompilationJob::isolate() const { return info()->isolate(); } 189 190 namespace { 191 192 void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object, 193 Handle<Code> code) { 194 Handle<WeakCell> cell = Code::WeakCellFor(code); 195 Heap* heap = isolate->heap(); 196 if (heap->InNewSpace(*object)) { 197 heap->AddWeakNewSpaceObjectToCodeDependency(object, cell); 198 } else { 199 Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object)); 200 dep = 201 DependentCode::InsertWeakCode(dep, DependentCode::kWeakCodeGroup, cell); 202 heap->AddWeakObjectToCodeDependency(object, dep); 203 } 204 } 205 206 } // namespace 207 208 void CompilationJob::RegisterWeakObjectsInOptimizedCode(Handle<Code> code) { 209 // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies. 210 Isolate* const isolate = code->GetIsolate(); 211 DCHECK(code->is_optimized_code()); 212 std::vector<Handle<Map>> maps; 213 std::vector<Handle<HeapObject>> objects; 214 { 215 DisallowHeapAllocation no_gc; 216 int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | 217 RelocInfo::ModeMask(RelocInfo::CELL); 218 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { 219 RelocInfo::Mode mode = it.rinfo()->rmode(); 220 if (mode == RelocInfo::CELL && 221 code->IsWeakObjectInOptimizedCode(it.rinfo()->target_cell())) { 222 objects.push_back(handle(it.rinfo()->target_cell(), isolate)); 223 } else if (mode == RelocInfo::EMBEDDED_OBJECT && 224 code->IsWeakObjectInOptimizedCode( 225 it.rinfo()->target_object())) { 226 Handle<HeapObject> object(HeapObject::cast(it.rinfo()->target_object()), 227 isolate); 228 if (object->IsMap()) { 229 maps.push_back(Handle<Map>::cast(object)); 230 } else { 231 objects.push_back(object); 232 } 233 } 234 } 235 } 236 for (Handle<Map> map : maps) { 237 if (map->dependent_code()->IsEmpty(DependentCode::kWeakCodeGroup)) { 238 isolate->heap()->AddRetainedMap(map); 239 } 240 Map::AddDependentCode(map, DependentCode::kWeakCodeGroup, code); 241 } 242 for (Handle<HeapObject> object : objects) { 243 AddWeakObjectToCodeDependency(isolate, object, code); 244 } 245 code->set_can_have_weak_objects(true); 246 } 247 248 // ---------------------------------------------------------------------------- 249 // Local helper methods that make up the compilation pipeline. 250 251 namespace { 252 253 void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag, 254 CompilationInfo* info) { 255 // Log the code generation. If source information is available include 256 // script name and line number. Check explicitly whether logging is 257 // enabled as finding the line number is not free. 258 if (info->isolate()->logger()->is_logging_code_events() || 259 info->isolate()->is_profiling()) { 260 Handle<SharedFunctionInfo> shared = info->shared_info(); 261 Handle<Script> script = info->parse_info()->script(); 262 Handle<AbstractCode> abstract_code = 263 info->has_bytecode_array() 264 ? Handle<AbstractCode>::cast(info->bytecode_array()) 265 : Handle<AbstractCode>::cast(info->code()); 266 if (abstract_code.is_identical_to( 267 info->isolate()->builtins()->CompileLazy())) { 268 return; 269 } 270 int line_num = Script::GetLineNumber(script, shared->start_position()) + 1; 271 int column_num = 272 Script::GetColumnNumber(script, shared->start_position()) + 1; 273 String* script_name = script->name()->IsString() 274 ? String::cast(script->name()) 275 : info->isolate()->heap()->empty_string(); 276 CodeEventListener::LogEventsAndTags log_tag = 277 Logger::ToNativeByScript(tag, *script); 278 PROFILE(info->isolate(), 279 CodeCreateEvent(log_tag, *abstract_code, *shared, script_name, 280 line_num, column_num)); 281 } 282 } 283 284 void EnsureFeedbackMetadata(CompilationInfo* info) { 285 DCHECK(info->has_shared_info()); 286 287 // If no type feedback metadata exists, we create it now. At this point the 288 // AstNumbering pass has already run. Note the snapshot can contain outdated 289 // vectors for a different configuration, hence we also recreate a new vector 290 // when the function is not compiled (i.e. no code was serialized). 291 292 // TODO(mvstanton): reintroduce is_empty() predicate to feedback_metadata(). 293 if (info->shared_info()->feedback_metadata()->length() == 0 || 294 !info->shared_info()->is_compiled()) { 295 Handle<TypeFeedbackMetadata> feedback_metadata = TypeFeedbackMetadata::New( 296 info->isolate(), info->literal()->feedback_vector_spec()); 297 info->shared_info()->set_feedback_metadata(*feedback_metadata); 298 } 299 300 // It's very important that recompiles do not alter the structure of the type 301 // feedback vector. Verify that the structure fits the function literal. 302 CHECK(!info->shared_info()->feedback_metadata()->SpecDiffersFrom( 303 info->literal()->feedback_vector_spec())); 304 } 305 306 bool UseTurboFan(Handle<SharedFunctionInfo> shared) { 307 bool optimization_disabled = shared->optimization_disabled(); 308 bool dont_crankshaft = shared->dont_crankshaft(); 309 310 // Check the enabling conditions for Turbofan. 311 // 1. "use asm" code. 312 bool is_turbofanable_asm = 313 FLAG_turbo_asm && shared->asm_function() && !optimization_disabled; 314 315 // 2. Fallback for features unsupported by Crankshaft. 316 bool is_unsupported_by_crankshaft_but_turbofanable = 317 dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 && 318 !optimization_disabled; 319 320 // 3. Explicitly enabled by the command-line filter. 321 bool passes_turbo_filter = shared->PassesFilter(FLAG_turbo_filter); 322 323 return is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable || 324 passes_turbo_filter; 325 } 326 327 bool ShouldUseIgnition(CompilationInfo* info) { 328 DCHECK(info->has_shared_info()); 329 330 // Skip Ignition for asm.js functions. 331 if (info->shared_info()->asm_function()) { 332 return false; 333 } 334 335 // When requesting debug code as a replacement for existing code, we provide 336 // the same kind as the existing code (to prevent implicit tier-change). 337 if (info->is_debug() && info->shared_info()->is_compiled()) { 338 return !info->shared_info()->HasBaselineCode(); 339 } 340 341 // Code destined for TurboFan should be compiled with Ignition first. 342 if (UseTurboFan(info->shared_info())) return true; 343 344 // Only use Ignition for any other function if FLAG_ignition is true. 345 if (!FLAG_ignition) return false; 346 347 // Checks whether top level functions should be passed by the filter. 348 if (info->shared_info()->is_toplevel()) { 349 Vector<const char> filter = CStrVector(FLAG_ignition_filter); 350 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*'); 351 } 352 353 // Finally respect the filter. 354 return info->shared_info()->PassesFilter(FLAG_ignition_filter); 355 } 356 357 CompilationJob* GetUnoptimizedCompilationJob(CompilationInfo* info) { 358 // Function should have been parsed and analyzed before creating a compilation 359 // job. 360 DCHECK_NOT_NULL(info->literal()); 361 DCHECK_NOT_NULL(info->scope()); 362 363 EnsureFeedbackMetadata(info); 364 if (ShouldUseIgnition(info)) { 365 return interpreter::Interpreter::NewCompilationJob(info); 366 } else { 367 return FullCodeGenerator::NewCompilationJob(info); 368 } 369 } 370 371 void InstallSharedScopeInfo(CompilationInfo* info, 372 Handle<SharedFunctionInfo> shared) { 373 Handle<ScopeInfo> scope_info = info->scope()->scope_info(); 374 shared->set_scope_info(*scope_info); 375 Scope* outer_scope = info->scope()->GetOuterScopeWithContext(); 376 if (outer_scope) { 377 shared->set_outer_scope_info(*outer_scope->scope_info()); 378 } 379 } 380 381 void InstallSharedCompilationResult(CompilationInfo* info, 382 Handle<SharedFunctionInfo> shared) { 383 // TODO(mstarzinger): Compiling for debug code might be used to reveal inner 384 // functions via {FindSharedFunctionInfoInScript}, in which case we end up 385 // regenerating existing bytecode. Fix this! 386 if (info->is_debug() && info->has_bytecode_array()) { 387 shared->ClearBytecodeArray(); 388 } 389 DCHECK(!info->code().is_null()); 390 shared->ReplaceCode(*info->code()); 391 if (info->has_bytecode_array()) { 392 DCHECK(!shared->HasBytecodeArray()); // Only compiled once. 393 shared->set_bytecode_array(*info->bytecode_array()); 394 } 395 } 396 397 void InstallUnoptimizedCode(CompilationInfo* info) { 398 Handle<SharedFunctionInfo> shared = info->shared_info(); 399 400 // Update the shared function info with the scope info. 401 InstallSharedScopeInfo(info, shared); 402 403 // Install compilation result on the shared function info 404 InstallSharedCompilationResult(info, shared); 405 } 406 407 CompilationJob::Status FinalizeUnoptimizedCompilationJob(CompilationJob* job) { 408 CompilationJob::Status status = job->FinalizeJob(); 409 if (status == CompilationJob::SUCCEEDED) { 410 InstallUnoptimizedCode(job->info()); 411 job->RecordUnoptimizedCompilationStats(); 412 } 413 return status; 414 } 415 416 bool GenerateUnoptimizedCode(CompilationInfo* info) { 417 if (FLAG_validate_asm && info->scope()->asm_module() && 418 !info->shared_info()->is_asm_wasm_broken() && !info->is_debug()) { 419 EnsureFeedbackMetadata(info); 420 MaybeHandle<FixedArray> wasm_data; 421 wasm_data = AsmJs::ConvertAsmToWasm(info->parse_info()); 422 if (!wasm_data.is_null()) { 423 info->shared_info()->set_asm_wasm_data(*wasm_data.ToHandleChecked()); 424 info->SetCode(info->isolate()->builtins()->InstantiateAsmJs()); 425 InstallUnoptimizedCode(info); 426 return true; 427 } 428 } 429 430 std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info)); 431 if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false; 432 if (job->ExecuteJob() != CompilationJob::SUCCEEDED) return false; 433 if (FinalizeUnoptimizedCompilationJob(job.get()) != 434 CompilationJob::SUCCEEDED) { 435 return false; 436 } 437 return true; 438 } 439 440 bool CompileUnoptimizedCode(CompilationInfo* info) { 441 DCHECK(AllowCompilation::IsAllowed(info->isolate())); 442 if (!Compiler::Analyze(info->parse_info()) || 443 !GenerateUnoptimizedCode(info)) { 444 Isolate* isolate = info->isolate(); 445 if (!isolate->has_pending_exception()) isolate->StackOverflow(); 446 return false; 447 } 448 return true; 449 } 450 451 MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode(CompilationInfo* info) { 452 VMState<COMPILER> state(info->isolate()); 453 PostponeInterruptsScope postpone(info->isolate()); 454 455 // Parse and update CompilationInfo with the results. 456 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>(); 457 DCHECK_EQ(info->shared_info()->language_mode(), 458 info->literal()->language_mode()); 459 460 // Compile either unoptimized code or bytecode for the interpreter. 461 if (!CompileUnoptimizedCode(info)) return MaybeHandle<Code>(); 462 463 // Record the function compilation event. 464 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); 465 466 return info->code(); 467 } 468 469 MUST_USE_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeMap( 470 Handle<JSFunction> function, BailoutId osr_ast_id) { 471 Handle<SharedFunctionInfo> shared(function->shared()); 472 DisallowHeapAllocation no_gc; 473 CodeAndLiterals cached = shared->SearchOptimizedCodeMap( 474 function->context()->native_context(), osr_ast_id); 475 if (cached.code != nullptr) { 476 // Caching of optimized code enabled and optimized code found. 477 if (cached.literals != nullptr) function->set_literals(cached.literals); 478 DCHECK(!cached.code->marked_for_deoptimization()); 479 DCHECK(function->shared()->is_compiled()); 480 return Handle<Code>(cached.code); 481 } 482 return MaybeHandle<Code>(); 483 } 484 485 void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) { 486 Handle<Code> code = info->code(); 487 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do. 488 489 // Function context specialization folds-in the function context, 490 // so no sharing can occur. 491 if (info->is_function_context_specializing()) return; 492 // Frame specialization implies function context specialization. 493 DCHECK(!info->is_frame_specializing()); 494 495 // TODO(4764): When compiling for OSR from bytecode, BailoutId might derive 496 // from bytecode offset and overlap with actual BailoutId. No caching! 497 if (info->is_osr() && info->is_optimizing_from_bytecode()) return; 498 499 // Cache optimized context-specific code. 500 Handle<JSFunction> function = info->closure(); 501 Handle<SharedFunctionInfo> shared(function->shared()); 502 Handle<LiteralsArray> literals(function->literals()); 503 Handle<Context> native_context(function->context()->native_context()); 504 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, 505 literals, info->osr_ast_id()); 506 } 507 508 bool Renumber(ParseInfo* parse_info) { 509 if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(), 510 parse_info->literal())) { 511 return false; 512 } 513 Handle<SharedFunctionInfo> shared_info = parse_info->shared_info(); 514 if (!shared_info.is_null()) { 515 FunctionLiteral* lit = parse_info->literal(); 516 shared_info->set_ast_node_count(lit->ast_node_count()); 517 if (lit->dont_optimize_reason() != kNoReason) { 518 shared_info->DisableOptimization(lit->dont_optimize_reason()); 519 } 520 if (lit->flags() & AstProperties::kDontCrankshaft) { 521 shared_info->set_dont_crankshaft(true); 522 } 523 } 524 return true; 525 } 526 527 bool GetOptimizedCodeNow(CompilationJob* job) { 528 CompilationInfo* info = job->info(); 529 Isolate* isolate = info->isolate(); 530 531 // Parsing is not required when optimizing from existing bytecode. 532 if (!info->is_optimizing_from_bytecode()) { 533 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; 534 EnsureFeedbackMetadata(info); 535 } 536 537 JSFunction::EnsureLiterals(info->closure()); 538 539 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate); 540 RuntimeCallTimerScope runtimeTimer(isolate, 541 &RuntimeCallStats::RecompileSynchronous); 542 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), 543 "V8.RecompileSynchronous"); 544 545 if (job->PrepareJob() != CompilationJob::SUCCEEDED || 546 job->ExecuteJob() != CompilationJob::SUCCEEDED || 547 job->FinalizeJob() != CompilationJob::SUCCEEDED) { 548 if (FLAG_trace_opt) { 549 PrintF("[aborted optimizing "); 550 info->closure()->ShortPrint(); 551 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); 552 } 553 return false; 554 } 555 556 // Success! 557 job->RecordOptimizedCompilationStats(); 558 DCHECK(!isolate->has_pending_exception()); 559 InsertCodeIntoOptimizedCodeMap(info); 560 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); 561 return true; 562 } 563 564 bool GetOptimizedCodeLater(CompilationJob* job) { 565 CompilationInfo* info = job->info(); 566 Isolate* isolate = info->isolate(); 567 568 if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) { 569 if (FLAG_trace_concurrent_recompilation) { 570 PrintF(" ** Compilation queue full, will retry optimizing "); 571 info->closure()->ShortPrint(); 572 PrintF(" later.\n"); 573 } 574 return false; 575 } 576 577 if (isolate->heap()->HighMemoryPressure()) { 578 if (FLAG_trace_concurrent_recompilation) { 579 PrintF(" ** High memory pressure, will retry optimizing "); 580 info->closure()->ShortPrint(); 581 PrintF(" later.\n"); 582 } 583 return false; 584 } 585 586 // Parsing is not required when optimizing from existing bytecode. 587 if (!info->is_optimizing_from_bytecode()) { 588 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; 589 EnsureFeedbackMetadata(info); 590 } 591 592 JSFunction::EnsureLiterals(info->closure()); 593 594 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); 595 RuntimeCallTimerScope runtimeTimer(info->isolate(), 596 &RuntimeCallStats::RecompileSynchronous); 597 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), 598 "V8.RecompileSynchronous"); 599 600 if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false; 601 isolate->optimizing_compile_dispatcher()->QueueForOptimization(job); 602 603 if (FLAG_trace_concurrent_recompilation) { 604 PrintF(" ** Queued "); 605 info->closure()->ShortPrint(); 606 PrintF(" for concurrent optimization.\n"); 607 } 608 return true; 609 } 610 611 MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function, 612 Compiler::ConcurrencyMode mode, 613 BailoutId osr_ast_id = BailoutId::None(), 614 JavaScriptFrame* osr_frame = nullptr) { 615 Isolate* isolate = function->GetIsolate(); 616 Handle<SharedFunctionInfo> shared(function->shared(), isolate); 617 618 bool ignition_osr = osr_frame && osr_frame->is_interpreted(); 619 DCHECK_IMPLIES(ignition_osr, !osr_ast_id.IsNone()); 620 DCHECK_IMPLIES(ignition_osr, FLAG_ignition_osr); 621 622 // Shared function no longer needs to be tiered up 623 shared->set_marked_for_tier_up(false); 624 625 Handle<Code> cached_code; 626 // TODO(4764): When compiling for OSR from bytecode, BailoutId might derive 627 // from bytecode offset and overlap with actual BailoutId. No lookup! 628 if (!ignition_osr && 629 GetCodeFromOptimizedCodeMap(function, osr_ast_id) 630 .ToHandle(&cached_code)) { 631 if (FLAG_trace_opt) { 632 PrintF("[found optimized code for "); 633 function->ShortPrint(); 634 if (!osr_ast_id.IsNone()) { 635 PrintF(" at OSR AST id %d", osr_ast_id.ToInt()); 636 } 637 PrintF("]\n"); 638 } 639 return cached_code; 640 } 641 642 // Reset profiler ticks, function is no longer considered hot. 643 if (shared->HasBaselineCode()) { 644 shared->code()->set_profiler_ticks(0); 645 } else if (shared->HasBytecodeArray()) { 646 shared->set_profiler_ticks(0); 647 } 648 649 VMState<COMPILER> state(isolate); 650 DCHECK(!isolate->has_pending_exception()); 651 PostponeInterruptsScope postpone(isolate); 652 bool use_turbofan = UseTurboFan(shared) || ignition_osr; 653 std::unique_ptr<CompilationJob> job( 654 use_turbofan ? compiler::Pipeline::NewCompilationJob(function) 655 : new HCompilationJob(function)); 656 CompilationInfo* info = job->info(); 657 ParseInfo* parse_info = info->parse_info(); 658 659 info->SetOptimizingForOsr(osr_ast_id, osr_frame); 660 661 // Do not use Crankshaft/TurboFan if we need to be able to set break points. 662 if (info->shared_info()->HasDebugInfo()) { 663 info->AbortOptimization(kFunctionBeingDebugged); 664 return MaybeHandle<Code>(); 665 } 666 667 // Limit the number of times we try to optimize functions. 668 const int kMaxOptCount = 669 FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000; 670 if (info->shared_info()->opt_count() > kMaxOptCount) { 671 info->AbortOptimization(kOptimizedTooManyTimes); 672 return MaybeHandle<Code>(); 673 } 674 675 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate); 676 RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::OptimizeCode); 677 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.OptimizeCode"); 678 679 // TurboFan can optimize directly from existing bytecode. 680 if (use_turbofan && ShouldUseIgnition(info)) { 681 if (info->is_osr() && !ignition_osr) return MaybeHandle<Code>(); 682 if (!Compiler::EnsureBytecode(info)) { 683 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); 684 return MaybeHandle<Code>(); 685 } 686 info->MarkAsOptimizeFromBytecode(); 687 } 688 689 // Verify that OSR compilations are delegated to the correct graph builder. 690 // Depending on the underlying frame the semantics of the {BailoutId} differ 691 // and the various graph builders hard-code a certain semantic: 692 // - Interpreter : The BailoutId represents a bytecode offset. 693 // - FullCodegen : The BailoutId represents the id of an AST node. 694 DCHECK_IMPLIES(info->is_osr() && ignition_osr, 695 info->is_optimizing_from_bytecode()); 696 DCHECK_IMPLIES(info->is_osr() && !ignition_osr, 697 !info->is_optimizing_from_bytecode()); 698 699 // In case of concurrent recompilation, all handles below this point will be 700 // allocated in a deferred handle scope that is detached and handed off to 701 // the background thread when we return. 702 std::unique_ptr<CompilationHandleScope> compilation; 703 if (mode == Compiler::CONCURRENT) { 704 compilation.reset(new CompilationHandleScope(info)); 705 } 706 707 // In case of TurboFan, all handles below will be canonicalized. 708 std::unique_ptr<CanonicalHandleScope> canonical; 709 if (use_turbofan) canonical.reset(new CanonicalHandleScope(info->isolate())); 710 711 // Reopen handles in the new CompilationHandleScope. 712 info->ReopenHandlesInNewHandleScope(); 713 parse_info->ReopenHandlesInNewHandleScope(); 714 715 if (mode == Compiler::CONCURRENT) { 716 if (GetOptimizedCodeLater(job.get())) { 717 job.release(); // The background recompile job owns this now. 718 return isolate->builtins()->InOptimizationQueue(); 719 } 720 } else { 721 if (GetOptimizedCodeNow(job.get())) return info->code(); 722 } 723 724 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); 725 return MaybeHandle<Code>(); 726 } 727 728 CompilationJob::Status FinalizeOptimizedCompilationJob(CompilationJob* job) { 729 CompilationInfo* info = job->info(); 730 Isolate* isolate = info->isolate(); 731 732 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); 733 RuntimeCallTimerScope runtimeTimer(isolate, 734 &RuntimeCallStats::RecompileSynchronous); 735 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), 736 "V8.RecompileSynchronous"); 737 738 Handle<SharedFunctionInfo> shared = info->shared_info(); 739 740 // Reset profiler ticks, function is no longer considered hot. 741 if (shared->HasBaselineCode()) { 742 shared->code()->set_profiler_ticks(0); 743 } else if (shared->HasBytecodeArray()) { 744 shared->set_profiler_ticks(0); 745 } 746 747 DCHECK(!shared->HasDebugInfo()); 748 749 // 1) Optimization on the concurrent thread may have failed. 750 // 2) The function may have already been optimized by OSR. Simply continue. 751 // Except when OSR already disabled optimization for some reason. 752 // 3) The code may have already been invalidated due to dependency change. 753 // 4) Code generation may have failed. 754 if (job->state() == CompilationJob::State::kReadyToFinalize) { 755 if (shared->optimization_disabled()) { 756 job->RetryOptimization(kOptimizationDisabled); 757 } else if (info->dependencies()->HasAborted()) { 758 job->RetryOptimization(kBailedOutDueToDependencyChange); 759 } else if (job->FinalizeJob() == CompilationJob::SUCCEEDED) { 760 job->RecordOptimizedCompilationStats(); 761 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); 762 if (shared 763 ->SearchOptimizedCodeMap(info->context()->native_context(), 764 info->osr_ast_id()) 765 .code == nullptr) { 766 InsertCodeIntoOptimizedCodeMap(info); 767 } 768 if (FLAG_trace_opt) { 769 PrintF("[completed optimizing "); 770 info->closure()->ShortPrint(); 771 PrintF("]\n"); 772 } 773 info->closure()->ReplaceCode(*info->code()); 774 return CompilationJob::SUCCEEDED; 775 } 776 } 777 778 DCHECK(job->state() == CompilationJob::State::kFailed); 779 if (FLAG_trace_opt) { 780 PrintF("[aborted optimizing "); 781 info->closure()->ShortPrint(); 782 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); 783 } 784 info->closure()->ReplaceCode(shared->code()); 785 return CompilationJob::FAILED; 786 } 787 788 MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) { 789 Isolate* isolate = function->GetIsolate(); 790 VMState<COMPILER> state(isolate); 791 PostponeInterruptsScope postpone(isolate); 792 Zone zone(isolate->allocator(), ZONE_NAME); 793 ParseInfo parse_info(&zone, handle(function->shared())); 794 CompilationInfo info(&parse_info, function); 795 796 // Function no longer needs to be tiered up 797 function->shared()->set_marked_for_tier_up(false); 798 799 // Reset profiler ticks, function is no longer considered hot. 800 if (function->shared()->HasBytecodeArray()) { 801 function->shared()->set_profiler_ticks(0); 802 } 803 804 // Nothing left to do if the function already has baseline code. 805 if (function->shared()->code()->kind() == Code::FUNCTION) { 806 return Handle<Code>(function->shared()->code()); 807 } 808 809 // We do not switch to baseline code when the debugger might have created a 810 // copy of the bytecode with break slots to be able to set break points. 811 if (function->shared()->HasDebugInfo()) { 812 return MaybeHandle<Code>(); 813 } 814 815 // TODO(4280): For now we do not switch generators or async functions to 816 // baseline code because there might be suspended activations stored in 817 // generator objects on the heap. We could eventually go directly to 818 // TurboFan in this case. 819 if (IsResumableFunction(function->shared()->kind())) { 820 return MaybeHandle<Code>(); 821 } 822 823 if (FLAG_trace_opt) { 824 OFStream os(stdout); 825 os << "[switching method " << Brief(*function) << " to baseline code]" 826 << std::endl; 827 } 828 829 // Parse and update CompilationInfo with the results. 830 if (!Parser::ParseStatic(info.parse_info())) return MaybeHandle<Code>(); 831 Handle<SharedFunctionInfo> shared = info.shared_info(); 832 DCHECK_EQ(shared->language_mode(), info.literal()->language_mode()); 833 834 // Compile baseline code using the full code generator. 835 if (!Compiler::Analyze(info.parse_info()) || 836 !FullCodeGenerator::MakeCode(&info)) { 837 if (!isolate->has_pending_exception()) isolate->StackOverflow(); 838 return MaybeHandle<Code>(); 839 } 840 841 // Update the shared function info with the scope info. 842 InstallSharedScopeInfo(&info, shared); 843 844 // Install compilation result on the shared function info 845 InstallSharedCompilationResult(&info, shared); 846 847 // Record the function compilation event. 848 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, &info); 849 850 return info.code(); 851 } 852 853 MaybeHandle<Code> GetLazyCode(Handle<JSFunction> function) { 854 Isolate* isolate = function->GetIsolate(); 855 DCHECK(!isolate->has_pending_exception()); 856 DCHECK(!function->is_compiled()); 857 TimerEventScope<TimerEventCompileCode> compile_timer(isolate); 858 RuntimeCallTimerScope runtimeTimer(isolate, 859 &RuntimeCallStats::CompileCodeLazy); 860 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode"); 861 AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy()); 862 863 Handle<Code> cached_code; 864 if (GetCodeFromOptimizedCodeMap(function, BailoutId::None()) 865 .ToHandle(&cached_code)) { 866 if (FLAG_trace_opt) { 867 PrintF("[found optimized code for "); 868 function->ShortPrint(); 869 PrintF(" during unoptimized compile]\n"); 870 } 871 DCHECK(function->shared()->is_compiled()); 872 return cached_code; 873 } 874 875 if (function->shared()->marked_for_tier_up()) { 876 DCHECK(FLAG_mark_shared_functions_for_tier_up); 877 878 function->shared()->set_marked_for_tier_up(false); 879 880 switch (Compiler::NextCompilationTier(*function)) { 881 case Compiler::BASELINE: { 882 if (FLAG_trace_opt) { 883 PrintF("[recompiling function "); 884 function->ShortPrint(); 885 PrintF( 886 " to baseline eagerly (shared function marked for tier up)]\n"); 887 } 888 889 Handle<Code> code; 890 if (GetBaselineCode(function).ToHandle(&code)) { 891 return code; 892 } 893 break; 894 } 895 case Compiler::OPTIMIZED: { 896 if (FLAG_trace_opt) { 897 PrintF("[optimizing method "); 898 function->ShortPrint(); 899 PrintF(" eagerly (shared function marked for tier up)]\n"); 900 } 901 902 Handle<Code> code; 903 // TODO(leszeks): Look into performing this compilation concurrently. 904 if (GetOptimizedCode(function, Compiler::NOT_CONCURRENT) 905 .ToHandle(&code)) { 906 return code; 907 } 908 break; 909 } 910 default: 911 UNREACHABLE(); 912 } 913 } 914 915 if (function->shared()->is_compiled()) { 916 return Handle<Code>(function->shared()->code()); 917 } 918 919 if (function->shared()->HasBytecodeArray()) { 920 Handle<Code> entry = isolate->builtins()->InterpreterEntryTrampoline(); 921 function->shared()->ReplaceCode(*entry); 922 return entry; 923 } 924 925 Zone zone(isolate->allocator(), ZONE_NAME); 926 ParseInfo parse_info(&zone, handle(function->shared())); 927 CompilationInfo info(&parse_info, function); 928 Handle<Code> result; 929 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, GetUnoptimizedCode(&info), Code); 930 931 if (FLAG_always_opt) { 932 Handle<Code> opt_code; 933 if (GetOptimizedCode(function, Compiler::NOT_CONCURRENT) 934 .ToHandle(&opt_code)) { 935 result = opt_code; 936 } 937 } 938 939 return result; 940 } 941 942 943 Handle<SharedFunctionInfo> NewSharedFunctionInfoForLiteral( 944 Isolate* isolate, FunctionLiteral* literal, Handle<Script> script) { 945 Handle<Code> code = isolate->builtins()->CompileLazy(); 946 Handle<ScopeInfo> scope_info = handle(ScopeInfo::Empty(isolate)); 947 Handle<SharedFunctionInfo> result = isolate->factory()->NewSharedFunctionInfo( 948 literal->name(), literal->materialized_literal_count(), literal->kind(), 949 code, scope_info); 950 SharedFunctionInfo::InitFromFunctionLiteral(result, literal); 951 SharedFunctionInfo::SetScript(result, script); 952 return result; 953 } 954 955 Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) { 956 Isolate* isolate = info->isolate(); 957 TimerEventScope<TimerEventCompileCode> timer(isolate); 958 RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::CompileCode); 959 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode"); 960 PostponeInterruptsScope postpone(isolate); 961 DCHECK(!isolate->native_context().is_null()); 962 ParseInfo* parse_info = info->parse_info(); 963 Handle<Script> script = parse_info->script(); 964 965 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile? 966 FixedArray* array = isolate->native_context()->embedder_data(); 967 script->set_context_data(array->get(v8::Context::kDebugIdIndex)); 968 969 isolate->debug()->OnBeforeCompile(script); 970 971 Handle<SharedFunctionInfo> result; 972 973 { VMState<COMPILER> state(info->isolate()); 974 if (parse_info->literal() == nullptr && !Parser::ParseStatic(parse_info)) { 975 return Handle<SharedFunctionInfo>::null(); 976 } 977 978 FunctionLiteral* lit = parse_info->literal(); 979 980 // Measure how long it takes to do the compilation; only take the 981 // rest of the function into account to avoid overlap with the 982 // parsing statistics. 983 RuntimeCallTimerScope runtimeTimer( 984 isolate, parse_info->is_eval() ? &RuntimeCallStats::CompileEval 985 : &RuntimeCallStats::Compile); 986 HistogramTimer* rate = parse_info->is_eval() 987 ? info->isolate()->counters()->compile_eval() 988 : info->isolate()->counters()->compile(); 989 HistogramTimerScope timer(rate); 990 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), 991 parse_info->is_eval() ? "V8.CompileEval" : "V8.Compile"); 992 993 // Allocate a shared function info object. 994 DCHECK_EQ(kNoSourcePosition, lit->function_token_position()); 995 result = NewSharedFunctionInfoForLiteral(isolate, lit, script); 996 result->set_is_toplevel(true); 997 parse_info->set_shared_info(result); 998 999 // Compile the code. 1000 if (!CompileUnoptimizedCode(info)) { 1001 return Handle<SharedFunctionInfo>::null(); 1002 } 1003 1004 Handle<String> script_name = 1005 script->name()->IsString() 1006 ? Handle<String>(String::cast(script->name())) 1007 : isolate->factory()->empty_string(); 1008 CodeEventListener::LogEventsAndTags log_tag = 1009 parse_info->is_eval() 1010 ? CodeEventListener::EVAL_TAG 1011 : Logger::ToNativeByScript(CodeEventListener::SCRIPT_TAG, *script); 1012 1013 PROFILE(isolate, CodeCreateEvent(log_tag, result->abstract_code(), *result, 1014 *script_name)); 1015 1016 if (!script.is_null()) 1017 script->set_compilation_state(Script::COMPILATION_STATE_COMPILED); 1018 } 1019 1020 return result; 1021 } 1022 1023 } // namespace 1024 1025 // ---------------------------------------------------------------------------- 1026 // Implementation of Compiler 1027 1028 bool Compiler::Analyze(ParseInfo* info) { 1029 DCHECK_NOT_NULL(info->literal()); 1030 if (!Rewriter::Rewrite(info)) return false; 1031 DeclarationScope::Analyze(info, AnalyzeMode::kRegular); 1032 if (!Renumber(info)) return false; 1033 DCHECK_NOT_NULL(info->scope()); 1034 return true; 1035 } 1036 1037 bool Compiler::ParseAndAnalyze(ParseInfo* info) { 1038 if (!Parser::ParseStatic(info)) return false; 1039 if (!Compiler::Analyze(info)) return false; 1040 DCHECK_NOT_NULL(info->literal()); 1041 DCHECK_NOT_NULL(info->scope()); 1042 return true; 1043 } 1044 1045 bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) { 1046 if (function->is_compiled()) return true; 1047 Isolate* isolate = function->GetIsolate(); 1048 DCHECK(AllowCompilation::IsAllowed(isolate)); 1049 1050 // Start a compilation. 1051 Handle<Code> code; 1052 if (!GetLazyCode(function).ToHandle(&code)) { 1053 if (flag == CLEAR_EXCEPTION) { 1054 isolate->clear_pending_exception(); 1055 } 1056 return false; 1057 } 1058 1059 // Install code on closure. 1060 function->ReplaceCode(*code); 1061 JSFunction::EnsureLiterals(function); 1062 1063 // Check postconditions on success. 1064 DCHECK(!isolate->has_pending_exception()); 1065 DCHECK(function->shared()->is_compiled()); 1066 DCHECK(function->is_compiled()); 1067 return true; 1068 } 1069 1070 bool Compiler::CompileBaseline(Handle<JSFunction> function) { 1071 Isolate* isolate = function->GetIsolate(); 1072 DCHECK(AllowCompilation::IsAllowed(isolate)); 1073 1074 // Start a compilation. 1075 Handle<Code> code; 1076 if (!GetBaselineCode(function).ToHandle(&code)) { 1077 // Baseline generation failed, get unoptimized code. 1078 DCHECK(function->shared()->is_compiled()); 1079 code = handle(function->shared()->code()); 1080 isolate->clear_pending_exception(); 1081 } 1082 1083 // Install code on closure. 1084 function->ReplaceCode(*code); 1085 JSFunction::EnsureLiterals(function); 1086 1087 // Check postconditions on success. 1088 DCHECK(!isolate->has_pending_exception()); 1089 DCHECK(function->shared()->is_compiled()); 1090 DCHECK(function->is_compiled()); 1091 return true; 1092 } 1093 1094 bool Compiler::CompileOptimized(Handle<JSFunction> function, 1095 ConcurrencyMode mode) { 1096 if (function->IsOptimized()) return true; 1097 Isolate* isolate = function->GetIsolate(); 1098 DCHECK(AllowCompilation::IsAllowed(isolate)); 1099 1100 // Start a compilation. 1101 Handle<Code> code; 1102 if (!GetOptimizedCode(function, mode).ToHandle(&code)) { 1103 // Optimization failed, get unoptimized code. 1104 DCHECK(!isolate->has_pending_exception()); 1105 if (function->shared()->is_compiled()) { 1106 code = handle(function->shared()->code(), isolate); 1107 } else if (function->shared()->HasBytecodeArray()) { 1108 code = isolate->builtins()->InterpreterEntryTrampoline(); 1109 function->shared()->ReplaceCode(*code); 1110 } else { 1111 Zone zone(isolate->allocator(), ZONE_NAME); 1112 ParseInfo parse_info(&zone, handle(function->shared())); 1113 CompilationInfo info(&parse_info, function); 1114 if (!GetUnoptimizedCode(&info).ToHandle(&code)) { 1115 return false; 1116 } 1117 } 1118 } 1119 1120 // Install code on closure. 1121 function->ReplaceCode(*code); 1122 JSFunction::EnsureLiterals(function); 1123 1124 // Check postconditions on success. 1125 DCHECK(!isolate->has_pending_exception()); 1126 DCHECK(function->shared()->is_compiled()); 1127 DCHECK(function->is_compiled()); 1128 return true; 1129 } 1130 1131 bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) { 1132 Isolate* isolate = shared->GetIsolate(); 1133 DCHECK(AllowCompilation::IsAllowed(isolate)); 1134 1135 // Start a compilation. 1136 Zone zone(isolate->allocator(), ZONE_NAME); 1137 ParseInfo parse_info(&zone, shared); 1138 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); 1139 info.MarkAsDebug(); 1140 if (GetUnoptimizedCode(&info).is_null()) { 1141 isolate->clear_pending_exception(); 1142 return false; 1143 } 1144 1145 // Check postconditions on success. 1146 DCHECK(!isolate->has_pending_exception()); 1147 DCHECK(shared->is_compiled()); 1148 DCHECK(shared->HasDebugCode()); 1149 return true; 1150 } 1151 1152 MaybeHandle<JSArray> Compiler::CompileForLiveEdit(Handle<Script> script) { 1153 Isolate* isolate = script->GetIsolate(); 1154 DCHECK(AllowCompilation::IsAllowed(isolate)); 1155 1156 // In order to ensure that live edit function info collection finds the newly 1157 // generated shared function infos, clear the script's list temporarily 1158 // and restore it at the end of this method. 1159 Handle<Object> old_function_infos(script->shared_function_infos(), isolate); 1160 script->set_shared_function_infos(Smi::kZero); 1161 1162 // Start a compilation. 1163 Zone zone(isolate->allocator(), ZONE_NAME); 1164 ParseInfo parse_info(&zone, script); 1165 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); 1166 info.MarkAsDebug(); 1167 1168 // TODO(635): support extensions. 1169 const bool compilation_succeeded = !CompileToplevel(&info).is_null(); 1170 Handle<JSArray> infos; 1171 if (compilation_succeeded) { 1172 // Check postconditions on success. 1173 DCHECK(!isolate->has_pending_exception()); 1174 infos = LiveEditFunctionTracker::Collect(parse_info.literal(), script, 1175 &zone, isolate); 1176 } 1177 1178 // Restore the original function info list in order to remain side-effect 1179 // free as much as possible, since some code expects the old shared function 1180 // infos to stick around. 1181 script->set_shared_function_infos(*old_function_infos); 1182 1183 return infos; 1184 } 1185 1186 bool Compiler::EnsureBytecode(CompilationInfo* info) { 1187 if (!ShouldUseIgnition(info)) return false; 1188 if (!info->shared_info()->HasBytecodeArray()) { 1189 Handle<Code> original_code(info->shared_info()->code()); 1190 if (GetUnoptimizedCode(info).is_null()) return false; 1191 if (info->shared_info()->HasAsmWasmData()) return false; 1192 DCHECK(info->shared_info()->is_compiled()); 1193 if (original_code->kind() == Code::FUNCTION) { 1194 // Generating bytecode will install the {InterpreterEntryTrampoline} as 1195 // shared code on the function. To avoid an implicit tier down we restore 1196 // original baseline code in case it existed beforehand. 1197 info->shared_info()->ReplaceCode(*original_code); 1198 } 1199 } 1200 DCHECK(info->shared_info()->HasBytecodeArray()); 1201 return true; 1202 } 1203 1204 // TODO(turbofan): In the future, unoptimized code with deopt support could 1205 // be generated lazily once deopt is triggered. 1206 bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) { 1207 DCHECK_NOT_NULL(info->literal()); 1208 DCHECK_NOT_NULL(info->scope()); 1209 Handle<SharedFunctionInfo> shared = info->shared_info(); 1210 if (!shared->has_deoptimization_support()) { 1211 Zone zone(info->isolate()->allocator(), ZONE_NAME); 1212 CompilationInfo unoptimized(info->parse_info(), info->closure()); 1213 unoptimized.EnableDeoptimizationSupport(); 1214 1215 // TODO(4280): For now we do not switch generators or async functions to 1216 // baseline code because there might be suspended activations stored in 1217 // generator objects on the heap. We could eventually go directly to 1218 // TurboFan in this case. 1219 if (IsResumableFunction(shared->kind())) return false; 1220 1221 // When we call PrepareForSerializing below, we will change the shared 1222 // ParseInfo. Make sure to reset it. 1223 bool old_will_serialize_value = info->parse_info()->will_serialize(); 1224 1225 // If the current code has reloc info for serialization, also include 1226 // reloc info for serialization for the new code, so that deopt support 1227 // can be added without losing IC state. 1228 if (shared->code()->kind() == Code::FUNCTION && 1229 shared->code()->has_reloc_info_for_serialization()) { 1230 unoptimized.PrepareForSerializing(); 1231 } 1232 EnsureFeedbackMetadata(&unoptimized); 1233 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false; 1234 1235 info->parse_info()->set_will_serialize(old_will_serialize_value); 1236 1237 // The scope info might not have been set if a lazily compiled 1238 // function is inlined before being called for the first time. 1239 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) { 1240 InstallSharedScopeInfo(info, shared); 1241 } 1242 1243 // Install compilation result on the shared function info 1244 shared->EnableDeoptimizationSupport(*unoptimized.code()); 1245 1246 // The existing unoptimized code was replaced with the new one. 1247 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, 1248 &unoptimized); 1249 } 1250 return true; 1251 } 1252 1253 // static 1254 Compiler::CompilationTier Compiler::NextCompilationTier(JSFunction* function) { 1255 Handle<SharedFunctionInfo> shared(function->shared(), function->GetIsolate()); 1256 if (shared->IsInterpreted()) { 1257 if (UseTurboFan(shared)) { 1258 return OPTIMIZED; 1259 } else { 1260 return BASELINE; 1261 } 1262 } else { 1263 return OPTIMIZED; 1264 } 1265 } 1266 1267 MaybeHandle<JSFunction> Compiler::GetFunctionFromEval( 1268 Handle<String> source, Handle<SharedFunctionInfo> outer_info, 1269 Handle<Context> context, LanguageMode language_mode, 1270 ParseRestriction restriction, int eval_scope_position, int eval_position, 1271 int line_offset, int column_offset, Handle<Object> script_name, 1272 ScriptOriginOptions options) { 1273 Isolate* isolate = source->GetIsolate(); 1274 int source_length = source->length(); 1275 isolate->counters()->total_eval_size()->Increment(source_length); 1276 isolate->counters()->total_compile_size()->Increment(source_length); 1277 1278 CompilationCache* compilation_cache = isolate->compilation_cache(); 1279 MaybeHandle<SharedFunctionInfo> maybe_shared_info = 1280 compilation_cache->LookupEval(source, outer_info, context, language_mode, 1281 eval_scope_position); 1282 Handle<SharedFunctionInfo> shared_info; 1283 1284 Handle<Script> script; 1285 if (!maybe_shared_info.ToHandle(&shared_info)) { 1286 script = isolate->factory()->NewScript(source); 1287 if (FLAG_trace_deopt) Script::InitLineEnds(script); 1288 if (!script_name.is_null()) { 1289 script->set_name(*script_name); 1290 script->set_line_offset(line_offset); 1291 script->set_column_offset(column_offset); 1292 } 1293 script->set_origin_options(options); 1294 script->set_compilation_type(Script::COMPILATION_TYPE_EVAL); 1295 Script::SetEvalOrigin(script, outer_info, eval_position); 1296 1297 Zone zone(isolate->allocator(), ZONE_NAME); 1298 ParseInfo parse_info(&zone, script); 1299 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); 1300 parse_info.set_eval(); 1301 parse_info.set_language_mode(language_mode); 1302 parse_info.set_parse_restriction(restriction); 1303 if (!context->IsNativeContext()) { 1304 parse_info.set_outer_scope_info(handle(context->scope_info())); 1305 } 1306 1307 shared_info = CompileToplevel(&info); 1308 1309 if (shared_info.is_null()) { 1310 return MaybeHandle<JSFunction>(); 1311 } else { 1312 // If caller is strict mode, the result must be in strict mode as well. 1313 DCHECK(is_sloppy(language_mode) || 1314 is_strict(shared_info->language_mode())); 1315 compilation_cache->PutEval(source, outer_info, context, shared_info, 1316 eval_scope_position); 1317 } 1318 } 1319 1320 Handle<JSFunction> result = 1321 isolate->factory()->NewFunctionFromSharedFunctionInfo( 1322 shared_info, context, NOT_TENURED); 1323 1324 // OnAfterCompile has to be called after we create the JSFunction, which we 1325 // may require to recompile the eval for debugging, if we find a function 1326 // that contains break points in the eval script. 1327 isolate->debug()->OnAfterCompile(script); 1328 1329 return result; 1330 } 1331 1332 namespace { 1333 1334 bool CodeGenerationFromStringsAllowed(Isolate* isolate, 1335 Handle<Context> context) { 1336 DCHECK(context->allow_code_gen_from_strings()->IsFalse(isolate)); 1337 // Check with callback if set. 1338 AllowCodeGenerationFromStringsCallback callback = 1339 isolate->allow_code_gen_callback(); 1340 if (callback == NULL) { 1341 // No callback set and code generation disallowed. 1342 return false; 1343 } else { 1344 // Callback set. Let it decide if code generation is allowed. 1345 VMState<EXTERNAL> state(isolate); 1346 return callback(v8::Utils::ToLocal(context)); 1347 } 1348 } 1349 1350 } // namespace 1351 1352 MaybeHandle<JSFunction> Compiler::GetFunctionFromString( 1353 Handle<Context> context, Handle<String> source, 1354 ParseRestriction restriction) { 1355 Isolate* const isolate = context->GetIsolate(); 1356 Handle<Context> native_context(context->native_context(), isolate); 1357 1358 // Check if native context allows code generation from 1359 // strings. Throw an exception if it doesn't. 1360 if (native_context->allow_code_gen_from_strings()->IsFalse(isolate) && 1361 !CodeGenerationFromStringsAllowed(isolate, native_context)) { 1362 Handle<Object> error_message = 1363 native_context->ErrorMessageForCodeGenerationFromStrings(); 1364 THROW_NEW_ERROR(isolate, NewEvalError(MessageTemplate::kCodeGenFromStrings, 1365 error_message), 1366 JSFunction); 1367 } 1368 1369 // Compile source string in the native context. 1370 int eval_scope_position = 0; 1371 int eval_position = kNoSourcePosition; 1372 Handle<SharedFunctionInfo> outer_info(native_context->closure()->shared()); 1373 return Compiler::GetFunctionFromEval(source, outer_info, native_context, 1374 SLOPPY, restriction, eval_scope_position, 1375 eval_position); 1376 } 1377 1378 Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript( 1379 Handle<String> source, Handle<Object> script_name, int line_offset, 1380 int column_offset, ScriptOriginOptions resource_options, 1381 Handle<Object> source_map_url, Handle<Context> context, 1382 v8::Extension* extension, ScriptData** cached_data, 1383 ScriptCompiler::CompileOptions compile_options, NativesFlag natives, 1384 bool is_module) { 1385 Isolate* isolate = source->GetIsolate(); 1386 if (compile_options == ScriptCompiler::kNoCompileOptions) { 1387 cached_data = NULL; 1388 } else if (compile_options == ScriptCompiler::kProduceParserCache || 1389 compile_options == ScriptCompiler::kProduceCodeCache) { 1390 DCHECK(cached_data && !*cached_data); 1391 DCHECK(extension == NULL); 1392 DCHECK(!isolate->debug()->is_loaded()); 1393 } else { 1394 DCHECK(compile_options == ScriptCompiler::kConsumeParserCache || 1395 compile_options == ScriptCompiler::kConsumeCodeCache); 1396 DCHECK(cached_data && *cached_data); 1397 DCHECK(extension == NULL); 1398 } 1399 int source_length = source->length(); 1400 isolate->counters()->total_load_size()->Increment(source_length); 1401 isolate->counters()->total_compile_size()->Increment(source_length); 1402 1403 LanguageMode language_mode = construct_language_mode(FLAG_use_strict); 1404 CompilationCache* compilation_cache = isolate->compilation_cache(); 1405 1406 // Do a lookup in the compilation cache but not for extensions. 1407 MaybeHandle<SharedFunctionInfo> maybe_result; 1408 Handle<SharedFunctionInfo> result; 1409 if (extension == NULL) { 1410 // First check per-isolate compilation cache. 1411 maybe_result = compilation_cache->LookupScript( 1412 source, script_name, line_offset, column_offset, resource_options, 1413 context, language_mode); 1414 if (maybe_result.is_null() && FLAG_serialize_toplevel && 1415 compile_options == ScriptCompiler::kConsumeCodeCache && 1416 !isolate->debug()->is_loaded()) { 1417 // Then check cached code provided by embedder. 1418 HistogramTimerScope timer(isolate->counters()->compile_deserialize()); 1419 RuntimeCallTimerScope runtimeTimer(isolate, 1420 &RuntimeCallStats::CompileDeserialize); 1421 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), 1422 "V8.CompileDeserialize"); 1423 Handle<SharedFunctionInfo> result; 1424 if (CodeSerializer::Deserialize(isolate, *cached_data, source) 1425 .ToHandle(&result)) { 1426 // Promote to per-isolate compilation cache. 1427 compilation_cache->PutScript(source, context, language_mode, result); 1428 return result; 1429 } 1430 // Deserializer failed. Fall through to compile. 1431 } 1432 } 1433 1434 base::ElapsedTimer timer; 1435 if (FLAG_profile_deserialization && FLAG_serialize_toplevel && 1436 compile_options == ScriptCompiler::kProduceCodeCache) { 1437 timer.Start(); 1438 } 1439 1440 if (!maybe_result.ToHandle(&result) || 1441 (FLAG_serialize_toplevel && 1442 compile_options == ScriptCompiler::kProduceCodeCache)) { 1443 // No cache entry found, or embedder wants a code cache. Compile the script. 1444 1445 // Create a script object describing the script to be compiled. 1446 Handle<Script> script = isolate->factory()->NewScript(source); 1447 if (FLAG_trace_deopt) Script::InitLineEnds(script); 1448 if (natives == NATIVES_CODE) { 1449 script->set_type(Script::TYPE_NATIVE); 1450 script->set_hide_source(true); 1451 } else if (natives == EXTENSION_CODE) { 1452 script->set_type(Script::TYPE_EXTENSION); 1453 script->set_hide_source(true); 1454 } 1455 if (!script_name.is_null()) { 1456 script->set_name(*script_name); 1457 script->set_line_offset(line_offset); 1458 script->set_column_offset(column_offset); 1459 } 1460 script->set_origin_options(resource_options); 1461 if (!source_map_url.is_null()) { 1462 script->set_source_mapping_url(*source_map_url); 1463 } 1464 1465 // Compile the function and add it to the cache. 1466 Zone zone(isolate->allocator(), ZONE_NAME); 1467 ParseInfo parse_info(&zone, script); 1468 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); 1469 if (is_module) parse_info.set_module(); 1470 if (compile_options != ScriptCompiler::kNoCompileOptions) { 1471 parse_info.set_cached_data(cached_data); 1472 } 1473 parse_info.set_compile_options(compile_options); 1474 parse_info.set_extension(extension); 1475 if (!context->IsNativeContext()) { 1476 parse_info.set_outer_scope_info(handle(context->scope_info())); 1477 } 1478 if (FLAG_serialize_toplevel && 1479 compile_options == ScriptCompiler::kProduceCodeCache) { 1480 info.PrepareForSerializing(); 1481 } 1482 1483 parse_info.set_language_mode( 1484 static_cast<LanguageMode>(parse_info.language_mode() | language_mode)); 1485 result = CompileToplevel(&info); 1486 if (extension == NULL && !result.is_null()) { 1487 compilation_cache->PutScript(source, context, language_mode, result); 1488 if (FLAG_serialize_toplevel && 1489 compile_options == ScriptCompiler::kProduceCodeCache) { 1490 HistogramTimerScope histogram_timer( 1491 isolate->counters()->compile_serialize()); 1492 RuntimeCallTimerScope runtimeTimer(isolate, 1493 &RuntimeCallStats::CompileSerialize); 1494 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), 1495 "V8.CompileSerialize"); 1496 *cached_data = CodeSerializer::Serialize(isolate, result, source); 1497 if (FLAG_profile_deserialization) { 1498 PrintF("[Compiling and serializing took %0.3f ms]\n", 1499 timer.Elapsed().InMillisecondsF()); 1500 } 1501 } 1502 } 1503 1504 if (result.is_null()) { 1505 isolate->ReportPendingMessages(); 1506 } else { 1507 isolate->debug()->OnAfterCompile(script); 1508 } 1509 } else if (result->ic_age() != isolate->heap()->global_ic_age()) { 1510 result->ResetForNewContext(isolate->heap()->global_ic_age()); 1511 } 1512 return result; 1513 } 1514 1515 Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForStreamedScript( 1516 Handle<Script> script, ParseInfo* parse_info, int source_length) { 1517 Isolate* isolate = script->GetIsolate(); 1518 // TODO(titzer): increment the counters in caller. 1519 isolate->counters()->total_load_size()->Increment(source_length); 1520 isolate->counters()->total_compile_size()->Increment(source_length); 1521 1522 LanguageMode language_mode = construct_language_mode(FLAG_use_strict); 1523 parse_info->set_language_mode( 1524 static_cast<LanguageMode>(parse_info->language_mode() | language_mode)); 1525 1526 CompilationInfo compile_info(parse_info, Handle<JSFunction>::null()); 1527 1528 // The source was parsed lazily, so compiling for debugging is not possible. 1529 DCHECK(!compile_info.is_debug()); 1530 1531 Handle<SharedFunctionInfo> result = CompileToplevel(&compile_info); 1532 if (!result.is_null()) isolate->debug()->OnAfterCompile(script); 1533 return result; 1534 } 1535 1536 1537 Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo( 1538 FunctionLiteral* literal, Handle<Script> script, 1539 CompilationInfo* outer_info) { 1540 // Precondition: code has been parsed and scopes have been analyzed. 1541 Isolate* isolate = outer_info->isolate(); 1542 MaybeHandle<SharedFunctionInfo> maybe_existing; 1543 1544 // Find any previously allocated shared function info for the given literal. 1545 if (outer_info->shared_info()->never_compiled()) { 1546 // On the first compile, there are no existing shared function info for 1547 // inner functions yet, so do not try to find them. All bets are off for 1548 // live edit though. 1549 SLOW_DCHECK(script->FindSharedFunctionInfo(literal).is_null() || 1550 isolate->debug()->live_edit_enabled()); 1551 } else { 1552 maybe_existing = script->FindSharedFunctionInfo(literal); 1553 } 1554 1555 // We found an existing shared function info. If it has any sort of code 1556 // attached, don't worry about compiling and simply return it. Otherwise, 1557 // continue to decide whether to eagerly compile. 1558 // Note that we also carry on if we are compiling eager to obtain code for 1559 // debugging, unless we already have code with debug break slots. 1560 Handle<SharedFunctionInfo> existing; 1561 if (maybe_existing.ToHandle(&existing)) { 1562 DCHECK(!existing->is_toplevel()); 1563 if (existing->HasBaselineCode() || existing->HasBytecodeArray()) { 1564 if (!outer_info->is_debug() || existing->HasDebugCode()) { 1565 return existing; 1566 } 1567 } 1568 } 1569 1570 // Allocate a shared function info object. 1571 Handle<SharedFunctionInfo> result; 1572 if (!maybe_existing.ToHandle(&result)) { 1573 result = NewSharedFunctionInfoForLiteral(isolate, literal, script); 1574 result->set_is_toplevel(false); 1575 1576 // If the outer function has been compiled before, we cannot be sure that 1577 // shared function info for this function literal has been created for the 1578 // first time. It may have already been compiled previously. 1579 result->set_never_compiled(outer_info->shared_info()->never_compiled()); 1580 } 1581 1582 Zone zone(isolate->allocator(), ZONE_NAME); 1583 ParseInfo parse_info(&zone, script); 1584 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); 1585 parse_info.set_literal(literal); 1586 parse_info.set_shared_info(result); 1587 parse_info.set_language_mode(literal->scope()->language_mode()); 1588 parse_info.set_ast_value_factory( 1589 outer_info->parse_info()->ast_value_factory()); 1590 parse_info.set_ast_value_factory_owned(false); 1591 1592 if (outer_info->will_serialize()) info.PrepareForSerializing(); 1593 if (outer_info->is_debug()) info.MarkAsDebug(); 1594 1595 // If this inner function is already compiled, we don't need to compile 1596 // again. When compiling for debug, we are not interested in having debug 1597 // break slots in inner functions, neither for setting break points nor 1598 // for revealing inner functions. 1599 // This is especially important for generators. We must not replace the 1600 // code for generators, as there may be suspended generator objects. 1601 if (!result->is_compiled()) { 1602 if (!literal->ShouldEagerCompile()) { 1603 info.SetCode(isolate->builtins()->CompileLazy()); 1604 Scope* outer_scope = literal->scope()->GetOuterScopeWithContext(); 1605 if (outer_scope) { 1606 result->set_outer_scope_info(*outer_scope->scope_info()); 1607 } 1608 } else { 1609 // Generate code 1610 TimerEventScope<TimerEventCompileCode> timer(isolate); 1611 RuntimeCallTimerScope runtimeTimer(isolate, 1612 &RuntimeCallStats::CompileCode); 1613 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode"); 1614 if (Renumber(info.parse_info()) && GenerateUnoptimizedCode(&info)) { 1615 // Code generation will ensure that the feedback vector is present and 1616 // appropriately sized. 1617 DCHECK(!info.code().is_null()); 1618 if (literal->should_be_used_once_hint()) { 1619 info.code()->MarkToBeExecutedOnce(isolate); 1620 } 1621 } else { 1622 return Handle<SharedFunctionInfo>::null(); 1623 } 1624 } 1625 } 1626 1627 if (maybe_existing.is_null()) { 1628 RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, &info); 1629 } 1630 1631 return result; 1632 } 1633 1634 Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForNative( 1635 v8::Extension* extension, Handle<String> name) { 1636 Isolate* isolate = name->GetIsolate(); 1637 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate); 1638 1639 // Compute the function template for the native function. 1640 v8::Local<v8::FunctionTemplate> fun_template = 1641 extension->GetNativeFunctionTemplate(v8_isolate, 1642 v8::Utils::ToLocal(name)); 1643 DCHECK(!fun_template.IsEmpty()); 1644 1645 // Instantiate the function and create a shared function info from it. 1646 Handle<JSFunction> fun = Handle<JSFunction>::cast(Utils::OpenHandle( 1647 *fun_template->GetFunction(v8_isolate->GetCurrentContext()) 1648 .ToLocalChecked())); 1649 Handle<Code> code = Handle<Code>(fun->shared()->code()); 1650 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub()); 1651 Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo( 1652 name, fun->shared()->num_literals(), FunctionKind::kNormalFunction, code, 1653 Handle<ScopeInfo>(fun->shared()->scope_info())); 1654 shared->set_outer_scope_info(fun->shared()->outer_scope_info()); 1655 shared->SetConstructStub(*construct_stub); 1656 shared->set_feedback_metadata(fun->shared()->feedback_metadata()); 1657 1658 // Copy the function data to the shared function info. 1659 shared->set_function_data(fun->shared()->function_data()); 1660 int parameters = fun->shared()->internal_formal_parameter_count(); 1661 shared->set_internal_formal_parameter_count(parameters); 1662 1663 return shared; 1664 } 1665 1666 MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function, 1667 BailoutId osr_ast_id, 1668 JavaScriptFrame* osr_frame) { 1669 DCHECK(!osr_ast_id.IsNone()); 1670 DCHECK_NOT_NULL(osr_frame); 1671 return GetOptimizedCode(function, NOT_CONCURRENT, osr_ast_id, osr_frame); 1672 } 1673 1674 CompilationJob* Compiler::PrepareUnoptimizedCompilationJob( 1675 CompilationInfo* info) { 1676 VMState<COMPILER> state(info->isolate()); 1677 std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info)); 1678 if (job->PrepareJob() != CompilationJob::SUCCEEDED) { 1679 return nullptr; 1680 } 1681 return job.release(); 1682 } 1683 1684 bool Compiler::FinalizeCompilationJob(CompilationJob* raw_job) { 1685 // Take ownership of compilation job. Deleting job also tears down the zone. 1686 std::unique_ptr<CompilationJob> job(raw_job); 1687 1688 VMState<COMPILER> state(job->info()->isolate()); 1689 if (job->info()->IsOptimizing()) { 1690 return FinalizeOptimizedCompilationJob(job.get()) == 1691 CompilationJob::SUCCEEDED; 1692 } else { 1693 if (FinalizeUnoptimizedCompilationJob(job.get()) == 1694 CompilationJob::SUCCEEDED) { 1695 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, 1696 job->info()); 1697 return true; 1698 } 1699 return false; 1700 } 1701 } 1702 1703 void Compiler::PostInstantiation(Handle<JSFunction> function, 1704 PretenureFlag pretenure) { 1705 Handle<SharedFunctionInfo> shared(function->shared()); 1706 1707 if (FLAG_always_opt && shared->allows_lazy_compilation()) { 1708 function->MarkForOptimization(); 1709 } 1710 1711 CodeAndLiterals cached = shared->SearchOptimizedCodeMap( 1712 function->context()->native_context(), BailoutId::None()); 1713 if (cached.code != nullptr) { 1714 // Caching of optimized code enabled and optimized code found. 1715 DCHECK(!cached.code->marked_for_deoptimization()); 1716 DCHECK(function->shared()->is_compiled()); 1717 function->ReplaceCode(cached.code); 1718 } 1719 1720 if (cached.literals != nullptr) { 1721 DCHECK(shared->is_compiled()); 1722 function->set_literals(cached.literals); 1723 } else if (shared->is_compiled()) { 1724 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. 1725 JSFunction::EnsureLiterals(function); 1726 } 1727 } 1728 1729 } // namespace internal 1730 } // namespace v8 1731