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/api-inl.h"
11#include "src/asmjs/asm-js.h"
12#include "src/assembler-inl.h"
13#include "src/ast/prettyprinter.h"
14#include "src/ast/scopes.h"
15#include "src/base/optional.h"
16#include "src/bootstrapper.h"
17#include "src/compilation-cache.h"
18#include "src/compiler-dispatcher/compiler-dispatcher.h"
19#include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
20#include "src/compiler/pipeline.h"
21#include "src/debug/debug.h"
22#include "src/debug/liveedit.h"
23#include "src/frames-inl.h"
24#include "src/globals.h"
25#include "src/heap/heap-inl.h"
26#include "src/interpreter/interpreter.h"
27#include "src/isolate-inl.h"
28#include "src/log-inl.h"
29#include "src/message-template.h"
30#include "src/objects/feedback-cell-inl.h"
31#include "src/objects/map.h"
32#include "src/optimized-compilation-info.h"
33#include "src/ostreams.h"
34#include "src/parsing/parse-info.h"
35#include "src/parsing/parser.h"
36#include "src/parsing/parsing.h"
37#include "src/parsing/rewriter.h"
38#include "src/parsing/scanner-character-streams.h"
39#include "src/runtime-profiler.h"
40#include "src/snapshot/code-serializer.h"
41#include "src/unoptimized-compilation-info.h"
42#include "src/vm-state-inl.h"
43#include "src/zone/zone-list-inl.h" // crbug.com/v8/8816
44
45namespace v8 {
46namespace internal {
47
48// A wrapper around a OptimizedCompilationInfo that detaches the Handles from
49// the underlying DeferredHandleScope and stores them in info_ on
50// destruction.
51class CompilationHandleScope final {
52 public:
53 explicit CompilationHandleScope(Isolate* isolate,
54 OptimizedCompilationInfo* info)
55 : deferred_(isolate), info_(info) {}
56 ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); }
57
58 private:
59 DeferredHandleScope deferred_;
60 OptimizedCompilationInfo* info_;
61};
62
63// Helper that times a scoped region and records the elapsed time.
64struct ScopedTimer {
65 explicit ScopedTimer(base::TimeDelta* location) : location_(location) {
66 DCHECK_NOT_NULL(location_);
67 timer_.Start();
68 }
69
70 ~ScopedTimer() { *location_ += timer_.Elapsed(); }
71
72 base::ElapsedTimer timer_;
73 base::TimeDelta* location_;
74};
75
76namespace {
77
78void LogFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
79 Handle<SharedFunctionInfo> shared,
80 Handle<Script> script,
81 Handle<AbstractCode> abstract_code, bool optimizing,
82 double time_taken_ms, Isolate* isolate) {
83 DCHECK(!abstract_code.is_null());
84 DCHECK(!abstract_code.is_identical_to(BUILTIN_CODE(isolate, CompileLazy)));
85
86 // Log the code generation. If source information is available include
87 // script name and line number. Check explicitly whether logging is
88 // enabled as finding the line number is not free.
89 if (!isolate->logger()->is_listening_to_code_events() &&
90 !isolate->is_profiling() && !FLAG_log_function_events &&
91 !isolate->code_event_dispatcher()->IsListeningToCodeEvents()) {
92 return;
93 }
94
95 int line_num = Script::GetLineNumber(script, shared->StartPosition()) + 1;
96 int column_num = Script::GetColumnNumber(script, shared->StartPosition()) + 1;
97 String script_name = script->name()->IsString()
98 ? String::cast(script->name())
99 : ReadOnlyRoots(isolate).empty_string();
100 CodeEventListener::LogEventsAndTags log_tag =
101 Logger::ToNativeByScript(tag, *script);
102 PROFILE(isolate, CodeCreateEvent(log_tag, *abstract_code, *shared,
103 script_name, line_num, column_num));
104 if (!FLAG_log_function_events) return;
105
106 DisallowHeapAllocation no_gc;
107
108 std::string name = optimizing ? "optimize" : "compile";
109 switch (tag) {
110 case CodeEventListener::EVAL_TAG:
111 name += "-eval";
112 break;
113 case CodeEventListener::SCRIPT_TAG:
114 break;
115 case CodeEventListener::LAZY_COMPILE_TAG:
116 name += "-lazy";
117 break;
118 case CodeEventListener::FUNCTION_TAG:
119 break;
120 default:
121 UNREACHABLE();
122 }
123
124 LOG(isolate, FunctionEvent(name.c_str(), script->id(), time_taken_ms,
125 shared->StartPosition(), shared->EndPosition(),
126 shared->DebugName()));
127}
128
129ScriptOriginOptions OriginOptionsForEval(Object script) {
130 if (!script->IsScript()) return ScriptOriginOptions();
131
132 const auto outer_origin_options = Script::cast(script)->origin_options();
133 return ScriptOriginOptions(outer_origin_options.IsSharedCrossOrigin(),
134 outer_origin_options.IsOpaque());
135}
136
137} // namespace
138
139// ----------------------------------------------------------------------------
140// Implementation of UnoptimizedCompilationJob
141
142CompilationJob::Status UnoptimizedCompilationJob::ExecuteJob() {
143 DisallowHeapAccess no_heap_access;
144 // Delegate to the underlying implementation.
145 DCHECK_EQ(state(), State::kReadyToExecute);
146 ScopedTimer t(&time_taken_to_execute_);
147 return UpdateState(ExecuteJobImpl(), State::kReadyToFinalize);
148}
149
150CompilationJob::Status UnoptimizedCompilationJob::FinalizeJob(
151 Handle<SharedFunctionInfo> shared_info, Isolate* isolate) {
152 DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
153 DisallowCodeDependencyChange no_dependency_change;
154 DisallowJavascriptExecution no_js(isolate);
155
156 // Delegate to the underlying implementation.
157 DCHECK_EQ(state(), State::kReadyToFinalize);
158 ScopedTimer t(&time_taken_to_finalize_);
159 return UpdateState(FinalizeJobImpl(shared_info, isolate), State::kSucceeded);
160}
161
162void UnoptimizedCompilationJob::RecordCompilationStats(Isolate* isolate) const {
163 int code_size;
164 if (compilation_info()->has_bytecode_array()) {
165 code_size = compilation_info()->bytecode_array()->SizeIncludingMetadata();
166 } else {
167 DCHECK(compilation_info()->has_asm_wasm_data());
168 code_size = compilation_info()->asm_wasm_data()->Size();
169 }
170
171 Counters* counters = isolate->counters();
172 // TODO(4280): Rename counters from "baseline" to "unoptimized" eventually.
173 counters->total_baseline_code_size()->Increment(code_size);
174 counters->total_baseline_compile_count()->Increment(1);
175
176 // TODO(5203): Add timers for each phase of compilation.
177 // Also add total time (there's now already timer_ on the base class).
178}
179
180void UnoptimizedCompilationJob::RecordFunctionCompilation(
181 CodeEventListener::LogEventsAndTags tag, Handle<SharedFunctionInfo> shared,
182 Isolate* isolate) const {
183 Handle<AbstractCode> abstract_code;
184 if (compilation_info()->has_bytecode_array()) {
185 abstract_code =
186 Handle<AbstractCode>::cast(compilation_info()->bytecode_array());
187 } else {
188 DCHECK(compilation_info()->has_asm_wasm_data());
189 abstract_code =
190 Handle<AbstractCode>::cast(BUILTIN_CODE(isolate, InstantiateAsmJs));
191 }
192
193 double time_taken_ms = time_taken_to_execute_.InMillisecondsF() +
194 time_taken_to_finalize_.InMillisecondsF();
195
196 LogFunctionCompilation(tag, shared, parse_info()->script(), abstract_code,
197 false, time_taken_ms, isolate);
198}
199
200// ----------------------------------------------------------------------------
201// Implementation of OptimizedCompilationJob
202
203CompilationJob::Status OptimizedCompilationJob::PrepareJob(Isolate* isolate) {
204 DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
205 DisallowJavascriptExecution no_js(isolate);
206
207 if (FLAG_trace_opt && compilation_info()->IsOptimizing()) {
208 StdoutStream os;
209 os << "[compiling method " << Brief(*compilation_info()->closure())
210 << " using " << compiler_name_;
211 if (compilation_info()->is_osr()) os << " OSR";
212 os << "]" << std::endl;
213 }
214
215 // Delegate to the underlying implementation.
216 DCHECK_EQ(state(), State::kReadyToPrepare);
217 ScopedTimer t(&time_taken_to_prepare_);
218 return UpdateState(PrepareJobImpl(isolate), State::kReadyToExecute);
219}
220
221CompilationJob::Status OptimizedCompilationJob::ExecuteJob() {
222 DisallowHeapAccess no_heap_access;
223 // Delegate to the underlying implementation.
224 DCHECK_EQ(state(), State::kReadyToExecute);
225 ScopedTimer t(&time_taken_to_execute_);
226 return UpdateState(ExecuteJobImpl(), State::kReadyToFinalize);
227}
228
229CompilationJob::Status OptimizedCompilationJob::FinalizeJob(Isolate* isolate) {
230 DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
231 DisallowJavascriptExecution no_js(isolate);
232
233 // Delegate to the underlying implementation.
234 DCHECK_EQ(state(), State::kReadyToFinalize);
235 ScopedTimer t(&time_taken_to_finalize_);
236 return UpdateState(FinalizeJobImpl(isolate), State::kSucceeded);
237}
238
239CompilationJob::Status OptimizedCompilationJob::RetryOptimization(
240 BailoutReason reason) {
241 DCHECK(compilation_info_->IsOptimizing());
242 compilation_info_->RetryOptimization(reason);
243 return UpdateState(FAILED, State::kFailed);
244}
245
246CompilationJob::Status OptimizedCompilationJob::AbortOptimization(
247 BailoutReason reason) {
248 DCHECK(compilation_info_->IsOptimizing());
249 compilation_info_->AbortOptimization(reason);
250 return UpdateState(FAILED, State::kFailed);
251}
252
253void OptimizedCompilationJob::RecordCompilationStats(CompilationMode mode,
254 Isolate* isolate) const {
255 DCHECK(compilation_info()->IsOptimizing());
256 Handle<JSFunction> function = compilation_info()->closure();
257 double ms_creategraph = time_taken_to_prepare_.InMillisecondsF();
258 double ms_optimize = time_taken_to_execute_.InMillisecondsF();
259 double ms_codegen = time_taken_to_finalize_.InMillisecondsF();
260 if (FLAG_trace_opt) {
261 PrintF("[optimizing ");
262 function->ShortPrint();
263 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize,
264 ms_codegen);
265 }
266 if (FLAG_trace_opt_stats) {
267 static double compilation_time = 0.0;
268 static int compiled_functions = 0;
269 static int code_size = 0;
270
271 compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
272 compiled_functions++;
273 code_size += function->shared()->SourceSize();
274 PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
275 compiled_functions, code_size, compilation_time);
276 }
277 // Don't record samples from machines without high-resolution timers,
278 // as that can cause serious reporting issues. See the thread at
279 // http://g/chrome-metrics-team/NwwJEyL8odU/discussion for more details.
280 if (base::TimeTicks::IsHighResolution()) {
281 Counters* const counters = isolate->counters();
282 if (compilation_info()->is_osr()) {
283 counters->turbofan_osr_prepare()->AddSample(
284 static_cast<int>(time_taken_to_prepare_.InMicroseconds()));
285 counters->turbofan_osr_execute()->AddSample(
286 static_cast<int>(time_taken_to_execute_.InMicroseconds()));
287 counters->turbofan_osr_finalize()->AddSample(
288 static_cast<int>(time_taken_to_finalize_.InMicroseconds()));
289 counters->turbofan_osr_total_time()->AddSample(
290 static_cast<int>(ElapsedTime().InMicroseconds()));
291 } else {
292 counters->turbofan_optimize_prepare()->AddSample(
293 static_cast<int>(time_taken_to_prepare_.InMicroseconds()));
294 counters->turbofan_optimize_execute()->AddSample(
295 static_cast<int>(time_taken_to_execute_.InMicroseconds()));
296 counters->turbofan_optimize_finalize()->AddSample(
297 static_cast<int>(time_taken_to_finalize_.InMicroseconds()));
298 counters->turbofan_optimize_total_time()->AddSample(
299 static_cast<int>(ElapsedTime().InMicroseconds()));
300
301 // Compute foreground / background time.
302 base::TimeDelta time_background;
303 base::TimeDelta time_foreground =
304 time_taken_to_prepare_ + time_taken_to_finalize_;
305 switch (mode) {
306 case OptimizedCompilationJob::kConcurrent:
307 time_background += time_taken_to_execute_;
308 break;
309 case OptimizedCompilationJob::kSynchronous:
310 time_foreground += time_taken_to_execute_;
311 break;
312 }
313 counters->turbofan_optimize_total_background()->AddSample(
314 static_cast<int>(time_background.InMicroseconds()));
315 counters->turbofan_optimize_total_foreground()->AddSample(
316 static_cast<int>(time_foreground.InMicroseconds()));
317 }
318 }
319}
320
321void OptimizedCompilationJob::RecordFunctionCompilation(
322 CodeEventListener::LogEventsAndTags tag, Isolate* isolate) const {
323 Handle<AbstractCode> abstract_code =
324 Handle<AbstractCode>::cast(compilation_info()->code());
325
326 double time_taken_ms = time_taken_to_prepare_.InMillisecondsF() +
327 time_taken_to_execute_.InMillisecondsF() +
328 time_taken_to_finalize_.InMillisecondsF();
329
330 Handle<Script> script(
331 Script::cast(compilation_info()->shared_info()->script()), isolate);
332 LogFunctionCompilation(tag, compilation_info()->shared_info(), script,
333 abstract_code, true, time_taken_ms, isolate);
334}
335
336// ----------------------------------------------------------------------------
337// Local helper methods that make up the compilation pipeline.
338
339namespace {
340
341bool UseAsmWasm(FunctionLiteral* literal, bool asm_wasm_broken) {
342 // Check whether asm.js validation is enabled.
343 if (!FLAG_validate_asm) return false;
344
345 // Modules that have validated successfully, but were subsequently broken by
346 // invalid module instantiation attempts are off limit forever.
347 if (asm_wasm_broken) return false;
348
349 // In stress mode we want to run the validator on everything.
350 if (FLAG_stress_validate_asm) return true;
351
352 // In general, we respect the "use asm" directive.
353 return literal->scope()->IsAsmModule();
354}
355
356void InstallBytecodeArray(Handle<BytecodeArray> bytecode_array,
357 Handle<SharedFunctionInfo> shared_info,
358 ParseInfo* parse_info, Isolate* isolate) {
359 if (!FLAG_interpreted_frames_native_stack) {
360 shared_info->set_bytecode_array(*bytecode_array);
361 return;
362 }
363
364 Handle<Code> code = isolate->factory()->CopyCode(Handle<Code>::cast(
365 isolate->factory()->interpreter_entry_trampoline_for_profiling()));
366
367 Handle<InterpreterData> interpreter_data =
368 Handle<InterpreterData>::cast(isolate->factory()->NewStruct(
369 INTERPRETER_DATA_TYPE, AllocationType::kOld));
370
371 interpreter_data->set_bytecode_array(*bytecode_array);
372 interpreter_data->set_interpreter_trampoline(*code);
373
374 shared_info->set_interpreter_data(*interpreter_data);
375
376 Handle<Script> script = parse_info->script();
377 Handle<AbstractCode> abstract_code = Handle<AbstractCode>::cast(code);
378 int line_num =
379 Script::GetLineNumber(script, shared_info->StartPosition()) + 1;
380 int column_num =
381 Script::GetColumnNumber(script, shared_info->StartPosition()) + 1;
382 String script_name = script->name()->IsString()
383 ? String::cast(script->name())
384 : ReadOnlyRoots(isolate).empty_string();
385 CodeEventListener::LogEventsAndTags log_tag = Logger::ToNativeByScript(
386 CodeEventListener::INTERPRETED_FUNCTION_TAG, *script);
387 PROFILE(isolate, CodeCreateEvent(log_tag, *abstract_code, *shared_info,
388 script_name, line_num, column_num));
389}
390
391void InstallUnoptimizedCode(UnoptimizedCompilationInfo* compilation_info,
392 Handle<SharedFunctionInfo> shared_info,
393 ParseInfo* parse_info, Isolate* isolate) {
394 DCHECK_EQ(shared_info->language_mode(),
395 compilation_info->literal()->language_mode());
396
397 // Update the shared function info with the scope info.
398 Handle<ScopeInfo> scope_info = compilation_info->scope()->scope_info();
399 shared_info->set_scope_info(*scope_info);
400
401 if (compilation_info->has_bytecode_array()) {
402 DCHECK(!shared_info->HasBytecodeArray()); // Only compiled once.
403 DCHECK(!compilation_info->has_asm_wasm_data());
404 DCHECK(!shared_info->HasFeedbackMetadata());
405
406 InstallBytecodeArray(compilation_info->bytecode_array(), shared_info,
407 parse_info, isolate);
408
409 Handle<FeedbackMetadata> feedback_metadata = FeedbackMetadata::New(
410 isolate, compilation_info->feedback_vector_spec());
411 shared_info->set_feedback_metadata(*feedback_metadata);
412 } else {
413 DCHECK(compilation_info->has_asm_wasm_data());
414 shared_info->set_asm_wasm_data(*compilation_info->asm_wasm_data());
415 shared_info->set_feedback_metadata(
416 ReadOnlyRoots(isolate).empty_feedback_metadata());
417 }
418
419 // Install coverage info on the shared function info.
420 if (compilation_info->has_coverage_info() &&
421 !shared_info->HasCoverageInfo()) {
422 DCHECK(isolate->is_block_code_coverage());
423 isolate->debug()->InstallCoverageInfo(shared_info,
424 compilation_info->coverage_info());
425 }
426}
427
428void EnsureSharedFunctionInfosArrayOnScript(ParseInfo* parse_info,
429 Isolate* isolate) {
430 DCHECK(parse_info->is_toplevel());
431 DCHECK(!parse_info->script().is_null());
432 if (parse_info->script()->shared_function_infos()->length() > 0) {
433 DCHECK_EQ(parse_info->script()->shared_function_infos()->length(),
434 parse_info->max_function_literal_id() + 1);
435 return;
436 }
437 Handle<WeakFixedArray> infos(isolate->factory()->NewWeakFixedArray(
438 parse_info->max_function_literal_id() + 1));
439 parse_info->script()->set_shared_function_infos(*infos);
440}
441
442void SetSharedFunctionFlagsFromLiteral(FunctionLiteral* literal,
443 Handle<SharedFunctionInfo> shared_info) {
444 shared_info->set_has_duplicate_parameters(
445 literal->has_duplicate_parameters());
446 shared_info->set_is_oneshot_iife(literal->is_oneshot_iife());
447 shared_info->SetExpectedNofPropertiesFromEstimate(literal);
448 if (literal->dont_optimize_reason() != BailoutReason::kNoReason) {
449 shared_info->DisableOptimization(literal->dont_optimize_reason());
450 }
451 shared_info->set_is_safe_to_skip_arguments_adaptor(
452 literal->SafeToSkipArgumentsAdaptor());
453}
454
455CompilationJob::Status FinalizeUnoptimizedCompilationJob(
456 UnoptimizedCompilationJob* job, Handle<SharedFunctionInfo> shared_info,
457 Isolate* isolate) {
458 UnoptimizedCompilationInfo* compilation_info = job->compilation_info();
459 ParseInfo* parse_info = job->parse_info();
460
461 SetSharedFunctionFlagsFromLiteral(compilation_info->literal(), shared_info);
462
463 CompilationJob::Status status = job->FinalizeJob(shared_info, isolate);
464 if (status == CompilationJob::SUCCEEDED) {
465 InstallUnoptimizedCode(compilation_info, shared_info, parse_info, isolate);
466 CodeEventListener::LogEventsAndTags log_tag;
467 if (parse_info->is_toplevel()) {
468 log_tag = compilation_info->is_eval() ? CodeEventListener::EVAL_TAG
469 : CodeEventListener::SCRIPT_TAG;
470 } else {
471 log_tag = parse_info->lazy_compile() ? CodeEventListener::LAZY_COMPILE_TAG
472 : CodeEventListener::FUNCTION_TAG;
473 }
474 job->RecordFunctionCompilation(log_tag, shared_info, isolate);
475 job->RecordCompilationStats(isolate);
476 }
477 return status;
478}
479
480std::unique_ptr<UnoptimizedCompilationJob> ExecuteUnoptimizedCompileJobs(
481 ParseInfo* parse_info, FunctionLiteral* literal,
482 AccountingAllocator* allocator,
483 UnoptimizedCompilationJobList* inner_function_jobs) {
484 if (UseAsmWasm(literal, parse_info->is_asm_wasm_broken())) {
485 std::unique_ptr<UnoptimizedCompilationJob> asm_job(
486 AsmJs::NewCompilationJob(parse_info, literal, allocator));
487 if (asm_job->ExecuteJob() == CompilationJob::SUCCEEDED) {
488 return asm_job;
489 }
490 // asm.js validation failed, fall through to standard unoptimized compile.
491 // Note: we rely on the fact that AsmJs jobs have done all validation in the
492 // PrepareJob and ExecuteJob phases and can't fail in FinalizeJob with
493 // with a validation error or another error that could be solve by falling
494 // through to standard unoptimized compile.
495 }
496 std::vector<FunctionLiteral*> eager_inner_literals;
497 std::unique_ptr<UnoptimizedCompilationJob> job(
498 interpreter::Interpreter::NewCompilationJob(
499 parse_info, literal, allocator, &eager_inner_literals));
500
501 if (job->ExecuteJob() != CompilationJob::SUCCEEDED) {
502 // Compilation failed, return null.
503 return std::unique_ptr<UnoptimizedCompilationJob>();
504 }
505
506 // Recursively compile eager inner literals.
507 for (FunctionLiteral* inner_literal : eager_inner_literals) {
508 std::unique_ptr<UnoptimizedCompilationJob> inner_job(
509 ExecuteUnoptimizedCompileJobs(parse_info, inner_literal, allocator,
510 inner_function_jobs));
511 // Compilation failed, return null.
512 if (!inner_job) return std::unique_ptr<UnoptimizedCompilationJob>();
513 inner_function_jobs->emplace_front(std::move(inner_job));
514 }
515
516 return job;
517}
518
519std::unique_ptr<UnoptimizedCompilationJob> GenerateUnoptimizedCode(
520 ParseInfo* parse_info, AccountingAllocator* allocator,
521 UnoptimizedCompilationJobList* inner_function_jobs) {
522 DisallowHeapAccess no_heap_access;
523 DCHECK(inner_function_jobs->empty());
524
525 if (!Compiler::Analyze(parse_info)) {
526 return std::unique_ptr<UnoptimizedCompilationJob>();
527 }
528
529 // Prepare and execute compilation of the outer-most function.
530 std::unique_ptr<UnoptimizedCompilationJob> outer_function_job(
531 ExecuteUnoptimizedCompileJobs(parse_info, parse_info->literal(),
532 allocator, inner_function_jobs));
533 if (!outer_function_job) return std::unique_ptr<UnoptimizedCompilationJob>();
534
535 // Character stream shouldn't be used again.
536 parse_info->ResetCharacterStream();
537
538 return outer_function_job;
539}
540
541MaybeHandle<SharedFunctionInfo> GenerateUnoptimizedCodeForToplevel(
542 Isolate* isolate, ParseInfo* parse_info, AccountingAllocator* allocator,
543 IsCompiledScope* is_compiled_scope) {
544 EnsureSharedFunctionInfosArrayOnScript(parse_info, isolate);
545 parse_info->ast_value_factory()->Internalize(isolate);
546
547 if (!Compiler::Analyze(parse_info)) return MaybeHandle<SharedFunctionInfo>();
548 DeclarationScope::AllocateScopeInfos(parse_info, isolate);
549
550 // Prepare and execute compilation of the outer-most function.
551 // Create the SharedFunctionInfo and add it to the script's list.
552 Handle<Script> script = parse_info->script();
553 Handle<SharedFunctionInfo> top_level =
554 isolate->factory()->NewSharedFunctionInfoForLiteral(parse_info->literal(),
555 script, true);
556
557 std::vector<FunctionLiteral*> functions_to_compile;
558 functions_to_compile.push_back(parse_info->literal());
559
560 while (!functions_to_compile.empty()) {
561 FunctionLiteral* literal = functions_to_compile.back();
562 functions_to_compile.pop_back();
563 Handle<SharedFunctionInfo> shared_info =
564 Compiler::GetSharedFunctionInfo(literal, script, isolate);
565 if (shared_info->is_compiled()) continue;
566 if (UseAsmWasm(literal, parse_info->is_asm_wasm_broken())) {
567 std::unique_ptr<UnoptimizedCompilationJob> asm_job(
568 AsmJs::NewCompilationJob(parse_info, literal, allocator));
569 if (asm_job->ExecuteJob() == CompilationJob::SUCCEEDED &&
570 FinalizeUnoptimizedCompilationJob(asm_job.get(), shared_info,
571 isolate) ==
572 CompilationJob::SUCCEEDED) {
573 continue;
574 }
575 // asm.js validation failed, fall through to standard unoptimized compile.
576 // Note: we rely on the fact that AsmJs jobs have done all validation in
577 // the PrepareJob and ExecuteJob phases and can't fail in FinalizeJob with
578 // with a validation error or another error that could be solve by falling
579 // through to standard unoptimized compile.
580 }
581
582 std::unique_ptr<UnoptimizedCompilationJob> job(
583 interpreter::Interpreter::NewCompilationJob(
584 parse_info, literal, allocator, &functions_to_compile));
585
586 if (job->ExecuteJob() == CompilationJob::FAILED ||
587 FinalizeUnoptimizedCompilationJob(job.get(), shared_info, isolate) ==
588 CompilationJob::FAILED) {
589 return MaybeHandle<SharedFunctionInfo>();
590 }
591
592 if (shared_info.is_identical_to(top_level)) {
593 // Ensure that the top level function is retained.
594 *is_compiled_scope = shared_info->is_compiled_scope();
595 DCHECK(is_compiled_scope->is_compiled());
596 }
597 }
598
599 // Character stream shouldn't be used again.
600 parse_info->ResetCharacterStream();
601
602 return top_level;
603}
604
605bool FinalizeUnoptimizedCode(
606 ParseInfo* parse_info, Isolate* isolate,
607 Handle<SharedFunctionInfo> shared_info,
608 UnoptimizedCompilationJob* outer_function_job,
609 UnoptimizedCompilationJobList* inner_function_jobs) {
610 DCHECK(AllowCompilation::IsAllowed(isolate));
611
612 // TODO(rmcilroy): Clear native context in debug once AsmJS generates doesn't
613 // rely on accessing native context during finalization.
614
615 // Allocate scope infos for the literal.
616 DeclarationScope::AllocateScopeInfos(parse_info, isolate);
617
618 // Finalize the outer-most function's compilation job.
619 if (FinalizeUnoptimizedCompilationJob(outer_function_job, shared_info,
620 isolate) != CompilationJob::SUCCEEDED) {
621 return false;
622 }
623
624 // Finalize the inner functions' compilation jobs.
625 for (auto&& inner_job : *inner_function_jobs) {
626 Handle<SharedFunctionInfo> inner_shared_info =
627 Compiler::GetSharedFunctionInfo(
628 inner_job->compilation_info()->literal(), parse_info->script(),
629 isolate);
630 // The inner function might be compiled already if compiling for debug.
631 if (inner_shared_info->is_compiled()) continue;
632 if (FinalizeUnoptimizedCompilationJob(inner_job.get(), inner_shared_info,
633 isolate) !=
634 CompilationJob::SUCCEEDED) {
635 return false;
636 }
637 }
638
639 // Report any warnings generated during compilation.
640 if (parse_info->pending_error_handler()->has_pending_warnings()) {
641 parse_info->pending_error_handler()->ReportWarnings(isolate,
642 parse_info->script());
643 }
644
645 return true;
646}
647
648V8_WARN_UNUSED_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeCache(
649 Handle<JSFunction> function, BailoutId osr_offset) {
650 RuntimeCallTimerScope runtimeTimer(
651 function->GetIsolate(),
652 RuntimeCallCounterId::kCompileGetFromOptimizedCodeMap);
653 Handle<SharedFunctionInfo> shared(function->shared(), function->GetIsolate());
654 DisallowHeapAllocation no_gc;
655 if (osr_offset.IsNone()) {
656 if (function->has_feedback_vector()) {
657 FeedbackVector feedback_vector = function->feedback_vector();
658 feedback_vector->EvictOptimizedCodeMarkedForDeoptimization(
659 function->shared(), "GetCodeFromOptimizedCodeCache");
660 Code code = feedback_vector->optimized_code();
661
662 if (!code.is_null()) {
663 // Caching of optimized code enabled and optimized code found.
664 DCHECK(!code->marked_for_deoptimization());
665 DCHECK(function->shared()->is_compiled());
666 return Handle<Code>(code, feedback_vector->GetIsolate());
667 }
668 }
669 }
670 return MaybeHandle<Code>();
671}
672
673void ClearOptimizedCodeCache(OptimizedCompilationInfo* compilation_info) {
674 Handle<JSFunction> function = compilation_info->closure();
675 if (compilation_info->osr_offset().IsNone()) {
676 Handle<FeedbackVector> vector =
677 handle(function->feedback_vector(), function->GetIsolate());
678 vector->ClearOptimizationMarker();
679 }
680}
681
682void InsertCodeIntoOptimizedCodeCache(
683 OptimizedCompilationInfo* compilation_info) {
684 Handle<Code> code = compilation_info->code();
685 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do.
686
687 // Function context specialization folds-in the function context,
688 // so no sharing can occur.
689 if (compilation_info->is_function_context_specializing()) {
690 // Native context specialized code is not shared, so make sure the optimized
691 // code cache is clear.
692 ClearOptimizedCodeCache(compilation_info);
693 return;
694 }
695
696 // Cache optimized context-specific code.
697 Handle<JSFunction> function = compilation_info->closure();
698 Handle<SharedFunctionInfo> shared(function->shared(), function->GetIsolate());
699 Handle<Context> native_context(function->context()->native_context(),
700 function->GetIsolate());
701 if (compilation_info->osr_offset().IsNone()) {
702 Handle<FeedbackVector> vector =
703 handle(function->feedback_vector(), function->GetIsolate());
704 FeedbackVector::SetOptimizedCode(vector, code);
705 }
706}
707
708bool GetOptimizedCodeNow(OptimizedCompilationJob* job, Isolate* isolate) {
709 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
710 RuntimeCallTimerScope runtimeTimer(
711 isolate, RuntimeCallCounterId::kRecompileSynchronous);
712 OptimizedCompilationInfo* compilation_info = job->compilation_info();
713 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
714 "V8.RecompileSynchronous");
715
716 if (job->PrepareJob(isolate) != CompilationJob::SUCCEEDED ||
717 job->ExecuteJob() != CompilationJob::SUCCEEDED ||
718 job->FinalizeJob(isolate) != CompilationJob::SUCCEEDED) {
719 if (FLAG_trace_opt) {
720 PrintF("[aborted optimizing ");
721 compilation_info->closure()->ShortPrint();
722 PrintF(" because: %s]\n",
723 GetBailoutReason(compilation_info->bailout_reason()));
724 }
725 return false;
726 }
727
728 // Success!
729 job->RecordCompilationStats(OptimizedCompilationJob::kSynchronous, isolate);
730 DCHECK(!isolate->has_pending_exception());
731 InsertCodeIntoOptimizedCodeCache(compilation_info);
732 job->RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, isolate);
733 return true;
734}
735
736bool GetOptimizedCodeLater(OptimizedCompilationJob* job, Isolate* isolate) {
737 OptimizedCompilationInfo* compilation_info = job->compilation_info();
738 if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) {
739 if (FLAG_trace_concurrent_recompilation) {
740 PrintF(" ** Compilation queue full, will retry optimizing ");
741 compilation_info->closure()->ShortPrint();
742 PrintF(" later.\n");
743 }
744 return false;
745 }
746
747 if (isolate->heap()->HighMemoryPressure()) {
748 if (FLAG_trace_concurrent_recompilation) {
749 PrintF(" ** High memory pressure, will retry optimizing ");
750 compilation_info->closure()->ShortPrint();
751 PrintF(" later.\n");
752 }
753 return false;
754 }
755
756 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
757 RuntimeCallTimerScope runtimeTimer(
758 isolate, RuntimeCallCounterId::kRecompileSynchronous);
759 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
760 "V8.RecompileSynchronous");
761
762 if (job->PrepareJob(isolate) != CompilationJob::SUCCEEDED) return false;
763 isolate->optimizing_compile_dispatcher()->QueueForOptimization(job);
764
765 if (FLAG_trace_concurrent_recompilation) {
766 PrintF(" ** Queued ");
767 compilation_info->closure()->ShortPrint();
768 PrintF(" for concurrent optimization.\n");
769 }
770 return true;
771}
772
773MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
774 ConcurrencyMode mode,
775 BailoutId osr_offset = BailoutId::None(),
776 JavaScriptFrame* osr_frame = nullptr) {
777 Isolate* isolate = function->GetIsolate();
778 Handle<SharedFunctionInfo> shared(function->shared(), isolate);
779
780 // Make sure we clear the optimization marker on the function so that we
781 // don't try to re-optimize.
782 if (function->HasOptimizationMarker()) {
783 function->ClearOptimizationMarker();
784 }
785
786 if (shared->optimization_disabled() &&
787 shared->disable_optimization_reason() == BailoutReason::kNeverOptimize) {
788 return MaybeHandle<Code>();
789 }
790
791 if (isolate->debug()->needs_check_on_function_call()) {
792 // Do not optimize when debugger needs to hook into every call.
793 return MaybeHandle<Code>();
794 }
795
796 // If code was pending optimization for testing, delete remove the strong root
797 // that was preventing the bytecode from being flushed between marking and
798 // optimization.
799 if (!isolate->heap()->pending_optimize_for_test_bytecode()->IsUndefined()) {
800 Handle<ObjectHashTable> table =
801 handle(ObjectHashTable::cast(
802 isolate->heap()->pending_optimize_for_test_bytecode()),
803 isolate);
804 bool was_present;
805 table = table->Remove(isolate, table, handle(function->shared(), isolate),
806 &was_present);
807 isolate->heap()->SetPendingOptimizeForTestBytecode(*table);
808 }
809
810 Handle<Code> cached_code;
811 if (GetCodeFromOptimizedCodeCache(function, osr_offset)
812 .ToHandle(&cached_code)) {
813 if (FLAG_trace_opt) {
814 PrintF("[found optimized code for ");
815 function->ShortPrint();
816 if (!osr_offset.IsNone()) {
817 PrintF(" at OSR AST id %d", osr_offset.ToInt());
818 }
819 PrintF("]\n");
820 }
821 return cached_code;
822 }
823
824 // Reset profiler ticks, function is no longer considered hot.
825 DCHECK(shared->is_compiled());
826 function->feedback_vector()->set_profiler_ticks(0);
827
828 VMState<COMPILER> state(isolate);
829 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
830 RuntimeCallTimerScope runtimeTimer(isolate,
831 RuntimeCallCounterId::kOptimizeCode);
832 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.OptimizeCode");
833
834 DCHECK(!isolate->has_pending_exception());
835 PostponeInterruptsScope postpone(isolate);
836 bool has_script = shared->script()->IsScript();
837 // BUG(5946): This DCHECK is necessary to make certain that we won't
838 // tolerate the lack of a script without bytecode.
839 DCHECK_IMPLIES(!has_script, shared->HasBytecodeArray());
840 std::unique_ptr<OptimizedCompilationJob> job(
841 compiler::Pipeline::NewCompilationJob(isolate, function, has_script));
842 OptimizedCompilationInfo* compilation_info = job->compilation_info();
843
844 compilation_info->SetOptimizingForOsr(osr_offset, osr_frame);
845
846 // Do not use TurboFan if we need to be able to set break points.
847 if (compilation_info->shared_info()->HasBreakInfo()) {
848 compilation_info->AbortOptimization(BailoutReason::kFunctionBeingDebugged);
849 return MaybeHandle<Code>();
850 }
851
852 // Do not use TurboFan if optimization is disabled or function doesn't pass
853 // turbo_filter.
854 if (!FLAG_opt || !shared->PassesFilter(FLAG_turbo_filter)) {
855 compilation_info->AbortOptimization(BailoutReason::kOptimizationDisabled);
856 return MaybeHandle<Code>();
857 }
858
859 // In case of concurrent recompilation, all handles below this point will be
860 // allocated in a deferred handle scope that is detached and handed off to
861 // the background thread when we return.
862 base::Optional<CompilationHandleScope> compilation;
863 if (mode == ConcurrencyMode::kConcurrent) {
864 compilation.emplace(isolate, compilation_info);
865 }
866
867 // All handles below will be canonicalized.
868 CanonicalHandleScope canonical(isolate);
869
870 // Reopen handles in the new CompilationHandleScope.
871 compilation_info->ReopenHandlesInNewHandleScope(isolate);
872
873 if (mode == ConcurrencyMode::kConcurrent) {
874 if (GetOptimizedCodeLater(job.get(), isolate)) {
875 job.release(); // The background recompile job owns this now.
876
877 // Set the optimization marker and return a code object which checks it.
878 function->SetOptimizationMarker(OptimizationMarker::kInOptimizationQueue);
879 DCHECK(function->IsInterpreted() ||
880 (!function->is_compiled() && function->shared()->IsInterpreted()));
881 DCHECK(function->shared()->HasBytecodeArray());
882 return BUILTIN_CODE(isolate, InterpreterEntryTrampoline);
883 }
884 } else {
885 if (GetOptimizedCodeNow(job.get(), isolate))
886 return compilation_info->code();
887 }
888
889 if (isolate->has_pending_exception()) isolate->clear_pending_exception();
890 return MaybeHandle<Code>();
891}
892
893bool FailWithPendingException(Isolate* isolate, ParseInfo* parse_info,
894 Compiler::ClearExceptionFlag flag) {
895 if (flag == Compiler::CLEAR_EXCEPTION) {
896 isolate->clear_pending_exception();
897 } else if (!isolate->has_pending_exception()) {
898 if (parse_info->pending_error_handler()->has_pending_error()) {
899 parse_info->pending_error_handler()->ReportErrors(
900 isolate, parse_info->script(), parse_info->ast_value_factory());
901 } else {
902 isolate->StackOverflow();
903 }
904 }
905 return false;
906}
907
908void FinalizeScriptCompilation(Isolate* isolate, ParseInfo* parse_info) {
909 Handle<Script> script = parse_info->script();
910 script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
911
912 // Register any pending parallel tasks with the associated SFI.
913 if (parse_info->parallel_tasks()) {
914 CompilerDispatcher* dispatcher = parse_info->parallel_tasks()->dispatcher();
915 for (auto& it : *parse_info->parallel_tasks()) {
916 FunctionLiteral* literal = it.first;
917 CompilerDispatcher::JobId job_id = it.second;
918 MaybeHandle<SharedFunctionInfo> maybe_shared_for_task =
919 script->FindSharedFunctionInfo(isolate, literal);
920 Handle<SharedFunctionInfo> shared_for_task;
921 if (maybe_shared_for_task.ToHandle(&shared_for_task)) {
922 dispatcher->RegisterSharedFunctionInfo(job_id, *shared_for_task);
923 } else {
924 dispatcher->AbortJob(job_id);
925 }
926 }
927 }
928}
929
930MaybeHandle<SharedFunctionInfo> FinalizeTopLevel(
931 ParseInfo* parse_info, Isolate* isolate,
932 UnoptimizedCompilationJob* outer_function_job,
933 UnoptimizedCompilationJobList* inner_function_jobs) {
934 // Internalize ast values onto the heap.
935 parse_info->ast_value_factory()->Internalize(isolate);
936
937 // Create shared function infos for top level and shared function infos array
938 // for inner functions.
939 EnsureSharedFunctionInfosArrayOnScript(parse_info, isolate);
940 DCHECK_EQ(kNoSourcePosition,
941 parse_info->literal()->function_token_position());
942 Handle<SharedFunctionInfo> shared_info =
943 isolate->factory()->NewSharedFunctionInfoForLiteral(
944 parse_info->literal(), parse_info->script(), true);
945
946 // Finalize compilation of the unoptimized bytecode or asm-js data.
947 if (!FinalizeUnoptimizedCode(parse_info, isolate, shared_info,
948 outer_function_job, inner_function_jobs)) {
949 FailWithPendingException(isolate, parse_info,
950 Compiler::ClearExceptionFlag::KEEP_EXCEPTION);
951 return MaybeHandle<SharedFunctionInfo>();
952 }
953
954 FinalizeScriptCompilation(isolate, parse_info);
955
956 return shared_info;
957}
958
959MaybeHandle<SharedFunctionInfo> CompileToplevel(
960 ParseInfo* parse_info, Isolate* isolate,
961 IsCompiledScope* is_compiled_scope) {
962 TimerEventScope<TimerEventCompileCode> top_level_timer(isolate);
963 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
964 DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
965
966 PostponeInterruptsScope postpone(isolate);
967 DCHECK(!isolate->native_context().is_null());
968 RuntimeCallTimerScope runtimeTimer(
969 isolate, parse_info->is_eval() ? RuntimeCallCounterId::kCompileEval
970 : RuntimeCallCounterId::kCompileScript);
971 VMState<BYTECODE_COMPILER> state(isolate);
972 if (parse_info->literal() == nullptr &&
973 !parsing::ParseProgram(parse_info, isolate)) {
974 return MaybeHandle<SharedFunctionInfo>();
975 }
976 // Measure how long it takes to do the compilation; only take the
977 // rest of the function into account to avoid overlap with the
978 // parsing statistics.
979 HistogramTimer* rate = parse_info->is_eval()
980 ? isolate->counters()->compile_eval()
981 : isolate->counters()->compile();
982 HistogramTimerScope timer(rate);
983 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
984 parse_info->is_eval() ? "V8.CompileEval" : "V8.Compile");
985
986 // Generate the unoptimized bytecode or asm-js data.
987 MaybeHandle<SharedFunctionInfo> shared_info =
988 GenerateUnoptimizedCodeForToplevel(
989 isolate, parse_info, isolate->allocator(), is_compiled_scope);
990 if (shared_info.is_null()) {
991 FailWithPendingException(isolate, parse_info,
992 Compiler::ClearExceptionFlag::KEEP_EXCEPTION);
993 return MaybeHandle<SharedFunctionInfo>();
994 }
995
996 FinalizeScriptCompilation(isolate, parse_info);
997 return shared_info;
998}
999
1000std::unique_ptr<UnoptimizedCompilationJob> CompileOnBackgroundThread(
1001 ParseInfo* parse_info, AccountingAllocator* allocator,
1002 UnoptimizedCompilationJobList* inner_function_jobs) {
1003 DisallowHeapAccess no_heap_access;
1004 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1005 "V8.CompileCodeBackground");
1006 RuntimeCallTimerScope runtimeTimer(
1007 parse_info->runtime_call_stats(),
1008 parse_info->is_toplevel()
1009 ? parse_info->is_eval()
1010 ? RuntimeCallCounterId::kCompileBackgroundEval
1011 : RuntimeCallCounterId::kCompileBackgroundScript
1012 : RuntimeCallCounterId::kCompileBackgroundFunction);
1013
1014 // Generate the unoptimized bytecode or asm-js data.
1015 std::unique_ptr<UnoptimizedCompilationJob> outer_function_job(
1016 GenerateUnoptimizedCode(parse_info, allocator, inner_function_jobs));
1017 return outer_function_job;
1018}
1019
1020} // namespace
1021
1022BackgroundCompileTask::BackgroundCompileTask(ScriptStreamingData* streamed_data,
1023 Isolate* isolate)
1024 : info_(new ParseInfo(isolate)),
1025 stack_size_(i::FLAG_stack_size),
1026 worker_thread_runtime_call_stats_(
1027 isolate->counters()->worker_thread_runtime_call_stats()),
1028 allocator_(isolate->allocator()),
1029 timer_(isolate->counters()->compile_script_on_background()) {
1030 VMState<PARSER> state(isolate);
1031
1032 // Prepare the data for the internalization phase and compilation phase, which
1033 // will happen in the main thread after parsing.
1034 LOG(isolate, ScriptEvent(Logger::ScriptEventType::kStreamingCompile,
1035 info_->script_id()));
1036 info_->set_toplevel();
1037 info_->set_allow_lazy_parsing();
1038 if (V8_UNLIKELY(info_->block_coverage_enabled())) {
1039 info_->AllocateSourceRangeMap();
1040 }
1041 LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1042 info_->set_language_mode(
1043 stricter_language_mode(info_->language_mode(), language_mode));
1044
1045 std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(
1046 streamed_data->source_stream.get(), streamed_data->encoding));
1047 info_->set_character_stream(std::move(stream));
1048}
1049
1050BackgroundCompileTask::BackgroundCompileTask(
1051 AccountingAllocator* allocator, const ParseInfo* outer_parse_info,
1052 const AstRawString* function_name, const FunctionLiteral* function_literal,
1053 WorkerThreadRuntimeCallStats* worker_thread_runtime_stats,
1054 TimedHistogram* timer, int max_stack_size)
1055 : info_(ParseInfo::FromParent(outer_parse_info, allocator, function_literal,
1056 function_name)),
1057 stack_size_(max_stack_size),
1058 worker_thread_runtime_call_stats_(worker_thread_runtime_stats),
1059 allocator_(allocator),
1060 timer_(timer) {
1061 DCHECK(outer_parse_info->is_toplevel());
1062 DCHECK(!function_literal->is_toplevel());
1063
1064 // Clone the character stream so both can be accessed independently.
1065 std::unique_ptr<Utf16CharacterStream> character_stream =
1066 outer_parse_info->character_stream()->Clone();
1067 character_stream->Seek(function_literal->start_position());
1068 info_->set_character_stream(std::move(character_stream));
1069
1070 // Get preparsed scope data from the function literal.
1071 if (function_literal->produced_preparse_data()) {
1072 ZonePreparseData* serialized_data =
1073 function_literal->produced_preparse_data()->Serialize(info_->zone());
1074 info_->set_consumed_preparse_data(
1075 ConsumedPreparseData::For(info_->zone(), serialized_data));
1076 }
1077}
1078
1079BackgroundCompileTask::~BackgroundCompileTask() = default;
1080
1081namespace {
1082
1083// A scope object that ensures a parse info's runtime call stats, stack limit
1084// and on_background_thread fields is set correctly during worker-thread
1085// compile, and restores it after going out of scope.
1086class OffThreadParseInfoScope {
1087 public:
1088 OffThreadParseInfoScope(
1089 ParseInfo* parse_info,
1090 WorkerThreadRuntimeCallStats* worker_thread_runtime_stats, int stack_size)
1091 : parse_info_(parse_info),
1092 original_runtime_call_stats_(parse_info_->runtime_call_stats()),
1093 original_stack_limit_(parse_info_->stack_limit()),
1094 worker_thread_scope_(worker_thread_runtime_stats) {
1095 parse_info_->set_on_background_thread(true);
1096 parse_info_->set_runtime_call_stats(worker_thread_scope_.Get());
1097 parse_info_->set_stack_limit(GetCurrentStackPosition() - stack_size * KB);
1098 }
1099
1100 ~OffThreadParseInfoScope() {
1101 parse_info_->set_stack_limit(original_stack_limit_);
1102 parse_info_->set_runtime_call_stats(original_runtime_call_stats_);
1103 parse_info_->set_on_background_thread(false);
1104 }
1105
1106 private:
1107 ParseInfo* parse_info_;
1108 RuntimeCallStats* original_runtime_call_stats_;
1109 uintptr_t original_stack_limit_;
1110 WorkerThreadRuntimeCallStatsScope worker_thread_scope_;
1111
1112 DISALLOW_COPY_AND_ASSIGN(OffThreadParseInfoScope);
1113};
1114
1115} // namespace
1116
1117void BackgroundCompileTask::Run() {
1118 DisallowHeapAllocation no_allocation;
1119 DisallowHandleAllocation no_handles;
1120 DisallowHeapAccess no_heap_access;
1121
1122 TimedHistogramScope timer(timer_);
1123 OffThreadParseInfoScope off_thread_scope(
1124 info_.get(), worker_thread_runtime_call_stats_, stack_size_);
1125 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1126 "BackgroundCompileTask::Run");
1127 RuntimeCallTimerScope runtimeTimer(
1128 info_->runtime_call_stats(),
1129 RuntimeCallCounterId::kCompileBackgroundCompileTask);
1130
1131 // Update the character stream's runtime call stats.
1132 info_->character_stream()->set_runtime_call_stats(
1133 info_->runtime_call_stats());
1134
1135 // Parser needs to stay alive for finalizing the parsing on the main
1136 // thread.
1137 parser_.reset(new Parser(info_.get()));
1138 parser_->InitializeEmptyScopeChain(info_.get());
1139
1140 parser_->ParseOnBackground(info_.get());
1141 if (info_->literal() != nullptr) {
1142 // Parsing has succeeded, compile.
1143 outer_function_job_ = CompileOnBackgroundThread(info_.get(), allocator_,
1144 &inner_function_jobs_);
1145 }
1146}
1147
1148
1149// ----------------------------------------------------------------------------
1150// Implementation of Compiler
1151
1152bool Compiler::Analyze(ParseInfo* parse_info) {
1153 DCHECK_NOT_NULL(parse_info->literal());
1154 RuntimeCallTimerScope runtimeTimer(
1155 parse_info->runtime_call_stats(),
1156 parse_info->on_background_thread()
1157 ? RuntimeCallCounterId::kCompileBackgroundAnalyse
1158 : RuntimeCallCounterId::kCompileAnalyse);
1159 if (!Rewriter::Rewrite(parse_info)) return false;
1160 if (!DeclarationScope::Analyze(parse_info)) return false;
1161 return true;
1162}
1163
1164bool Compiler::ParseAndAnalyze(ParseInfo* parse_info,
1165 Handle<SharedFunctionInfo> shared_info,
1166 Isolate* isolate) {
1167 if (!parsing::ParseAny(parse_info, shared_info, isolate)) {
1168 return false;
1169 }
1170 return Compiler::Analyze(parse_info);
1171}
1172
1173// static
1174bool Compiler::CollectSourcePositions(Isolate* isolate,
1175 Handle<SharedFunctionInfo> shared_info) {
1176 DCHECK(shared_info->is_compiled());
1177 DCHECK(shared_info->HasBytecodeArray());
1178 DCHECK(!shared_info->GetBytecodeArray()->HasSourcePositionTable());
1179
1180 // Collecting source positions requires allocating a new source position
1181 // table.
1182 DCHECK(AllowHeapAllocation::IsAllowed());
1183
1184 Handle<BytecodeArray> bytecode =
1185 handle(shared_info->GetBytecodeArray(), isolate);
1186
1187 // TODO(v8:8510): Push the CLEAR_EXCEPTION flag or something like it down into
1188 // the parser so it aborts without setting a pending exception, which then
1189 // gets thrown. This would avoid the situation where potentially we'd reparse
1190 // several times (running out of stack each time) before hitting this limit.
1191 if (GetCurrentStackPosition() < isolate->stack_guard()->real_climit()) {
1192 // Stack is already exhausted.
1193 bytecode->SetSourcePositionsFailedToCollect();
1194 return false;
1195 }
1196
1197 DCHECK(AllowCompilation::IsAllowed(isolate));
1198 DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
1199 DCHECK(!isolate->has_pending_exception());
1200 VMState<BYTECODE_COMPILER> state(isolate);
1201 PostponeInterruptsScope postpone(isolate);
1202 RuntimeCallTimerScope runtimeTimer(
1203 isolate, RuntimeCallCounterId::kCompileCollectSourcePositions);
1204 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1205 "V8.CollectSourcePositions");
1206 HistogramTimerScope timer(isolate->counters()->collect_source_positions());
1207
1208 // Set up parse info.
1209 ParseInfo parse_info(isolate, shared_info);
1210 parse_info.set_lazy_compile();
1211 parse_info.set_collect_source_positions();
1212 if (FLAG_allow_natives_syntax) parse_info.set_allow_natives_syntax();
1213
1214 // Parse and update ParseInfo with the results.
1215 if (!parsing::ParseAny(&parse_info, shared_info, isolate)) {
1216 // Parsing failed probably as a result of stack exhaustion.
1217 bytecode->SetSourcePositionsFailedToCollect();
1218 return FailWithPendingException(
1219 isolate, &parse_info, Compiler::ClearExceptionFlag::CLEAR_EXCEPTION);
1220 }
1221
1222 // Generate the unoptimized bytecode.
1223 // TODO(v8:8510): Consider forcing preparsing of inner functions to avoid
1224 // wasting time fully parsing them when they won't ever be used.
1225 UnoptimizedCompilationJobList inner_function_jobs;
1226 std::unique_ptr<UnoptimizedCompilationJob> outer_function_job(
1227 GenerateUnoptimizedCode(&parse_info, isolate->allocator(),
1228 &inner_function_jobs));
1229 if (!outer_function_job) {
1230 // Recompiling failed probably as a result of stack exhaustion.
1231 bytecode->SetSourcePositionsFailedToCollect();
1232 return FailWithPendingException(
1233 isolate, &parse_info, Compiler::ClearExceptionFlag::CLEAR_EXCEPTION);
1234 }
1235
1236 DCHECK(outer_function_job->compilation_info()->collect_source_positions());
1237
1238 // TODO(v8:8510) Avoid re-allocating bytecode array/constant pool and
1239 // re-internalizeing the ast values. Maybe we could use the
1240 // unoptimized_compilation_flag to signal that all we need is the source
1241 // position table (and we could do the DCHECK that the bytecode array is the
1242 // same in the bytecode-generator, by comparing the real bytecode array on the
1243 // SFI with the off-heap bytecode array).
1244
1245 // Internalize ast values onto the heap.
1246 parse_info.ast_value_factory()->Internalize(isolate);
1247
1248 {
1249 // Allocate scope infos for the literal.
1250 DeclarationScope::AllocateScopeInfos(&parse_info, isolate);
1251 CHECK_EQ(outer_function_job->FinalizeJob(shared_info, isolate),
1252 CompilationJob::SUCCEEDED);
1253 }
1254
1255 // Update the source position table on the original bytecode.
1256 DCHECK(bytecode->IsBytecodeEqual(
1257 *outer_function_job->compilation_info()->bytecode_array()));
1258 DCHECK(outer_function_job->compilation_info()->has_bytecode_array());
1259 ByteArray source_position_table = outer_function_job->compilation_info()
1260 ->bytecode_array()
1261 ->SourcePositionTable();
1262 bytecode->set_source_position_table(source_position_table);
1263 // If debugging, make sure that instrumented bytecode has the source position
1264 // table set on it as well.
1265 if (shared_info->HasDebugInfo() &&
1266 shared_info->GetDebugInfo()->HasInstrumentedBytecodeArray()) {
1267 shared_info->GetDebugBytecodeArray()->set_source_position_table(
1268 source_position_table);
1269 }
1270
1271 DCHECK(!isolate->has_pending_exception());
1272 DCHECK(shared_info->is_compiled_scope().is_compiled());
1273 return true;
1274}
1275
1276bool Compiler::Compile(Handle<SharedFunctionInfo> shared_info,
1277 ClearExceptionFlag flag,
1278 IsCompiledScope* is_compiled_scope) {
1279 // We should never reach here if the function is already compiled.
1280 DCHECK(!shared_info->is_compiled());
1281 DCHECK(!is_compiled_scope->is_compiled());
1282
1283 Isolate* isolate = shared_info->GetIsolate();
1284 DCHECK(AllowCompilation::IsAllowed(isolate));
1285 DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
1286 DCHECK(!isolate->has_pending_exception());
1287 DCHECK(!shared_info->HasBytecodeArray());
1288 VMState<BYTECODE_COMPILER> state(isolate);
1289 PostponeInterruptsScope postpone(isolate);
1290 TimerEventScope<TimerEventCompileCode> compile_timer(isolate);
1291 RuntimeCallTimerScope runtimeTimer(isolate,
1292 RuntimeCallCounterId::kCompileFunction);
1293 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
1294 AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy());
1295
1296 // Set up parse info.
1297 ParseInfo parse_info(isolate, shared_info);
1298 parse_info.set_lazy_compile();
1299
1300 // Check if the compiler dispatcher has shared_info enqueued for compile.
1301 CompilerDispatcher* dispatcher = isolate->compiler_dispatcher();
1302 if (dispatcher->IsEnqueued(shared_info)) {
1303 if (!dispatcher->FinishNow(shared_info)) {
1304 return FailWithPendingException(isolate, &parse_info, flag);
1305 }
1306 *is_compiled_scope = shared_info->is_compiled_scope();
1307 DCHECK(is_compiled_scope->is_compiled());
1308 return true;
1309 }
1310
1311 if (shared_info->HasUncompiledDataWithPreparseData()) {
1312 parse_info.set_consumed_preparse_data(ConsumedPreparseData::For(
1313 isolate,
1314 handle(
1315 shared_info->uncompiled_data_with_preparse_data()->preparse_data(),
1316 isolate)));
1317 }
1318
1319 // Parse and update ParseInfo with the results.
1320 if (!parsing::ParseAny(&parse_info, shared_info, isolate)) {
1321 return FailWithPendingException(isolate, &parse_info, flag);
1322 }
1323
1324 // Generate the unoptimized bytecode or asm-js data.
1325 UnoptimizedCompilationJobList inner_function_jobs;
1326 std::unique_ptr<UnoptimizedCompilationJob> outer_function_job(
1327 GenerateUnoptimizedCode(&parse_info, isolate->allocator(),
1328 &inner_function_jobs));
1329 if (!outer_function_job) {
1330 return FailWithPendingException(isolate, &parse_info, flag);
1331 }
1332
1333 // Internalize ast values onto the heap.
1334 parse_info.ast_value_factory()->Internalize(isolate);
1335
1336 // Finalize compilation of the unoptimized bytecode or asm-js data.
1337 if (!FinalizeUnoptimizedCode(&parse_info, isolate, shared_info,
1338 outer_function_job.get(),
1339 &inner_function_jobs)) {
1340 return FailWithPendingException(isolate, &parse_info, flag);
1341 }
1342
1343 DCHECK(!isolate->has_pending_exception());
1344 *is_compiled_scope = shared_info->is_compiled_scope();
1345 DCHECK(is_compiled_scope->is_compiled());
1346 return true;
1347}
1348
1349bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag,
1350 IsCompiledScope* is_compiled_scope) {
1351 // We should never reach here if the function is already compiled or optimized
1352 DCHECK(!function->is_compiled());
1353 DCHECK(!function->IsOptimized());
1354 DCHECK(!function->HasOptimizationMarker());
1355 DCHECK(!function->HasOptimizedCode());
1356
1357 // Reset the JSFunction if we are recompiling due to the bytecode having been
1358 // flushed.
1359 function->ResetIfBytecodeFlushed();
1360
1361 Isolate* isolate = function->GetIsolate();
1362 Handle<SharedFunctionInfo> shared_info = handle(function->shared(), isolate);
1363
1364 // Ensure shared function info is compiled.
1365 *is_compiled_scope = shared_info->is_compiled_scope();
1366 if (!is_compiled_scope->is_compiled() &&
1367 !Compile(shared_info, flag, is_compiled_scope)) {
1368 return false;
1369 }
1370 DCHECK(is_compiled_scope->is_compiled());
1371 Handle<Code> code = handle(shared_info->GetCode(), isolate);
1372
1373 // Initialize the feedback cell for this JSFunction.
1374 JSFunction::InitializeFeedbackCell(function);
1375
1376 // Optimize now if --always-opt is enabled.
1377 if (FLAG_always_opt && !function->shared()->HasAsmWasmData()) {
1378 if (FLAG_trace_opt) {
1379 PrintF("[optimizing ");
1380 function->ShortPrint();
1381 PrintF(" because --always-opt]\n");
1382 }
1383 Handle<Code> opt_code;
1384 if (GetOptimizedCode(function, ConcurrencyMode::kNotConcurrent)
1385 .ToHandle(&opt_code)) {
1386 code = opt_code;
1387 }
1388 }
1389
1390 // Install code on closure.
1391 function->set_code(*code);
1392
1393 // Check postconditions on success.
1394 DCHECK(!isolate->has_pending_exception());
1395 DCHECK(function->shared()->is_compiled());
1396 DCHECK(function->is_compiled());
1397 return true;
1398}
1399
1400bool Compiler::FinalizeBackgroundCompileTask(
1401 BackgroundCompileTask* task, Handle<SharedFunctionInfo> shared_info,
1402 Isolate* isolate, ClearExceptionFlag flag) {
1403 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1404 "V8.FinalizeBackgroundCompileTask");
1405 RuntimeCallTimerScope runtimeTimer(
1406 isolate, RuntimeCallCounterId::kCompileFinalizeBackgroundCompileTask);
1407 HandleScope scope(isolate);
1408 ParseInfo* parse_info = task->info();
1409 DCHECK(!parse_info->is_toplevel());
1410 DCHECK(!shared_info->is_compiled());
1411
1412 Handle<Script> script(Script::cast(shared_info->script()), isolate);
1413 parse_info->set_script(script);
1414
1415 task->parser()->UpdateStatistics(isolate, script);
1416 task->parser()->HandleSourceURLComments(isolate, script);
1417
1418 if (parse_info->literal() == nullptr || !task->outer_function_job()) {
1419 // Parsing or compile failed on background thread - report error messages.
1420 return FailWithPendingException(isolate, parse_info, flag);
1421 }
1422
1423 // Parsing has succeeded - finalize compilation.
1424 parse_info->ast_value_factory()->Internalize(isolate);
1425 if (!FinalizeUnoptimizedCode(parse_info, isolate, shared_info,
1426 task->outer_function_job(),
1427 task->inner_function_jobs())) {
1428 // Finalization failed - throw an exception.
1429 return FailWithPendingException(isolate, parse_info, flag);
1430 }
1431
1432 DCHECK(!isolate->has_pending_exception());
1433 DCHECK(shared_info->is_compiled());
1434 return true;
1435}
1436
1437bool Compiler::CompileOptimized(Handle<JSFunction> function,
1438 ConcurrencyMode mode) {
1439 if (function->IsOptimized()) return true;
1440 Isolate* isolate = function->GetIsolate();
1441 DCHECK(AllowCompilation::IsAllowed(isolate));
1442
1443 // Start a compilation.
1444 Handle<Code> code;
1445 if (!GetOptimizedCode(function, mode).ToHandle(&code)) {
1446 // Optimization failed, get unoptimized code. Unoptimized code must exist
1447 // already if we are optimizing.
1448 DCHECK(!isolate->has_pending_exception());
1449 DCHECK(function->shared()->is_compiled());
1450 DCHECK(function->shared()->IsInterpreted());
1451 code = BUILTIN_CODE(isolate, InterpreterEntryTrampoline);
1452 }
1453
1454 // Install code on closure.
1455 function->set_code(*code);
1456
1457 // Check postconditions on success.
1458 DCHECK(!isolate->has_pending_exception());
1459 DCHECK(function->shared()->is_compiled());
1460 DCHECK(function->is_compiled());
1461 DCHECK_IMPLIES(function->HasOptimizationMarker(),
1462 function->IsInOptimizationQueue());
1463 DCHECK_IMPLIES(function->HasOptimizationMarker(),
1464 function->ChecksOptimizationMarker());
1465 DCHECK_IMPLIES(function->IsInOptimizationQueue(),
1466 mode == ConcurrencyMode::kConcurrent);
1467 return true;
1468}
1469
1470MaybeHandle<SharedFunctionInfo> Compiler::CompileForLiveEdit(
1471 ParseInfo* parse_info, Isolate* isolate) {
1472 IsCompiledScope is_compiled_scope;
1473 return CompileToplevel(parse_info, isolate, &is_compiled_scope);
1474}
1475
1476MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
1477 Handle<String> source, Handle<SharedFunctionInfo> outer_info,
1478 Handle<Context> context, LanguageMode language_mode,
1479 ParseRestriction restriction, int parameters_end_pos,
1480 int eval_scope_position, int eval_position) {
1481 Isolate* isolate = context->GetIsolate();
1482 int source_length = source->length();
1483 isolate->counters()->total_eval_size()->Increment(source_length);
1484 isolate->counters()->total_compile_size()->Increment(source_length);
1485
1486 // The cache lookup key needs to be aware of the separation between the
1487 // parameters and the body to prevent this valid invocation:
1488 // Function("", "function anonymous(\n/**/) {\n}");
1489 // from adding an entry that falsely approves this invalid invocation:
1490 // Function("\n/**/) {\nfunction anonymous(", "}");
1491 // The actual eval_scope_position for indirect eval and CreateDynamicFunction
1492 // is unused (just 0), which means it's an available field to use to indicate
1493 // this separation. But to make sure we're not causing other false hits, we
1494 // negate the scope position.
1495 if (restriction == ONLY_SINGLE_FUNCTION_LITERAL &&
1496 parameters_end_pos != kNoSourcePosition) {
1497 // use the parameters_end_pos as the eval_scope_position in the eval cache.
1498 DCHECK_EQ(eval_scope_position, 0);
1499 eval_scope_position = -parameters_end_pos;
1500 }
1501 CompilationCache* compilation_cache = isolate->compilation_cache();
1502 InfoCellPair eval_result = compilation_cache->LookupEval(
1503 source, outer_info, context, language_mode, eval_scope_position);
1504 Handle<FeedbackCell> feedback_cell;
1505 if (eval_result.has_feedback_cell()) {
1506 feedback_cell = handle(eval_result.feedback_cell(), isolate);
1507 }
1508
1509 Handle<SharedFunctionInfo> shared_info;
1510 Handle<Script> script;
1511 IsCompiledScope is_compiled_scope;
1512 bool allow_eval_cache;
1513 if (eval_result.has_shared()) {
1514 shared_info = Handle<SharedFunctionInfo>(eval_result.shared(), isolate);
1515 script = Handle<Script>(Script::cast(shared_info->script()), isolate);
1516 is_compiled_scope = shared_info->is_compiled_scope();
1517 allow_eval_cache = true;
1518 } else {
1519 ParseInfo parse_info(isolate);
1520 script = parse_info.CreateScript(
1521 isolate, source, OriginOptionsForEval(outer_info->script()));
1522 script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
1523 script->set_eval_from_shared(*outer_info);
1524 if (eval_position == kNoSourcePosition) {
1525 // If the position is missing, attempt to get the code offset by
1526 // walking the stack. Do not translate the code offset into source
1527 // position, but store it as negative value for lazy translation.
1528 StackTraceFrameIterator it(isolate);
1529 if (!it.done() && it.is_javascript()) {
1530 FrameSummary summary = FrameSummary::GetTop(it.javascript_frame());
1531 script->set_eval_from_shared(
1532 summary.AsJavaScript().function()->shared());
1533 script->set_origin_options(OriginOptionsForEval(*summary.script()));
1534 eval_position = -summary.code_offset();
1535 } else {
1536 eval_position = 0;
1537 }
1538 }
1539 script->set_eval_from_position(eval_position);
1540 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
1541 TRACE_DISABLED_BY_DEFAULT("v8.compile"), "Script",
1542 TRACE_ID_WITH_SCOPE(Script::kTraceScope, script->id()),
1543 script->ToTracedValue());
1544
1545 parse_info.set_eval();
1546 parse_info.set_language_mode(language_mode);
1547 parse_info.set_parse_restriction(restriction);
1548 parse_info.set_parameters_end_pos(parameters_end_pos);
1549 if (!context->IsNativeContext()) {
1550 parse_info.set_outer_scope_info(handle(context->scope_info(), isolate));
1551 }
1552 DCHECK(!parse_info.is_module());
1553
1554 if (!CompileToplevel(&parse_info, isolate, &is_compiled_scope)
1555 .ToHandle(&shared_info)) {
1556 return MaybeHandle<JSFunction>();
1557 }
1558 allow_eval_cache = parse_info.allow_eval_cache();
1559 }
1560
1561 // If caller is strict mode, the result must be in strict mode as well.
1562 DCHECK(is_sloppy(language_mode) || is_strict(shared_info->language_mode()));
1563
1564 Handle<JSFunction> result;
1565 if (eval_result.has_shared()) {
1566 if (eval_result.has_feedback_cell()) {
1567 result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1568 shared_info, context, feedback_cell, AllocationType::kYoung);
1569 } else {
1570 result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1571 shared_info, context, AllocationType::kYoung);
1572 JSFunction::InitializeFeedbackCell(result);
1573 if (allow_eval_cache) {
1574 // Make sure to cache this result.
1575 Handle<FeedbackCell> new_feedback_cell(result->raw_feedback_cell(),
1576 isolate);
1577 compilation_cache->PutEval(source, outer_info, context, shared_info,
1578 new_feedback_cell, eval_scope_position);
1579 }
1580 }
1581 } else {
1582 result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1583 shared_info, context, AllocationType::kYoung);
1584 JSFunction::InitializeFeedbackCell(result);
1585 if (allow_eval_cache) {
1586 // Add the SharedFunctionInfo and the LiteralsArray to the eval cache if
1587 // we didn't retrieve from there.
1588 Handle<FeedbackCell> new_feedback_cell(result->raw_feedback_cell(),
1589 isolate);
1590 compilation_cache->PutEval(source, outer_info, context, shared_info,
1591 new_feedback_cell, eval_scope_position);
1592 }
1593 }
1594 DCHECK(is_compiled_scope.is_compiled());
1595
1596 return result;
1597}
1598
1599
1600bool Compiler::CodeGenerationFromStringsAllowed(Isolate* isolate,
1601 Handle<Context> context,
1602 Handle<String> source) {
1603 DCHECK(context->allow_code_gen_from_strings()->IsFalse(isolate));
1604 // Check with callback if set.
1605 AllowCodeGenerationFromStringsCallback callback =
1606 isolate->allow_code_gen_callback();
1607 if (callback == nullptr) {
1608 // No callback set and code generation disallowed.
1609 return false;
1610 } else {
1611 // Callback set. Let it decide if code generation is allowed.
1612 VMState<EXTERNAL> state(isolate);
1613 return callback(v8::Utils::ToLocal(context), v8::Utils::ToLocal(source));
1614 }
1615}
1616
1617MaybeHandle<JSFunction> Compiler::GetFunctionFromString(
1618 Handle<Context> context, Handle<String> source,
1619 ParseRestriction restriction, int parameters_end_pos) {
1620 Isolate* const isolate = context->GetIsolate();
1621 Handle<Context> native_context(context->native_context(), isolate);
1622
1623 // Check if native context allows code generation from
1624 // strings. Throw an exception if it doesn't.
1625 if (native_context->allow_code_gen_from_strings()->IsFalse(isolate) &&
1626 !CodeGenerationFromStringsAllowed(isolate, native_context, source)) {
1627 Handle<Object> error_message =
1628 native_context->ErrorMessageForCodeGenerationFromStrings();
1629 THROW_NEW_ERROR(isolate, NewEvalError(MessageTemplate::kCodeGenFromStrings,
1630 error_message),
1631 JSFunction);
1632 }
1633
1634 // Compile source string in the native context.
1635 int eval_scope_position = 0;
1636 int eval_position = kNoSourcePosition;
1637 Handle<SharedFunctionInfo> outer_info(
1638 native_context->empty_function()->shared(), isolate);
1639 return Compiler::GetFunctionFromEval(
1640 source, outer_info, native_context, LanguageMode::kSloppy, restriction,
1641 parameters_end_pos, eval_scope_position, eval_position);
1642}
1643
1644namespace {
1645
1646struct ScriptCompileTimerScope {
1647 public:
1648 // TODO(leszeks): There are too many blink-specific entries in this enum,
1649 // figure out a way to push produce/hit-isolate-cache/consume/consume-failed
1650 // back up the API and log them in blink instead.
1651 enum class CacheBehaviour {
1652 kProduceCodeCache,
1653 kHitIsolateCacheWhenNoCache,
1654 kConsumeCodeCache,
1655 kConsumeCodeCacheFailed,
1656 kNoCacheBecauseInlineScript,
1657 kNoCacheBecauseScriptTooSmall,
1658 kNoCacheBecauseCacheTooCold,
1659 kNoCacheNoReason,
1660 kNoCacheBecauseNoResource,
1661 kNoCacheBecauseInspector,
1662 kNoCacheBecauseCachingDisabled,
1663 kNoCacheBecauseModule,
1664 kNoCacheBecauseStreamingSource,
1665 kNoCacheBecauseV8Extension,
1666 kHitIsolateCacheWhenProduceCodeCache,
1667 kHitIsolateCacheWhenConsumeCodeCache,
1668 kNoCacheBecauseExtensionModule,
1669 kNoCacheBecausePacScript,
1670 kNoCacheBecauseInDocumentWrite,
1671 kNoCacheBecauseResourceWithNoCacheHandler,
1672 kHitIsolateCacheWhenStreamingSource,
1673 kCount
1674 };
1675
1676 explicit ScriptCompileTimerScope(
1677 Isolate* isolate, ScriptCompiler::NoCacheReason no_cache_reason)
1678 : isolate_(isolate),
1679 all_scripts_histogram_scope_(isolate->counters()->compile_script(),
1680 true),
1681 no_cache_reason_(no_cache_reason),
1682 hit_isolate_cache_(false),
1683 producing_code_cache_(false),
1684 consuming_code_cache_(false),
1685 consuming_code_cache_failed_(false) {}
1686
1687 ~ScriptCompileTimerScope() {
1688 CacheBehaviour cache_behaviour = GetCacheBehaviour();
1689
1690 Histogram* cache_behaviour_histogram =
1691 isolate_->counters()->compile_script_cache_behaviour();
1692 // Sanity check that the histogram has exactly one bin per enum entry.
1693 DCHECK_EQ(0, cache_behaviour_histogram->min());
1694 DCHECK_EQ(static_cast<int>(CacheBehaviour::kCount),
1695 cache_behaviour_histogram->max() + 1);
1696 DCHECK_EQ(static_cast<int>(CacheBehaviour::kCount),
1697 cache_behaviour_histogram->num_buckets());
1698 cache_behaviour_histogram->AddSample(static_cast<int>(cache_behaviour));
1699
1700 histogram_scope_.set_histogram(
1701 GetCacheBehaviourTimedHistogram(cache_behaviour));
1702 }
1703
1704 void set_hit_isolate_cache() { hit_isolate_cache_ = true; }
1705
1706 void set_producing_code_cache() { producing_code_cache_ = true; }
1707
1708 void set_consuming_code_cache() { consuming_code_cache_ = true; }
1709
1710 void set_consuming_code_cache_failed() {
1711 consuming_code_cache_failed_ = true;
1712 }
1713
1714 private:
1715 Isolate* isolate_;
1716 LazyTimedHistogramScope histogram_scope_;
1717 // TODO(leszeks): This timer is the sum of the other times, consider removing
1718 // it to save space.
1719 HistogramTimerScope all_scripts_histogram_scope_;
1720 ScriptCompiler::NoCacheReason no_cache_reason_;
1721 bool hit_isolate_cache_;
1722 bool producing_code_cache_;
1723 bool consuming_code_cache_;
1724 bool consuming_code_cache_failed_;
1725
1726 CacheBehaviour GetCacheBehaviour() {
1727 if (producing_code_cache_) {
1728 if (hit_isolate_cache_) {
1729 return CacheBehaviour::kHitIsolateCacheWhenProduceCodeCache;
1730 } else {
1731 return CacheBehaviour::kProduceCodeCache;
1732 }
1733 }
1734
1735 if (consuming_code_cache_) {
1736 if (hit_isolate_cache_) {
1737 return CacheBehaviour::kHitIsolateCacheWhenConsumeCodeCache;
1738 } else if (consuming_code_cache_failed_) {
1739 return CacheBehaviour::kConsumeCodeCacheFailed;
1740 }
1741 return CacheBehaviour::kConsumeCodeCache;
1742 }
1743
1744 if (hit_isolate_cache_) {
1745 if (no_cache_reason_ == ScriptCompiler::kNoCacheBecauseStreamingSource) {
1746 return CacheBehaviour::kHitIsolateCacheWhenStreamingSource;
1747 }
1748 return CacheBehaviour::kHitIsolateCacheWhenNoCache;
1749 }
1750
1751 switch (no_cache_reason_) {
1752 case ScriptCompiler::kNoCacheBecauseInlineScript:
1753 return CacheBehaviour::kNoCacheBecauseInlineScript;
1754 case ScriptCompiler::kNoCacheBecauseScriptTooSmall:
1755 return CacheBehaviour::kNoCacheBecauseScriptTooSmall;
1756 case ScriptCompiler::kNoCacheBecauseCacheTooCold:
1757 return CacheBehaviour::kNoCacheBecauseCacheTooCold;
1758 case ScriptCompiler::kNoCacheNoReason:
1759 return CacheBehaviour::kNoCacheNoReason;
1760 case ScriptCompiler::kNoCacheBecauseNoResource:
1761 return CacheBehaviour::kNoCacheBecauseNoResource;
1762 case ScriptCompiler::kNoCacheBecauseInspector:
1763 return CacheBehaviour::kNoCacheBecauseInspector;
1764 case ScriptCompiler::kNoCacheBecauseCachingDisabled:
1765 return CacheBehaviour::kNoCacheBecauseCachingDisabled;
1766 case ScriptCompiler::kNoCacheBecauseModule:
1767 return CacheBehaviour::kNoCacheBecauseModule;
1768 case ScriptCompiler::kNoCacheBecauseStreamingSource:
1769 return CacheBehaviour::kNoCacheBecauseStreamingSource;
1770 case ScriptCompiler::kNoCacheBecauseV8Extension:
1771 return CacheBehaviour::kNoCacheBecauseV8Extension;
1772 case ScriptCompiler::kNoCacheBecauseExtensionModule:
1773 return CacheBehaviour::kNoCacheBecauseExtensionModule;
1774 case ScriptCompiler::kNoCacheBecausePacScript:
1775 return CacheBehaviour::kNoCacheBecausePacScript;
1776 case ScriptCompiler::kNoCacheBecauseInDocumentWrite:
1777 return CacheBehaviour::kNoCacheBecauseInDocumentWrite;
1778 case ScriptCompiler::kNoCacheBecauseResourceWithNoCacheHandler:
1779 return CacheBehaviour::kNoCacheBecauseResourceWithNoCacheHandler;
1780 case ScriptCompiler::kNoCacheBecauseDeferredProduceCodeCache: {
1781 if (hit_isolate_cache_) {
1782 return CacheBehaviour::kHitIsolateCacheWhenProduceCodeCache;
1783 } else {
1784 return CacheBehaviour::kProduceCodeCache;
1785 }
1786 }
1787 }
1788 UNREACHABLE();
1789 }
1790
1791 TimedHistogram* GetCacheBehaviourTimedHistogram(
1792 CacheBehaviour cache_behaviour) {
1793 switch (cache_behaviour) {
1794 case CacheBehaviour::kProduceCodeCache:
1795 // Even if we hit the isolate's compilation cache, we currently recompile
1796 // when we want to produce the code cache.
1797 case CacheBehaviour::kHitIsolateCacheWhenProduceCodeCache:
1798 return isolate_->counters()->compile_script_with_produce_cache();
1799 case CacheBehaviour::kHitIsolateCacheWhenNoCache:
1800 case CacheBehaviour::kHitIsolateCacheWhenConsumeCodeCache:
1801 case CacheBehaviour::kHitIsolateCacheWhenStreamingSource:
1802 return isolate_->counters()->compile_script_with_isolate_cache_hit();
1803 case CacheBehaviour::kConsumeCodeCacheFailed:
1804 return isolate_->counters()->compile_script_consume_failed();
1805 case CacheBehaviour::kConsumeCodeCache:
1806 return isolate_->counters()->compile_script_with_consume_cache();
1807
1808 case CacheBehaviour::kNoCacheBecauseInlineScript:
1809 return isolate_->counters()
1810 ->compile_script_no_cache_because_inline_script();
1811 case CacheBehaviour::kNoCacheBecauseScriptTooSmall:
1812 return isolate_->counters()
1813 ->compile_script_no_cache_because_script_too_small();
1814 case CacheBehaviour::kNoCacheBecauseCacheTooCold:
1815 return isolate_->counters()
1816 ->compile_script_no_cache_because_cache_too_cold();
1817
1818 // Aggregate all the other "no cache" counters into a single histogram, to
1819 // save space.
1820 case CacheBehaviour::kNoCacheNoReason:
1821 case CacheBehaviour::kNoCacheBecauseNoResource:
1822 case CacheBehaviour::kNoCacheBecauseInspector:
1823 case CacheBehaviour::kNoCacheBecauseCachingDisabled:
1824 // TODO(leszeks): Consider counting separately once modules are more
1825 // common.
1826 case CacheBehaviour::kNoCacheBecauseModule:
1827 // TODO(leszeks): Count separately or remove entirely once we have
1828 // background compilation.
1829 case CacheBehaviour::kNoCacheBecauseStreamingSource:
1830 case CacheBehaviour::kNoCacheBecauseV8Extension:
1831 case CacheBehaviour::kNoCacheBecauseExtensionModule:
1832 case CacheBehaviour::kNoCacheBecausePacScript:
1833 case CacheBehaviour::kNoCacheBecauseInDocumentWrite:
1834 case CacheBehaviour::kNoCacheBecauseResourceWithNoCacheHandler:
1835 return isolate_->counters()->compile_script_no_cache_other();
1836
1837 case CacheBehaviour::kCount:
1838 UNREACHABLE();
1839 }
1840 UNREACHABLE();
1841 }
1842};
1843
1844Handle<Script> NewScript(Isolate* isolate, ParseInfo* parse_info,
1845 Handle<String> source,
1846 Compiler::ScriptDetails script_details,
1847 ScriptOriginOptions origin_options,
1848 NativesFlag natives) {
1849 // Create a script object describing the script to be compiled.
1850 Handle<Script> script =
1851 parse_info->CreateScript(isolate, source, origin_options, natives);
1852 Handle<Object> script_name;
1853 if (script_details.name_obj.ToHandle(&script_name)) {
1854 script->set_name(*script_name);
1855 script->set_line_offset(script_details.line_offset);
1856 script->set_column_offset(script_details.column_offset);
1857 }
1858 Handle<Object> source_map_url;
1859 if (script_details.source_map_url.ToHandle(&source_map_url)) {
1860 script->set_source_mapping_url(*source_map_url);
1861 }
1862 Handle<FixedArray> host_defined_options;
1863 if (script_details.host_defined_options.ToHandle(&host_defined_options)) {
1864 script->set_host_defined_options(*host_defined_options);
1865 }
1866 LOG(isolate, ScriptDetails(*script));
1867 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
1868 TRACE_DISABLED_BY_DEFAULT("v8.compile"), "Script",
1869 TRACE_ID_WITH_SCOPE(Script::kTraceScope, script->id()),
1870 script->ToTracedValue());
1871 return script;
1872}
1873
1874} // namespace
1875
1876MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
1877 Isolate* isolate, Handle<String> source,
1878 const Compiler::ScriptDetails& script_details,
1879 ScriptOriginOptions origin_options, v8::Extension* extension,
1880 ScriptData* cached_data, ScriptCompiler::CompileOptions compile_options,
1881 ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag natives) {
1882 ScriptCompileTimerScope compile_timer(isolate, no_cache_reason);
1883
1884 if (compile_options == ScriptCompiler::kNoCompileOptions ||
1885 compile_options == ScriptCompiler::kEagerCompile) {
1886 DCHECK_NULL(cached_data);
1887 } else {
1888 DCHECK(compile_options == ScriptCompiler::kConsumeCodeCache);
1889 DCHECK(cached_data);
1890 DCHECK_NULL(extension);
1891 }
1892 int source_length = source->length();
1893 isolate->counters()->total_load_size()->Increment(source_length);
1894 isolate->counters()->total_compile_size()->Increment(source_length);
1895
1896 LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1897 CompilationCache* compilation_cache = isolate->compilation_cache();
1898
1899 // Do a lookup in the compilation cache but not for extensions.
1900 MaybeHandle<SharedFunctionInfo> maybe_result;
1901 IsCompiledScope is_compiled_scope;
1902 if (extension == nullptr) {
1903 bool can_consume_code_cache =
1904 compile_options == ScriptCompiler::kConsumeCodeCache;
1905 if (can_consume_code_cache) {
1906 compile_timer.set_consuming_code_cache();
1907 }
1908
1909 // First check per-isolate compilation cache.
1910 maybe_result = compilation_cache->LookupScript(
1911 source, script_details.name_obj, script_details.line_offset,
1912 script_details.column_offset, origin_options, isolate->native_context(),
1913 language_mode);
1914 if (!maybe_result.is_null()) {
1915 compile_timer.set_hit_isolate_cache();
1916 } else if (can_consume_code_cache) {
1917 compile_timer.set_consuming_code_cache();
1918 // Then check cached code provided by embedder.
1919 HistogramTimerScope timer(isolate->counters()->compile_deserialize());
1920 RuntimeCallTimerScope runtimeTimer(
1921 isolate, RuntimeCallCounterId::kCompileDeserialize);
1922 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1923 "V8.CompileDeserialize");
1924 Handle<SharedFunctionInfo> inner_result;
1925 if (CodeSerializer::Deserialize(isolate, cached_data, source,
1926 origin_options)
1927 .ToHandle(&inner_result) &&
1928 inner_result->is_compiled()) {
1929 // Promote to per-isolate compilation cache.
1930 is_compiled_scope = inner_result->is_compiled_scope();
1931 DCHECK(is_compiled_scope.is_compiled());
1932 compilation_cache->PutScript(source, isolate->native_context(),
1933 language_mode, inner_result);
1934 Handle<Script> script(Script::cast(inner_result->script()), isolate);
1935 maybe_result = inner_result;
1936 } else {
1937 // Deserializer failed. Fall through to compile.
1938 compile_timer.set_consuming_code_cache_failed();
1939 }
1940 }
1941 }
1942
1943 if (maybe_result.is_null()) {
1944 ParseInfo parse_info(isolate);
1945 // No cache entry found compile the script.
1946 NewScript(isolate, &parse_info, source, script_details, origin_options,
1947 natives);
1948
1949 // Compile the function and add it to the isolate cache.
1950 if (origin_options.IsModule()) parse_info.set_module();
1951 parse_info.set_extension(extension);
1952 parse_info.set_eager(compile_options == ScriptCompiler::kEagerCompile);
1953
1954 parse_info.set_language_mode(
1955 stricter_language_mode(parse_info.language_mode(), language_mode));
1956 maybe_result = CompileToplevel(&parse_info, isolate, &is_compiled_scope);
1957 Handle<SharedFunctionInfo> result;
1958 if (extension == nullptr && maybe_result.ToHandle(&result)) {
1959 DCHECK(is_compiled_scope.is_compiled());
1960 compilation_cache->PutScript(source, isolate->native_context(),
1961 language_mode, result);
1962 } else if (maybe_result.is_null() && natives != EXTENSION_CODE) {
1963 isolate->ReportPendingMessages();
1964 }
1965 }
1966
1967 return maybe_result;
1968}
1969
1970MaybeHandle<JSFunction> Compiler::GetWrappedFunction(
1971 Handle<String> source, Handle<FixedArray> arguments,
1972 Handle<Context> context, const Compiler::ScriptDetails& script_details,
1973 ScriptOriginOptions origin_options, ScriptData* cached_data,
1974 v8::ScriptCompiler::CompileOptions compile_options,
1975 v8::ScriptCompiler::NoCacheReason no_cache_reason) {
1976 Isolate* isolate = context->GetIsolate();
1977 ScriptCompileTimerScope compile_timer(isolate, no_cache_reason);
1978
1979 if (compile_options == ScriptCompiler::kNoCompileOptions ||
1980 compile_options == ScriptCompiler::kEagerCompile) {
1981 DCHECK_NULL(cached_data);
1982 } else {
1983 DCHECK(compile_options == ScriptCompiler::kConsumeCodeCache);
1984 DCHECK(cached_data);
1985 }
1986
1987 int source_length = source->length();
1988 isolate->counters()->total_compile_size()->Increment(source_length);
1989
1990 LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1991
1992 MaybeHandle<SharedFunctionInfo> maybe_result;
1993 bool can_consume_code_cache =
1994 compile_options == ScriptCompiler::kConsumeCodeCache;
1995 if (can_consume_code_cache) {
1996 compile_timer.set_consuming_code_cache();
1997 // Then check cached code provided by embedder.
1998 HistogramTimerScope timer(isolate->counters()->compile_deserialize());
1999 RuntimeCallTimerScope runtimeTimer(
2000 isolate, RuntimeCallCounterId::kCompileDeserialize);
2001 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
2002 "V8.CompileDeserialize");
2003 maybe_result = CodeSerializer::Deserialize(isolate, cached_data, source,
2004 origin_options);
2005 if (maybe_result.is_null()) {
2006 // Deserializer failed. Fall through to compile.
2007 compile_timer.set_consuming_code_cache_failed();
2008 }
2009 }
2010
2011 Handle<SharedFunctionInfo> wrapped;
2012 Handle<Script> script;
2013 IsCompiledScope is_compiled_scope;
2014 if (!maybe_result.ToHandle(&wrapped)) {
2015 ParseInfo parse_info(isolate);
2016 script = NewScript(isolate, &parse_info, source, script_details,
2017 origin_options, NOT_NATIVES_CODE);
2018 script->set_wrapped_arguments(*arguments);
2019
2020 parse_info.set_eval(); // Use an eval scope as declaration scope.
2021 parse_info.set_wrapped_as_function();
2022 // parse_info.set_eager(compile_options == ScriptCompiler::kEagerCompile);
2023 if (!context->IsNativeContext()) {
2024 parse_info.set_outer_scope_info(handle(context->scope_info(), isolate));
2025 }
2026 parse_info.set_language_mode(
2027 stricter_language_mode(parse_info.language_mode(), language_mode));
2028
2029 Handle<SharedFunctionInfo> top_level;
2030 maybe_result = CompileToplevel(&parse_info, isolate, &is_compiled_scope);
2031 if (maybe_result.is_null()) isolate->ReportPendingMessages();
2032 ASSIGN_RETURN_ON_EXCEPTION(isolate, top_level, maybe_result, JSFunction);
2033
2034 SharedFunctionInfo::ScriptIterator infos(isolate, *script);
2035 for (SharedFunctionInfo info = infos.Next(); !info.is_null();
2036 info = infos.Next()) {
2037 if (info->is_wrapped()) {
2038 wrapped = Handle<SharedFunctionInfo>(info, isolate);
2039 break;
2040 }
2041 }
2042 DCHECK(!wrapped.is_null());
2043 } else {
2044 is_compiled_scope = wrapped->is_compiled_scope();
2045 script = Handle<Script>(Script::cast(wrapped->script()), isolate);
2046 }
2047 DCHECK(is_compiled_scope.is_compiled());
2048
2049 return isolate->factory()->NewFunctionFromSharedFunctionInfo(
2050 wrapped, context, AllocationType::kYoung);
2051}
2052
2053MaybeHandle<SharedFunctionInfo>
2054Compiler::GetSharedFunctionInfoForStreamedScript(
2055 Isolate* isolate, Handle<String> source,
2056 const ScriptDetails& script_details, ScriptOriginOptions origin_options,
2057 ScriptStreamingData* streaming_data) {
2058 ScriptCompileTimerScope compile_timer(
2059 isolate, ScriptCompiler::kNoCacheBecauseStreamingSource);
2060 PostponeInterruptsScope postpone(isolate);
2061
2062 int source_length = source->length();
2063 isolate->counters()->total_load_size()->Increment(source_length);
2064 isolate->counters()->total_compile_size()->Increment(source_length);
2065
2066 BackgroundCompileTask* task = streaming_data->task.get();
2067 ParseInfo* parse_info = task->info();
2068 DCHECK(parse_info->is_toplevel());
2069 // Check if compile cache already holds the SFI, if so no need to finalize
2070 // the code compiled on the background thread.
2071 CompilationCache* compilation_cache = isolate->compilation_cache();
2072 MaybeHandle<SharedFunctionInfo> maybe_result =
2073 compilation_cache->LookupScript(
2074 source, script_details.name_obj, script_details.line_offset,
2075 script_details.column_offset, origin_options,
2076 isolate->native_context(), parse_info->language_mode());
2077 if (!maybe_result.is_null()) {
2078 compile_timer.set_hit_isolate_cache();
2079 }
2080
2081 if (maybe_result.is_null()) {
2082 // No cache entry found, finalize compilation of the script and add it to
2083 // the isolate cache.
2084 Handle<Script> script =
2085 NewScript(isolate, parse_info, source, script_details, origin_options,
2086 NOT_NATIVES_CODE);
2087 task->parser()->UpdateStatistics(isolate, script);
2088 task->parser()->HandleSourceURLComments(isolate, script);
2089
2090 if (parse_info->literal() == nullptr || !task->outer_function_job()) {
2091 // Parsing has failed - report error messages.
2092 FailWithPendingException(isolate, parse_info,
2093 Compiler::ClearExceptionFlag::KEEP_EXCEPTION);
2094 } else {
2095 // Parsing has succeeded - finalize compilation.
2096 maybe_result =
2097 FinalizeTopLevel(parse_info, isolate, task->outer_function_job(),
2098 task->inner_function_jobs());
2099 if (maybe_result.is_null()) {
2100 // Finalization failed - throw an exception.
2101 FailWithPendingException(isolate, parse_info,
2102 Compiler::ClearExceptionFlag::KEEP_EXCEPTION);
2103 }
2104 }
2105
2106 // Add compiled code to the isolate cache.
2107 Handle<SharedFunctionInfo> result;
2108 if (maybe_result.ToHandle(&result)) {
2109 compilation_cache->PutScript(source, isolate->native_context(),
2110 parse_info->language_mode(), result);
2111 }
2112 }
2113
2114 streaming_data->Release();
2115 return maybe_result;
2116}
2117
2118Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
2119 FunctionLiteral* literal, Handle<Script> script, Isolate* isolate) {
2120 // Precondition: code has been parsed and scopes have been analyzed.
2121 MaybeHandle<SharedFunctionInfo> maybe_existing;
2122
2123 // Find any previously allocated shared function info for the given literal.
2124 maybe_existing = script->FindSharedFunctionInfo(isolate, literal);
2125
2126 // If we found an existing shared function info, return it.
2127 Handle<SharedFunctionInfo> existing;
2128 if (maybe_existing.ToHandle(&existing)) return existing;
2129
2130 // Allocate a shared function info object which will be compiled lazily.
2131 Handle<SharedFunctionInfo> result =
2132 isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script,
2133 false);
2134 return result;
2135}
2136
2137MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function,
2138 BailoutId osr_offset,
2139 JavaScriptFrame* osr_frame) {
2140 DCHECK(!osr_offset.IsNone());
2141 DCHECK_NOT_NULL(osr_frame);
2142 return GetOptimizedCode(function, ConcurrencyMode::kNotConcurrent, osr_offset,
2143 osr_frame);
2144}
2145
2146bool Compiler::FinalizeOptimizedCompilationJob(OptimizedCompilationJob* job,
2147 Isolate* isolate) {
2148 VMState<COMPILER> state(isolate);
2149 // Take ownership of compilation job. Deleting job also tears down the zone.
2150 std::unique_ptr<OptimizedCompilationJob> job_scope(job);
2151 OptimizedCompilationInfo* compilation_info = job->compilation_info();
2152
2153 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
2154 RuntimeCallTimerScope runtimeTimer(
2155 isolate, RuntimeCallCounterId::kRecompileSynchronous);
2156