v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
compiler.cc
Go to the documentation of this file.
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
6
7#include <algorithm>
8#include <memory>
9#include <optional>
10
11#include "src/api/api-inl.h"
12#include "src/asmjs/asm-js.h"
14#include "src/ast/scopes.h"
15#include "src/base/logging.h"
25#include "src/common/globals.h"
30#include "src/debug/debug.h"
31#include "src/debug/liveedit.h"
38#include "src/flags/flags.h"
40#include "src/handles/handles.h"
43#include "src/heap/heap-inl.h"
51#include "src/logging/log-inl.h"
56#include "src/objects/map.h"
60#include "src/objects/string.h"
62#include "src/parsing/parser.h"
63#include "src/parsing/parsing.h"
68#include "src/utils/ostreams.h"
69#include "src/zone/zone-list-inl.h" // crbug.com/v8/8816
70
71#ifdef V8_ENABLE_MAGLEV
73#include "src/maglev/maglev.h"
74#endif // V8_ENABLE_MAGLEV
75
76namespace v8 {
77namespace internal {
78
79namespace {
80
81constexpr bool IsOSR(BytecodeOffset osr_offset) { return !osr_offset.IsNone(); }
82
83class CompilerTracer : public AllStatic {
84 public:
85 static void TraceStartBaselineCompile(
86 Isolate* isolate, DirectHandle<SharedFunctionInfo> shared) {
87 if (!v8_flags.trace_baseline) return;
88 CodeTracer::Scope scope(isolate->GetCodeTracer());
89 PrintTracePrefix(scope, "compiling method", shared, CodeKind::BASELINE);
90 PrintTraceSuffix(scope);
91 }
92
93 static void TraceStartMaglevCompile(Isolate* isolate,
94 DirectHandle<JSFunction> function,
95 bool osr, ConcurrencyMode mode) {
96 if (!v8_flags.trace_opt) return;
97 CodeTracer::Scope scope(isolate->GetCodeTracer());
98 PrintTracePrefix(scope, "compiling method", function, CodeKind::MAGLEV);
99 if (osr) PrintF(scope.file(), " OSR");
100 PrintF(scope.file(), ", mode: %s", ToString(mode));
101 PrintTraceSuffix(scope);
102 }
103
104 static void TracePrepareJob(Isolate* isolate, OptimizedCompilationInfo* info,
105 ConcurrencyMode mode) {
106 if (!v8_flags.trace_opt || !info->IsOptimizing()) return;
107 CodeTracer::Scope scope(isolate->GetCodeTracer());
108 PrintTracePrefix(scope, "compiling method", info);
109 if (info->is_osr()) PrintF(scope.file(), " OSR");
110 PrintF(scope.file(), ", mode: %s", ToString(mode));
111 PrintTraceSuffix(scope);
112 }
113
114 static void TraceOptimizeOSRStarted(Isolate* isolate,
115 DirectHandle<JSFunction> function,
116 BytecodeOffset osr_offset,
117 ConcurrencyMode mode) {
118 if (!v8_flags.trace_osr) return;
119 CodeTracer::Scope scope(isolate->GetCodeTracer());
120 PrintF(
121 scope.file(),
122 "[OSR - compilation started. function: %s, osr offset: %d, mode: %s]\n",
123 function->DebugNameCStr().get(), osr_offset.ToInt(), ToString(mode));
124 }
125
126 static void TraceOptimizeOSRFinished(Isolate* isolate,
127 DirectHandle<JSFunction> function,
128 BytecodeOffset osr_offset) {
129 if (!v8_flags.trace_osr) return;
130 CodeTracer::Scope scope(isolate->GetCodeTracer());
131 PrintF(scope.file(),
132 "[OSR - compilation finished. function: %s, osr offset: %d]\n",
133 function->DebugNameCStr().get(), osr_offset.ToInt());
134 }
135
136 static void TraceOptimizeOSRAvailable(Isolate* isolate,
137 DirectHandle<JSFunction> function,
138 BytecodeOffset osr_offset,
139 ConcurrencyMode mode) {
140 if (!v8_flags.trace_osr) return;
141 CodeTracer::Scope scope(isolate->GetCodeTracer());
142 PrintF(scope.file(),
143 "[OSR - available (compilation completed or cache hit). function: "
144 "%s, osr offset: %d, mode: %s]\n",
145 function->DebugNameCStr().get(), osr_offset.ToInt(), ToString(mode));
146 }
147
148 static void TraceOptimizeOSRUnavailable(Isolate* isolate,
149 DirectHandle<JSFunction> function,
150 BytecodeOffset osr_offset,
151 ConcurrencyMode mode) {
152 if (!v8_flags.trace_osr) return;
153 CodeTracer::Scope scope(isolate->GetCodeTracer());
154 PrintF(scope.file(),
155 "[OSR - unavailable (failed or in progress). function: %s, osr "
156 "offset: %d, mode: %s]\n",
157 function->DebugNameCStr().get(), osr_offset.ToInt(), ToString(mode));
158 }
159
160 static void TraceFinishTurbofanCompile(Isolate* isolate,
161 OptimizedCompilationInfo* info,
162 double ms_creategraph,
163 double ms_optimize,
164 double ms_codegen) {
165 DCHECK(v8_flags.trace_opt);
166 DCHECK(info->IsOptimizing());
167 CodeTracer::Scope scope(isolate->GetCodeTracer());
168 PrintTracePrefix(scope, "completed compiling", info);
169 if (info->is_osr()) PrintF(scope.file(), " OSR");
170 PrintF(scope.file(), " - took %0.3f, %0.3f, %0.3f ms", ms_creategraph,
171 ms_optimize, ms_codegen);
172 PrintTraceSuffix(scope);
173 }
174
175 static void TraceFinishBaselineCompile(
176 Isolate* isolate, DirectHandle<SharedFunctionInfo> shared,
177 double ms_timetaken) {
178 if (!v8_flags.trace_baseline) return;
179 CodeTracer::Scope scope(isolate->GetCodeTracer());
180 PrintTracePrefix(scope, "completed compiling", shared, CodeKind::BASELINE);
181 PrintF(scope.file(), " - took %0.3f ms", ms_timetaken);
182 PrintTraceSuffix(scope);
183 }
184
185 static void TraceFinishMaglevCompile(Isolate* isolate,
186 DirectHandle<JSFunction> function,
187 bool osr, double ms_prepare,
188 double ms_execute, double ms_finalize) {
189 if (!v8_flags.trace_opt) return;
190 CodeTracer::Scope scope(isolate->GetCodeTracer());
191 PrintTracePrefix(scope, "completed compiling", function, CodeKind::MAGLEV);
192 if (osr) PrintF(scope.file(), " OSR");
193 PrintF(scope.file(), " - took %0.3f, %0.3f, %0.3f ms", ms_prepare,
194 ms_execute, ms_finalize);
195 PrintTraceSuffix(scope);
196 }
197
198 static void TraceAbortedMaglevCompile(Isolate* isolate,
199 DirectHandle<JSFunction> function,
200 BailoutReason bailout_reason) {
201 if (!v8_flags.trace_opt) return;
202 CodeTracer::Scope scope(isolate->GetCodeTracer());
203 PrintTracePrefix(scope, "aborted compiling", function, CodeKind::MAGLEV);
204 PrintF(scope.file(), " because: %s", GetBailoutReason(bailout_reason));
205 PrintTraceSuffix(scope);
206 }
207
208 static void TraceCompletedJob(Isolate* isolate,
209 OptimizedCompilationInfo* info) {
210 if (!v8_flags.trace_opt) return;
211 CodeTracer::Scope scope(isolate->GetCodeTracer());
212 PrintTracePrefix(scope, "completed optimizing", info);
213 if (info->is_osr()) PrintF(scope.file(), " OSR");
214 PrintTraceSuffix(scope);
215 }
216
217 static void TraceAbortedJob(Isolate* isolate, OptimizedCompilationInfo* info,
218 double ms_prepare, double ms_execute,
219 double ms_finalize) {
220 if (!v8_flags.trace_opt) return;
221 CodeTracer::Scope scope(isolate->GetCodeTracer());
222 PrintTracePrefix(scope, "aborted optimizing", info);
223 if (info->is_osr()) PrintF(scope.file(), " OSR");
224 PrintF(scope.file(), " because: %s",
225 GetBailoutReason(info->bailout_reason()));
226 PrintF(scope.file(), " - took %0.3f, %0.3f, %0.3f ms", ms_prepare,
227 ms_execute, ms_finalize);
228 PrintTraceSuffix(scope);
229 }
230
231 static void TraceOptimizedCodeCacheHit(Isolate* isolate,
232 DirectHandle<JSFunction> function,
233 BytecodeOffset osr_offset,
234 CodeKind code_kind) {
235 if (!v8_flags.trace_opt) return;
236 CodeTracer::Scope scope(isolate->GetCodeTracer());
237 PrintTracePrefix(scope, "found optimized code for", function, code_kind);
238 if (IsOSR(osr_offset)) {
239 PrintF(scope.file(), " at OSR bytecode offset %d", osr_offset.ToInt());
240 }
241 PrintTraceSuffix(scope);
242 }
243
244 static void TraceOptimizeForAlwaysOpt(Isolate* isolate,
245 DirectHandle<JSFunction> function,
246 CodeKind code_kind) {
247 if (!v8_flags.trace_opt) return;
248 CodeTracer::Scope scope(isolate->GetCodeTracer());
249 PrintTracePrefix(scope, "optimizing", function, code_kind);
250 PrintF(scope.file(), " because --always-turbofan");
251 PrintTraceSuffix(scope);
252 }
253
254 static void TraceMarkForAlwaysOpt(Isolate* isolate,
255 DirectHandle<JSFunction> function) {
256 if (!v8_flags.trace_opt) return;
257 CodeTracer::Scope scope(isolate->GetCodeTracer());
258 PrintF(scope.file(), "[marking ");
259 ShortPrint(*function, scope.file());
260 PrintF(scope.file(),
261 " for optimized recompilation because --always-turbofan");
262 PrintF(scope.file(), "]\n");
263 }
264
265 private:
266 static void PrintTracePrefix(const CodeTracer::Scope& scope,
267 const char* header,
268 OptimizedCompilationInfo* info) {
269 PrintTracePrefix(scope, header, info->closure(), info->code_kind());
270 }
271
272 static void PrintTracePrefix(const CodeTracer::Scope& scope,
273 const char* header,
274 DirectHandle<JSFunction> function,
275 CodeKind code_kind) {
276 PrintF(scope.file(), "[%s ", header);
277 ShortPrint(*function, scope.file());
278 PrintF(scope.file(), " (target %s)", CodeKindToString(code_kind));
279 }
280
281 static void PrintTracePrefix(const CodeTracer::Scope& scope,
282 const char* header,
283 DirectHandle<SharedFunctionInfo> shared,
284 CodeKind code_kind) {
285 PrintF(scope.file(), "[%s ", header);
286 ShortPrint(*shared, scope.file());
287 PrintF(scope.file(), " (target %s)", CodeKindToString(code_kind));
288 }
289
290 static void PrintTraceSuffix(const CodeTracer::Scope& scope) {
291 PrintF(scope.file(), "]\n");
292 }
293};
294
295} // namespace
296
297// static
303 DirectHandle<AbstractCode> abstract_code,
304 CodeKind kind, double time_taken_ms) {
305 DCHECK_NE(*abstract_code,
306 Cast<AbstractCode>(*BUILTIN_CODE(isolate, CompileLazy)));
307
308 // Log the code generation. If source information is available include
309 // script name and line number. Check explicitly whether logging is
310 // enabled as finding the line number is not free.
311 if (!isolate->IsLoggingCodeCreation()) return;
312
314 Script::GetPositionInfo(script, shared->StartPosition(), &info);
315 int line_num = info.line + 1;
316 int column_num = info.column + 1;
317 DirectHandle<String> script_name(IsString(script->name())
318 ? Cast<String>(script->name())
319 : ReadOnlyRoots(isolate).empty_string(),
320 isolate);
322 V8FileLogger::ToNativeByScript(code_type, *script);
323 PROFILE(isolate, CodeCreateEvent(log_tag, abstract_code, shared, script_name,
324 line_num, column_num));
325 if (!vector.is_null()) {
326 LOG(isolate, FeedbackVectorEvent(*vector, *abstract_code));
327 }
328 if (!v8_flags.log_function_events) return;
329
330 std::string name;
331 switch (kind) {
332 case CodeKind::INTERPRETED_FUNCTION:
333 name = "interpreter";
334 break;
335 case CodeKind::BASELINE:
336 name = "baseline";
337 break;
338 case CodeKind::MAGLEV:
339 name = "maglev";
340 break;
341 case CodeKind::TURBOFAN_JS:
342 name = "turbofan";
343 break;
344 default:
345 UNREACHABLE();
346 }
347 switch (code_type) {
348 case LogEventListener::CodeTag::kEval:
349 name += "-eval";
350 break;
351 case LogEventListener::CodeTag::kScript:
352 case LogEventListener::CodeTag::kFunction:
353 break;
354 default:
355 UNREACHABLE();
356 }
357
358 DirectHandle<String> debug_name =
359 SharedFunctionInfo::DebugName(isolate, shared);
361 LOG(isolate, FunctionEvent(name.c_str(), script->id(), time_taken_ms,
362 shared->StartPosition(), shared->EndPosition(),
363 *debug_name));
364}
365
366namespace {
367
368ScriptOriginOptions OriginOptionsForEval(
369 Tagged<Object> script, ParsingWhileDebugging parsing_while_debugging) {
370 bool is_shared_cross_origin =
371 parsing_while_debugging == ParsingWhileDebugging::kYes;
372 bool is_opaque = false;
373 if (IsScript(script)) {
374 auto script_origin_options = Cast<Script>(script)->origin_options();
375 if (script_origin_options.IsSharedCrossOrigin()) {
376 is_shared_cross_origin = true;
377 }
378 if (script_origin_options.IsOpaque()) {
379 is_opaque = true;
380 }
381 }
382 return ScriptOriginOptions(is_shared_cross_origin, is_opaque);
383}
384
385} // namespace
386
387// ----------------------------------------------------------------------------
388// Implementation of UnoptimizedCompilationJob
389
391 // Delegate to the underlying implementation.
393 base::ScopedTimer t(v8_flags.log_function_events ? &time_taken_to_execute_
394 : nullptr);
396}
397
399 DirectHandle<SharedFunctionInfo> shared_info, Isolate* isolate) {
400 DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
401 DisallowCodeDependencyChange no_dependency_change;
402 DisallowJavascriptExecution no_js(isolate);
403
404 // Delegate to the underlying implementation.
406 base::ScopedTimer t(v8_flags.log_function_events ? &time_taken_to_finalize_
407 : nullptr);
408 return UpdateState(FinalizeJobImpl(shared_info, isolate), State::kSucceeded);
409}
410
412 DirectHandle<SharedFunctionInfo> shared_info, LocalIsolate* isolate) {
413 // Delegate to the underlying implementation.
415 base::ScopedTimer t(v8_flags.log_function_events ? &time_taken_to_finalize_
416 : nullptr);
417 return UpdateState(FinalizeJobImpl(shared_info, isolate), State::kSucceeded);
418}
419
420namespace {
421void LogUnoptimizedCompilation(Isolate* isolate,
424 base::TimeDelta time_taken_to_execute,
425 base::TimeDelta time_taken_to_finalize) {
426 DirectHandle<AbstractCode> abstract_code;
427 if (shared->HasBytecodeArray()) {
428 abstract_code = direct_handle(
429 Cast<AbstractCode>(shared->GetBytecodeArray(isolate)), isolate);
430 } else {
431#if V8_ENABLE_WEBASSEMBLY
432 DCHECK(shared->HasAsmWasmData());
433 abstract_code = Cast<AbstractCode>(BUILTIN_CODE(isolate, InstantiateAsmJs));
434#else
435 UNREACHABLE();
436#endif // V8_ENABLE_WEBASSEMBLY
437 }
438
439 double time_taken_ms = time_taken_to_execute.InMillisecondsF() +
440 time_taken_to_finalize.InMillisecondsF();
441
442 DirectHandle<Script> script(Cast<Script>(shared->script()), isolate);
444 isolate, code_type, script, shared, DirectHandle<FeedbackVector>(),
445 abstract_code, CodeKind::INTERPRETED_FUNCTION, time_taken_ms);
446}
447
448} // namespace
449
450// ----------------------------------------------------------------------------
451// Implementation of OptimizedCompilationJob
452
454 DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
455 DisallowJavascriptExecution no_js(isolate);
456
457 // Delegate to the underlying implementation.
461}
462
464 RuntimeCallStats* stats, LocalIsolate* local_isolate) {
465 DCHECK_IMPLIES(local_isolate && !local_isolate->is_main_thread(),
466 local_isolate->heap()->IsParked());
467 // Delegate to the underlying implementation.
470 return UpdateState(ExecuteJobImpl(stats, local_isolate),
472}
473
475 DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
476 DisallowJavascriptExecution no_js(isolate);
477
478 // Delegate to the underlying implementation.
482}
483
485 Isolate* isolate, DirectHandle<Code> code) {
486 DCHECK(code->is_optimized_code());
487
489 GlobalHandleVector<Map> maps(isolate->heap());
490 PtrComprCageBase cage_base(isolate);
491 int const mode_mask = RelocInfo::EmbeddedObjectModeMask();
492 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
493 DCHECK(RelocInfo::IsEmbeddedObjectMode(it.rinfo()->rmode()));
494 Tagged<HeapObject> target_object = it.rinfo()->target_object(cage_base);
495 if (code->IsWeakObjectInOptimizedCode(target_object)) {
496 if (IsMap(target_object, cage_base)) {
497 maps.Push(Cast<Map>(target_object));
498 }
499 }
500 }
501 return maps;
502}
503
505 Isolate* isolate, DirectHandle<NativeContext> context,
507 isolate->heap()->AddRetainedMaps(context, std::move(maps));
508 code->set_can_have_weak_objects(true);
509}
510
511namespace {
512uint64_t GetNextTraceId() {
513 // Define a global counter for optimized compile trace ids, which
514 // counts in the top 32 bits of a uint64_t. This will be mixed into
515 // the TurbofanCompilationJob `this` pointer, which hopefully will
516 // make the ids unique enough even when the job memory is reused
517 // for future jobs.
518 static std::atomic_uint32_t next_trace_id = 0xfa5701d0;
519 return static_cast<uint64_t>(next_trace_id++) << 32;
520}
521} // namespace
522
524 Isolate* isolate, OptimizedCompilationInfo* compilation_info,
525 State initial_state)
526 : OptimizedCompilationJob("Turbofan", initial_state),
527 isolate_(isolate),
528 compilation_info_(compilation_info),
529 trace_id_(GetNextTraceId() ^ reinterpret_cast<uintptr_t>(this)) {}
530
537
544
546
548 Isolate* isolate) const {
549 DCHECK(compilation_info()->IsOptimizing());
551 if (v8_flags.trace_opt || v8_flags.trace_opt_stats) {
552 double ms_creategraph = time_taken_to_prepare_.InMillisecondsF();
553 double ms_optimize = time_taken_to_execute_.InMillisecondsF();
554 double ms_codegen = time_taken_to_finalize_.InMillisecondsF();
555 if (v8_flags.trace_opt) {
556 CompilerTracer::TraceFinishTurbofanCompile(
557 isolate, compilation_info(), ms_creategraph, ms_optimize, ms_codegen);
558 }
559 if (v8_flags.trace_opt_stats) {
560 static double compilation_time = 0.0;
561 static int compiled_functions = 0;
562 static int code_size = 0;
563
564 compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
565 compiled_functions++;
566 code_size += shared->SourceSize();
567 PrintF(
568 "[turbofan] Compiled: %d functions with %d byte source size in "
569 "%fms.\n",
570 compiled_functions, code_size, compilation_time);
571 }
572 }
573 // Don't record samples from machines without high-resolution timers,
574 // as that can cause serious reporting issues. See the thread at
575 // http://g/chrome-metrics-team/NwwJEyL8odU/discussion for more details.
577
578 int elapsed_microseconds = static_cast<int>(ElapsedTime().InMicroseconds());
579 Counters* const counters = isolate->counters();
580 counters->turbofan_ticks()->AddSample(static_cast<int>(
581 compilation_info()->tick_counter().CurrentTicks() / 1000));
582
583 if (compilation_info()->is_osr()) {
584 counters->turbofan_osr_prepare()->AddSample(
585 static_cast<int>(time_taken_to_prepare_.InMicroseconds()));
586 counters->turbofan_osr_execute()->AddSample(
587 static_cast<int>(time_taken_to_execute_.InMicroseconds()));
588 counters->turbofan_osr_finalize()->AddSample(
589 static_cast<int>(time_taken_to_finalize_.InMicroseconds()));
590 counters->turbofan_osr_total_time()->AddSample(elapsed_microseconds);
591 return;
592 }
593
594 DCHECK(!compilation_info()->is_osr());
595 counters->turbofan_optimize_prepare()->AddSample(
596 static_cast<int>(time_taken_to_prepare_.InMicroseconds()));
597 counters->turbofan_optimize_execute()->AddSample(
598 static_cast<int>(time_taken_to_execute_.InMicroseconds()));
599 counters->turbofan_optimize_finalize()->AddSample(
600 static_cast<int>(time_taken_to_finalize_.InMicroseconds()));
601 counters->turbofan_optimize_total_time()->AddSample(elapsed_microseconds);
602
603 // Compute foreground / background time.
604 base::TimeDelta time_background;
605 base::TimeDelta time_foreground =
607 switch (mode) {
609 time_background += time_taken_to_execute_;
610 counters->turbofan_optimize_concurrent_total_time()->AddSample(
611 elapsed_microseconds);
612 break;
614 counters->turbofan_optimize_non_concurrent_total_time()->AddSample(
615 elapsed_microseconds);
616 time_foreground += time_taken_to_execute_;
617 break;
618 }
619 counters->turbofan_optimize_total_background()->AddSample(
620 static_cast<int>(time_background.InMicroseconds()));
621 counters->turbofan_optimize_total_foreground()->AddSample(
622 static_cast<int>(time_foreground.InMicroseconds()));
623
624 if (v8_flags.profile_guided_optimization &&
625 shared->cached_tiering_decision() ==
627 shared->set_cached_tiering_decision(CachedTieringDecision::kEarlyTurbofan);
628 }
629}
630
632 LogEventListener::CodeTag code_type, Isolate* isolate) const {
633 DirectHandle<AbstractCode> abstract_code =
635
636 double time_taken_ms = time_taken_to_prepare_.InMillisecondsF() +
639
641 Cast<Script>(compilation_info()->shared_info()->script()), isolate);
642 DirectHandle<FeedbackVector> feedback_vector(
643 compilation_info()->closure()->feedback_vector(), isolate);
645 isolate, code_type, script, compilation_info()->shared_info(),
646 feedback_vector, abstract_code, compilation_info()->code_kind(),
647 time_taken_ms);
648}
649
651 // Xor together the this pointer and the optimization id, to try to make the
652 // id more unique on platforms where just the `this` pointer is likely to be
653 // reused.
654 return trace_id_;
655}
656
657// ----------------------------------------------------------------------------
658// Local helper methods that make up the compilation pipeline.
659
660namespace {
661
662#if V8_ENABLE_WEBASSEMBLY
663bool UseAsmWasm(FunctionLiteral* literal, bool asm_wasm_broken) {
664 // Check whether asm.js validation is enabled.
665 if (!v8_flags.validate_asm) return false;
666
667 // Modules that have validated successfully, but were subsequently broken by
668 // invalid module instantiation attempts are off limit forever.
669 if (asm_wasm_broken) return false;
670
671 // In stress mode we want to run the validator on everything.
672 if (v8_flags.stress_validate_asm) return true;
673
674 // In general, we respect the "use asm" directive.
675 return literal->scope()->IsAsmModule();
676}
677#endif
678
679} // namespace
680
682 Isolate* isolate, DirectHandle<SharedFunctionInfo> shared_info,
684 DCHECK(isolate->interpreted_frames_native_stack());
685 if (!IsBytecodeArray(shared_info->GetTrustedData(isolate))) {
686 DCHECK(!shared_info->HasInterpreterData(isolate));
687 return;
688 }
689 DirectHandle<BytecodeArray> bytecode_array(
690 shared_info->GetBytecodeArray(isolate), isolate);
691
692 DirectHandle<Code> code =
694
695 DirectHandle<InterpreterData> interpreter_data =
696 isolate->factory()->NewInterpreterData(bytecode_array, code);
697
698 if (shared_info->HasBaselineCode()) {
699 shared_info->baseline_code(kAcquireLoad)
700 ->set_bytecode_or_interpreter_data(*interpreter_data);
701 } else {
702 // IsBytecodeArray
703 shared_info->set_interpreter_data(isolate, *interpreter_data);
704 }
705
706 DirectHandle<Script> script(Cast<Script>(shared_info->script()), isolate);
709 Script::GetPositionInfo(script, shared_info->StartPosition(), &info);
710 int line_num = info.line + 1;
711 int column_num = info.column + 1;
712 DirectHandle<String> script_name(IsString(script->name())
713 ? Cast<String>(script->name())
714 : ReadOnlyRoots(isolate).empty_string(),
715 isolate);
716 PROFILE(isolate, CodeCreateEvent(log_tag, abstract_code, shared_info,
717 script_name, line_num, column_num));
718}
719
720namespace {
721
722template <typename IsolateT>
723void InstallUnoptimizedCode(UnoptimizedCompilationInfo* compilation_info,
725 IsolateT* isolate) {
726 if (compilation_info->has_bytecode_array()) {
727 DCHECK(!shared_info->HasBytecodeArray()); // Only compiled once.
728 DCHECK(!compilation_info->has_asm_wasm_data());
729 DCHECK(!shared_info->HasFeedbackMetadata());
730
731#if V8_ENABLE_WEBASSEMBLY
732 // If the function failed asm-wasm compilation, mark asm_wasm as broken
733 // to ensure we don't try to compile as asm-wasm.
734 if (compilation_info->literal()->scope()->IsAsmModule()) {
735 shared_info->set_is_asm_wasm_broken(true);
736 }
737#endif // V8_ENABLE_WEBASSEMBLY
738
739 DirectHandle<FeedbackMetadata> feedback_metadata = FeedbackMetadata::New(
740 isolate, compilation_info->feedback_vector_spec());
741 shared_info->set_feedback_metadata(*feedback_metadata, kReleaseStore);
742
743 shared_info->set_age(0);
744 shared_info->set_bytecode_array(*compilation_info->bytecode_array());
745 } else {
746#if V8_ENABLE_WEBASSEMBLY
747 DCHECK(compilation_info->has_asm_wasm_data());
748 // We should only have asm/wasm data when finalizing on the main thread.
749 DCHECK((std::is_same<IsolateT, Isolate>::value));
750 shared_info->set_asm_wasm_data(*compilation_info->asm_wasm_data());
751 shared_info->set_feedback_metadata(
752 ReadOnlyRoots(isolate).empty_feedback_metadata(), kReleaseStore);
753#else
754 UNREACHABLE();
755#endif // V8_ENABLE_WEBASSEMBLY
756 }
757}
758
759template <typename IsolateT>
760void EnsureInfosArrayOnScript(DirectHandle<Script> script,
761 ParseInfo* parse_info, IsolateT* isolate) {
762 DCHECK(parse_info->flags().is_toplevel());
763 if (script->infos()->length() > 0) {
764 DCHECK_EQ(script->infos()->length(), parse_info->max_info_id() + 1);
765 return;
766 }
767 DirectHandle<WeakFixedArray> infos(isolate->factory()->NewWeakFixedArray(
768 parse_info->max_info_id() + 1, AllocationType::kOld));
769 script->set_infos(*infos);
770}
771
772void UpdateSharedFunctionFlagsAfterCompilation(FunctionLiteral* literal) {
774 DCHECK_EQ(shared_info->language_mode(), literal->language_mode());
775
776 // These fields are all initialised in ParseInfo from the SharedFunctionInfo,
777 // and then set back on the literal after parse. Hence, they should already
778 // match.
779 DCHECK_EQ(shared_info->requires_instance_members_initializer(),
781 DCHECK_EQ(shared_info->class_scope_has_private_brand(),
783 DCHECK_EQ(shared_info->has_static_private_methods_or_accessors(),
785
786 shared_info->set_has_duplicate_parameters(
788 shared_info->UpdateAndFinalizeExpectedNofPropertiesFromEstimate(literal);
789
790 shared_info->SetScopeInfo(*literal->scope()->scope_info());
791}
792
793// Finalize a single compilation job. This function can return
794// RETRY_ON_MAIN_THREAD if the job cannot be finalized off-thread, in which case
795// it should be safe to call it again on the main thread with the same job.
796template <typename IsolateT>
797CompilationJob::Status FinalizeSingleUnoptimizedCompilationJob(
798 UnoptimizedCompilationJob* job, Handle<SharedFunctionInfo> shared_info,
799 IsolateT* isolate,
801 finalize_unoptimized_compilation_data_list) {
802 UnoptimizedCompilationInfo* compilation_info = job->compilation_info();
803
804 CompilationJob::Status status = job->FinalizeJob(shared_info, isolate);
805 if (status == CompilationJob::SUCCEEDED) {
806 InstallUnoptimizedCode(compilation_info, shared_info, isolate);
807
808 MaybeHandle<CoverageInfo> coverage_info;
809 if (compilation_info->has_coverage_info()) {
810 MutexGuardIfOffThread<IsolateT> mutex_guard(
811 isolate->shared_function_info_access(), isolate);
812 if (!shared_info->HasCoverageInfo(
813 isolate->GetMainThreadIsolateUnsafe())) {
814 coverage_info = compilation_info->coverage_info();
815 }
816 }
817
818 finalize_unoptimized_compilation_data_list->emplace_back(
819 isolate, shared_info, coverage_info, job->time_taken_to_execute(),
820 job->time_taken_to_finalize());
821 }
823 (std::is_same<IsolateT, LocalIsolate>::value));
824 return status;
825}
826
827std::unique_ptr<UnoptimizedCompilationJob>
828ExecuteSingleUnoptimizedCompilationJob(
829 ParseInfo* parse_info, FunctionLiteral* literal, Handle<Script> script,
830 AccountingAllocator* allocator,
831 std::vector<FunctionLiteral*>* eager_inner_literals,
832 LocalIsolate* local_isolate) {
833#if V8_ENABLE_WEBASSEMBLY
834 if (UseAsmWasm(literal, parse_info->flags().is_asm_wasm_broken())) {
835 std::unique_ptr<UnoptimizedCompilationJob> asm_job(
836 AsmJs::NewCompilationJob(parse_info, literal, allocator));
837 if (asm_job->ExecuteJob() == CompilationJob::SUCCEEDED) {
838 return asm_job;
839 }
840 // asm.js validation failed, fall through to standard unoptimized compile.
841 // Note: we rely on the fact that AsmJs jobs have done all validation in the
842 // PrepareJob and ExecuteJob phases and can't fail in FinalizeJob with
843 // with a validation error or another error that could be solve by falling
844 // through to standard unoptimized compile.
845 }
846#endif
847 std::unique_ptr<UnoptimizedCompilationJob> job(
849 parse_info, literal, script, allocator, eager_inner_literals,
850 local_isolate));
851
852 if (job->ExecuteJob() != CompilationJob::SUCCEEDED) {
853 // Compilation failed, return null.
854 return std::unique_ptr<UnoptimizedCompilationJob>();
855 }
856
857 return job;
858}
859
860template <typename IsolateT>
861bool IterativelyExecuteAndFinalizeUnoptimizedCompilationJobs(
862 IsolateT* isolate, Handle<Script> script, ParseInfo* parse_info,
863 AccountingAllocator* allocator, IsCompiledScope* is_compiled_scope,
865 finalize_unoptimized_compilation_data_list,
867 jobs_to_retry_finalization_on_main_thread) {
868 DeclarationScope::AllocateScopeInfos(parse_info, script, isolate);
869
870 std::vector<FunctionLiteral*> functions_to_compile;
871 functions_to_compile.push_back(parse_info->literal());
872
873 bool compilation_succeeded = true;
874 while (!functions_to_compile.empty()) {
875 FunctionLiteral* literal = functions_to_compile.back();
876 functions_to_compile.pop_back();
878 // It's possible that compilation of an outer function overflowed the stack,
879 // so a literal we'd like to compile won't have its SFI yet. Skip compiling
880 // the inner function in that case.
881 if (shared_info.is_null()) continue;
882 if (shared_info->is_compiled()) continue;
883
884 std::unique_ptr<UnoptimizedCompilationJob> job =
885 ExecuteSingleUnoptimizedCompilationJob(parse_info, literal, script,
886 allocator, &functions_to_compile,
887 isolate->AsLocalIsolate());
888
889 if (!job) {
890 // Compilation failed presumably because of stack overflow, make sure
891 // the shared function info contains uncompiled data for the next
892 // compilation attempts.
893 if (!shared_info->HasUncompiledData()) {
895 }
896 compilation_succeeded = false;
897 // Proceed finalizing other functions in case they don't have uncompiled
898 // data.
899 continue;
900 }
901
902 UpdateSharedFunctionFlagsAfterCompilation(literal);
903
904 auto finalization_status = FinalizeSingleUnoptimizedCompilationJob(
905 job.get(), shared_info, isolate,
906 finalize_unoptimized_compilation_data_list);
907
908 switch (finalization_status) {
910 if (literal == parse_info->literal()) {
911 // Ensure that the top level function is retained.
912 *is_compiled_scope = shared_info->is_compiled_scope(isolate);
913 DCHECK(is_compiled_scope->is_compiled());
914 }
915 break;
916
918 compilation_succeeded = false;
919 // Proceed finalizing other functions in case they don't have uncompiled
920 // data.
921 continue;
922
924 // This should not happen on the main thread.
925 DCHECK((!std::is_same<IsolateT, Isolate>::value));
926 DCHECK_NOT_NULL(jobs_to_retry_finalization_on_main_thread);
927
928 // Clear the literal and ParseInfo to prevent further attempts to
929 // access them.
930 job->compilation_info()->ClearLiteral();
931 job->ClearParseInfo();
932 jobs_to_retry_finalization_on_main_thread->emplace_back(
933 isolate, shared_info, std::move(job));
934 break;
935 }
936 }
937
938 // Report any warnings generated during compilation.
939 if (parse_info->pending_error_handler()->has_pending_warnings()) {
940 parse_info->pending_error_handler()->PrepareWarnings(isolate);
941 }
942
943 return compilation_succeeded;
944}
945
946bool FinalizeDeferredUnoptimizedCompilationJobs(
947 Isolate* isolate, DirectHandle<Script> script,
948 DeferredFinalizationJobDataList* deferred_jobs,
949 PendingCompilationErrorHandler* pending_error_handler,
951 finalize_unoptimized_compilation_data_list) {
952 DCHECK(AllowCompilation::IsAllowed(isolate));
953
954 if (deferred_jobs->empty()) return true;
955
956 // TODO(rmcilroy): Clear native context in debug once AsmJS generates doesn't
957 // rely on accessing native context during finalization.
958
959 // Finalize the deferred compilation jobs.
960 for (auto&& job : *deferred_jobs) {
961 Handle<SharedFunctionInfo> shared_info = job.function_handle();
962 if (FinalizeSingleUnoptimizedCompilationJob(
963 job.job(), shared_info, isolate,
964 finalize_unoptimized_compilation_data_list) !=
966 return false;
967 }
968 }
969
970 // Report any warnings generated during deferred finalization.
971 if (pending_error_handler->has_pending_warnings()) {
972 pending_error_handler->PrepareWarnings(isolate);
973 }
974
975 return true;
976}
977
978// A wrapper to access the optimized code cache slots on the feedback vector.
979class OptimizedCodeCache : public AllStatic {
980 public:
981 static V8_WARN_UNUSED_RESULT MaybeHandle<Code> Get(
982 Isolate* isolate, DirectHandle<JSFunction> function,
983 BytecodeOffset osr_offset, CodeKind code_kind) {
984 DCHECK_IMPLIES(V8_ENABLE_LEAPTIERING_BOOL, IsOSR(osr_offset));
985 if (!CodeKindIsStoredInOptimizedCodeCache(code_kind)) return {};
986 if (!function->has_feedback_vector()) return {};
987
989 Tagged<SharedFunctionInfo> shared = function->shared();
990 RCS_SCOPE(isolate, RuntimeCallCounterId::kCompileGetFromOptimizedCodeMap);
991
993 Tagged<FeedbackVector> feedback_vector = function->feedback_vector();
994 if (IsOSR(osr_offset)) {
995 Handle<BytecodeArray> bytecode(shared->GetBytecodeArray(isolate),
996 isolate);
997 interpreter::BytecodeArrayIterator it(bytecode, osr_offset.ToInt());
998 // Bytecode may be different, so make sure we're at a valid OSR entry.
999 SBXCHECK(it.CurrentBytecodeIsValidOSREntry());
1000 std::optional<Tagged<Code>> maybe_code =
1001 feedback_vector->GetOptimizedOsrCode(isolate, it.GetSlotOperand(2));
1002 if (maybe_code.has_value()) code = maybe_code.value();
1003 } else {
1004#ifdef V8_ENABLE_LEAPTIERING
1005 UNREACHABLE();
1006#else
1007 feedback_vector->EvictOptimizedCodeMarkedForDeoptimization(
1008 isolate, shared, "OptimizedCodeCache::Get");
1009 code = feedback_vector->optimized_code(isolate);
1010#endif // V8_ENABLE_LEAPTIERING
1011 }
1012
1013 // Normal tierup should never request a code-kind we already have. In case
1014 // of OSR it can happen that we OSR from ignition to turbofan. This is
1015 // explicitly allowed here by reusing any larger-kinded than requested
1016 // code.
1017 DCHECK_IMPLIES(!code.is_null() && code->kind() > code_kind,
1018 IsOSR(osr_offset));
1019 if (code.is_null() || code->kind() < code_kind) return {};
1020
1021 DCHECK(!code->marked_for_deoptimization());
1022 DCHECK(shared->is_compiled());
1024 DCHECK_IMPLIES(IsOSR(osr_offset), CodeKindCanOSR(code->kind()));
1025
1026 CompilerTracer::TraceOptimizedCodeCacheHit(isolate, function, osr_offset,
1027 code_kind);
1028 return handle(code, isolate);
1029 }
1030
1031 static void Insert(Isolate* isolate, Tagged<JSFunction> function,
1032 BytecodeOffset osr_offset, Tagged<Code> code,
1033 bool is_function_context_specializing) {
1034 DCHECK_IMPLIES(V8_ENABLE_LEAPTIERING_BOOL, IsOSR(osr_offset));
1035 const CodeKind kind = code->kind();
1037
1038 Tagged<FeedbackVector> feedback_vector = function->feedback_vector();
1039
1040 if (IsOSR(osr_offset)) {
1042 DCHECK(!is_function_context_specializing);
1043 Tagged<SharedFunctionInfo> shared = function->shared();
1044 Handle<BytecodeArray> bytecode(shared->GetBytecodeArray(isolate),
1045 isolate);
1046 interpreter::BytecodeArrayIterator it(bytecode, osr_offset.ToInt());
1047 // Bytecode may be different, so make sure we're at a valid OSR entry.
1048 SBXCHECK(it.CurrentBytecodeIsValidOSREntry());
1049 feedback_vector->SetOptimizedOsrCode(isolate, it.GetSlotOperand(2), code);
1050 return;
1051 }
1052
1053#ifdef V8_ENABLE_LEAPTIERING
1054 UNREACHABLE();
1055#else
1056 DCHECK(!IsOSR(osr_offset));
1057
1058 if (is_function_context_specializing) {
1059 // Function context specialization folds-in the function context, so no
1060 // sharing can occur. Make sure the optimized code cache is cleared.
1061 // Only do so if the specialized code's kind matches the cached code kind.
1062 if (feedback_vector->has_optimized_code() &&
1063 feedback_vector->optimized_code(isolate)->kind() == code->kind()) {
1064 feedback_vector->ClearOptimizedCode();
1065 }
1066 return;
1067 }
1068
1069 function->shared()->set_function_context_independent_compiled(true);
1070 feedback_vector->SetOptimizedCode(isolate, code);
1071#endif // V8_ENABLE_LEAPTIERING
1072 }
1073};
1074
1075// Runs PrepareJob in the proper compilation scopes. Handles will be allocated
1076// in a persistent handle scope that is detached and handed off to the
1077// {compilation_info} after PrepareJob.
1078bool PrepareJobWithHandleScope(OptimizedCompilationJob* job, Isolate* isolate,
1079 OptimizedCompilationInfo* compilation_info,
1080 ConcurrencyMode mode) {
1081 CompilationHandleScope compilation(isolate, compilation_info);
1082 CompilerTracer::TracePrepareJob(isolate, compilation_info, mode);
1083 compilation_info->ReopenAndCanonicalizeHandlesInNewScope(isolate);
1084 return job->PrepareJob(isolate) == CompilationJob::SUCCEEDED;
1085}
1086
1087bool CompileTurbofan_NotConcurrent(Isolate* isolate,
1088 TurbofanCompilationJob* job) {
1089 OptimizedCompilationInfo* const compilation_info = job->compilation_info();
1090 DCHECK_EQ(compilation_info->code_kind(), CodeKind::TURBOFAN_JS);
1091
1092 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
1093 RCS_SCOPE(isolate, RuntimeCallCounterId::kOptimizeNonConcurrent);
1095 "V8.OptimizeNonConcurrent");
1096
1097 if (!PrepareJobWithHandleScope(job, isolate, compilation_info,
1099 CompilerTracer::TraceAbortedJob(isolate, compilation_info,
1100 job->prepare_in_ms(), job->execute_in_ms(),
1101 job->finalize_in_ms());
1102 return false;
1103 }
1104
1105 if (job->ExecuteJob(isolate->counters()->runtime_call_stats(),
1106 isolate->main_thread_local_isolate())) {
1107 CompilerTracer::TraceAbortedJob(isolate, compilation_info,
1108 job->prepare_in_ms(), job->execute_in_ms(),
1109 job->finalize_in_ms());
1110 return false;
1111 }
1112
1113 if (job->FinalizeJob(isolate) != CompilationJob::SUCCEEDED) {
1114 CompilerTracer::TraceAbortedJob(isolate, compilation_info,
1115 job->prepare_in_ms(), job->execute_in_ms(),
1116 job->finalize_in_ms());
1117 return false;
1118 }
1119
1120 // Success!
1121 job->RecordCompilationStats(ConcurrencyMode::kSynchronous, isolate);
1122 DCHECK(!isolate->has_exception());
1123 if (!V8_ENABLE_LEAPTIERING_BOOL || job->compilation_info()->is_osr()) {
1124 OptimizedCodeCache::Insert(
1125 isolate, *compilation_info->closure(), compilation_info->osr_offset(),
1126 *compilation_info->code(),
1127 compilation_info->function_context_specializing());
1128 }
1129 job->RecordFunctionCompilation(LogEventListener::CodeTag::kFunction, isolate);
1130 return true;
1131}
1132
1133bool CompileTurbofan_Concurrent(Isolate* isolate,
1134 std::unique_ptr<TurbofanCompilationJob> job) {
1135 OptimizedCompilationInfo* const compilation_info = job->compilation_info();
1136 DCHECK_EQ(compilation_info->code_kind(), CodeKind::TURBOFAN_JS);
1137 DirectHandle<JSFunction> function = compilation_info->closure();
1138
1139 if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) {
1140 if (v8_flags.trace_concurrent_recompilation) {
1141 PrintF(" ** Compilation queue full, will retry optimizing ");
1142 ShortPrint(*function);
1143 PrintF(" later.\n");
1144 }
1145 return false;
1146 }
1147
1148 if (isolate->heap()->HighMemoryPressure()) {
1149 if (v8_flags.trace_concurrent_recompilation) {
1150 PrintF(" ** High memory pressure, will retry optimizing ");
1151 ShortPrint(*function);
1152 PrintF(" later.\n");
1153 }
1154 return false;
1155 }
1156
1157 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
1158 RCS_SCOPE(isolate, RuntimeCallCounterId::kOptimizeConcurrentPrepare);
1160 "V8.OptimizeConcurrentPrepare", job->trace_id(),
1162
1163 if (!PrepareJobWithHandleScope(job.get(), isolate, compilation_info,
1165 return false;
1166 }
1167
1168 if (V8_LIKELY(!compilation_info->discard_result_for_testing())) {
1169 function->SetTieringInProgress(true, compilation_info->osr_offset());
1170 }
1171
1172 // The background recompile will own this job.
1173 if (!isolate->optimizing_compile_dispatcher()->TryQueueForOptimization(job)) {
1174 function->SetTieringInProgress(false, compilation_info->osr_offset());
1175
1176 if (v8_flags.trace_concurrent_recompilation) {
1177 PrintF(" ** Compilation queue full, will retry optimizing ");
1178 ShortPrint(*function);
1179 PrintF(" later.\n");
1180 }
1181 return false;
1182 }
1183
1184 if (v8_flags.trace_concurrent_recompilation) {
1185 PrintF(" ** Queued ");
1186 ShortPrint(*function);
1187 PrintF(" for concurrent optimization.\n");
1188 }
1189
1190 DCHECK(compilation_info->shared_info()->HasBytecodeArray());
1191 return true;
1192}
1193
1194enum class CompileResultBehavior {
1195 // Default behavior, i.e. install the result, insert into caches, etc.
1196 kDefault,
1197 // Used only for stress testing. The compilation result should be discarded.
1198 kDiscardForTesting,
1199};
1200
1201bool ShouldOptimize(CodeKind code_kind,
1202 DirectHandle<SharedFunctionInfo> shared) {
1204 switch (code_kind) {
1205 case CodeKind::TURBOFAN_JS:
1206 return v8_flags.turbofan && shared->PassesFilter(v8_flags.turbo_filter);
1207 case CodeKind::MAGLEV:
1208 return maglev::IsMaglevEnabled() &&
1209 shared->PassesFilter(v8_flags.maglev_filter);
1210 default:
1211 UNREACHABLE();
1212 }
1213}
1214
1215MaybeHandle<Code> CompileTurbofan(Isolate* isolate, Handle<JSFunction> function,
1216 DirectHandle<SharedFunctionInfo> shared,
1217 ConcurrencyMode mode,
1218 BytecodeOffset osr_offset,
1219 CompileResultBehavior result_behavior) {
1220 VMState<COMPILER> state(isolate);
1221 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
1222 RCS_SCOPE(isolate, RuntimeCallCounterId::kOptimizeCode);
1223 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.OptimizeCode");
1224
1225 DCHECK(!isolate->has_exception());
1226 PostponeInterruptsScope postpone(isolate);
1227 const compiler::IsScriptAvailable has_script =
1228 IsScript(shared->script()) ? compiler::IsScriptAvailable::kYes
1230 // BUG(5946): This DCHECK is necessary to make certain that we won't
1231 // tolerate the lack of a script without bytecode.
1233 shared->HasBytecodeArray());
1234 std::unique_ptr<TurbofanCompilationJob> job(
1235 compiler::NewCompilationJob(isolate, function, has_script, osr_offset));
1236
1237 if (result_behavior == CompileResultBehavior::kDiscardForTesting) {
1238 job->compilation_info()->set_discard_result_for_testing();
1239 }
1240
1241 if (IsOSR(osr_offset)) {
1242 isolate->CountUsage(v8::Isolate::kTurboFanOsrCompileStarted);
1243 }
1244
1245 // Prepare the job and launch concurrent compilation, or compile now.
1246 if (IsConcurrent(mode)) {
1247 if (CompileTurbofan_Concurrent(isolate, std::move(job))) return {};
1248 } else {
1249 DCHECK(IsSynchronous(mode));
1250 if (CompileTurbofan_NotConcurrent(isolate, job.get())) {
1251 return job->compilation_info()->code();
1252 }
1253 }
1254
1255 if (isolate->has_exception()) isolate->clear_exception();
1256 return {};
1257}
1258
1259#ifdef V8_ENABLE_MAGLEV
1260// TODO(v8:7700): Record maglev compilations better.
1261void RecordMaglevFunctionCompilation(Isolate* isolate,
1262 DirectHandle<JSFunction> function,
1263 DirectHandle<AbstractCode> code) {
1264 PtrComprCageBase cage_base(isolate);
1265 DirectHandle<SharedFunctionInfo> shared(function->shared(cage_base), isolate);
1266 DirectHandle<Script> script(Cast<Script>(shared->script(cage_base)), isolate);
1267 DirectHandle<FeedbackVector> feedback_vector(
1268 function->feedback_vector(cage_base), isolate);
1269
1270 // Optimistic estimate.
1271 double time_taken_ms = 0;
1272
1274 isolate, LogEventListener::CodeTag::kFunction, script, shared,
1275 feedback_vector, code, code->kind(cage_base), time_taken_ms);
1276}
1277#endif // V8_ENABLE_MAGLEV
1278
1279MaybeHandle<Code> CompileMaglev(Isolate* isolate, Handle<JSFunction> function,
1280 ConcurrencyMode mode, BytecodeOffset osr_offset,
1281 CompileResultBehavior result_behavior) {
1282#ifdef V8_ENABLE_MAGLEV
1284 CHECK(result_behavior == CompileResultBehavior::kDefault);
1285
1286 // TODO(v8:7700): Tracing, see CompileTurbofan.
1287
1288 DCHECK(!isolate->has_exception());
1289 PostponeInterruptsScope postpone(isolate);
1290
1291 // TODO(v8:7700): See everything in CompileTurbofan_Concurrent.
1292 // - Tracing,
1293 // - timers,
1294 // - aborts on memory pressure,
1295 // ...
1296
1297 // Prepare the job.
1298 auto job = maglev::MaglevCompilationJob::New(isolate, function, osr_offset);
1299
1300 if (IsConcurrent(mode) &&
1301 !isolate->maglev_concurrent_dispatcher()->is_enabled()) {
1303 }
1304
1305 {
1307 TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1308 IsSynchronous(mode) ? "V8.MaglevPrepare" : "V8.MaglevConcurrentPrepare",
1309 job->trace_id(), TRACE_EVENT_FLAG_FLOW_OUT);
1310 CompilerTracer::TraceStartMaglevCompile(isolate, function, job->is_osr(),
1311 mode);
1312 CompilationJob::Status status = job->PrepareJob(isolate);
1313 CHECK_EQ(status, CompilationJob::SUCCEEDED); // TODO(v8:7700): Use status.
1314 }
1315
1316 if (IsSynchronous(mode)) {
1317 CompilationJob::Status status =
1318 job->ExecuteJob(isolate->counters()->runtime_call_stats(),
1319 isolate->main_thread_local_isolate());
1320 if (status == CompilationJob::FAILED) {
1321 return {};
1322 }
1324
1325 Compiler::FinalizeMaglevCompilationJob(job.get(), isolate);
1326
1327 return job->code();
1328 }
1329
1330 DCHECK(IsConcurrent(mode));
1331
1332 // Enqueue it.
1333 isolate->maglev_concurrent_dispatcher()->EnqueueJob(std::move(job));
1334
1335 // Remember that the function is currently being processed.
1336 function->SetTieringInProgress(true, osr_offset);
1337 function->SetInterruptBudget(isolate, BudgetModification::kRaise,
1338 CodeKind::MAGLEV);
1339
1340 return {};
1341#else // V8_ENABLE_MAGLEV
1342 UNREACHABLE();
1343#endif // V8_ENABLE_MAGLEV
1344}
1345
1346MaybeHandle<Code> GetOrCompileOptimized(
1347 Isolate* isolate, DirectHandle<JSFunction> function, ConcurrencyMode mode,
1348 CodeKind code_kind, BytecodeOffset osr_offset = BytecodeOffset::None(),
1349 CompileResultBehavior result_behavior = CompileResultBehavior::kDefault) {
1350 if (IsOSR(osr_offset)) {
1351 function->TraceOptimizationStatus(
1352 "^%s (osr %i)", CodeKindToString(code_kind), osr_offset.ToInt());
1353 } else {
1354 function->TraceOptimizationStatus("^%s", CodeKindToString(code_kind));
1355 }
1357
1358 DirectHandle<SharedFunctionInfo> shared(function->shared(), isolate);
1359
1360 // Reset the OSR urgency. If we enter a function OSR should not be triggered.
1361 // If we are in fact in a loop we should avoid triggering this compilation
1362 // request on every iteration and thereby skipping other interrupts.
1363 function->feedback_vector()->reset_osr_urgency();
1364
1365 // Clear the optimization marker on the function so that we don't try to
1366 // re-optimize.
1367 if (!IsOSR(osr_offset)) {
1368 function->ResetTieringRequests();
1369 // Always reset the OSR urgency to ensure we reset it on function entry.
1370 int invocation_count =
1371 function->feedback_vector()->invocation_count(kRelaxedLoad);
1372 if (!(V8_UNLIKELY(v8_flags.testing_d8_test_runner ||
1373 v8_flags.allow_natives_syntax) &&
1375 *function)) &&
1376 invocation_count < v8_flags.minimum_invocations_before_optimization) {
1377 function->feedback_vector()->set_invocation_count(invocation_count + 1,
1379 return {};
1380 }
1381 }
1382
1383 // TODO(v8:7700): Distinguish between Maglev and Turbofan.
1384 if (shared->optimization_disabled() &&
1385 shared->disabled_optimization_reason() == BailoutReason::kNeverOptimize) {
1386 return {};
1387 }
1388
1389 // Do not optimize when debugger needs to hook into every call.
1390 if (isolate->debug()->needs_check_on_function_call()) {
1391 return {};
1392 }
1393
1394 // Do not optimize if we need to be able to set break points.
1395 if (shared->HasBreakInfo(isolate)) return {};
1396
1397 // Do not optimize if optimization is disabled or function doesn't pass
1398 // turbo_filter.
1399 if (!ShouldOptimize(code_kind, shared)) return {};
1400
1401 if (!V8_ENABLE_LEAPTIERING_BOOL || IsOSR(osr_offset)) {
1402 Handle<Code> cached_code;
1403 if (OptimizedCodeCache::Get(isolate, function, osr_offset, code_kind)
1404 .ToHandle(&cached_code)) {
1405 DCHECK_IMPLIES(!IsOSR(osr_offset), cached_code->kind() <= code_kind);
1406 return cached_code;
1407 }
1408
1409 if (IsOSR(osr_offset)) {
1410 // One OSR job per function at a time.
1411 if (function->osr_tiering_in_progress()) return {};
1412 }
1413 }
1414
1415 DCHECK(shared->is_compiled());
1416
1417 if (code_kind == CodeKind::TURBOFAN_JS) {
1418 return CompileTurbofan(isolate, indirect_handle(function, isolate), shared,
1419 mode, osr_offset, result_behavior);
1420 } else {
1421 DCHECK_EQ(code_kind, CodeKind::MAGLEV);
1422 return CompileMaglev(isolate, indirect_handle(function, isolate), mode,
1423 osr_offset, result_behavior);
1424 }
1425}
1426
1427// When --stress-concurrent-inlining is enabled, spawn concurrent jobs in
1428// addition to non-concurrent compiles to increase coverage in mjsunit tests
1429// (where most interesting compiles are non-concurrent). The result of the
1430// compilation is thrown out.
1431void SpawnDuplicateConcurrentJobForStressTesting(
1432 Isolate* isolate, DirectHandle<JSFunction> function, ConcurrencyMode mode,
1433 CodeKind code_kind) {
1434 // TODO(v8:7700): Support Maglev.
1435 if (code_kind == CodeKind::MAGLEV) return;
1436
1437 if (function->ActiveTierIsTurbofan(isolate)) return;
1438
1439 DCHECK(v8_flags.stress_concurrent_inlining &&
1440 isolate->concurrent_recompilation_enabled() && IsSynchronous(mode) &&
1441 isolate->node_observer() == nullptr);
1442 CompileResultBehavior result_behavior =
1443 v8_flags.stress_concurrent_inlining_attach_code
1444 ? CompileResultBehavior::kDefault
1445 : CompileResultBehavior::kDiscardForTesting;
1446 USE(GetOrCompileOptimized(isolate, function, ConcurrencyMode::kConcurrent,
1447 code_kind, BytecodeOffset::None(),
1448 result_behavior));
1449}
1450
1451bool FailAndClearException(Isolate* isolate) {
1452 isolate->clear_internal_exception();
1453 return false;
1454}
1455
1456template <typename IsolateT>
1457bool PrepareException(IsolateT* isolate, ParseInfo* parse_info) {
1458 if (parse_info->pending_error_handler()->has_pending_error()) {
1459 parse_info->pending_error_handler()->PrepareErrors(
1460 isolate, parse_info->ast_value_factory());
1461 }
1462 return false;
1463}
1464
1465bool FailWithPreparedException(
1466 Isolate* isolate, Handle<Script> script,
1467 const PendingCompilationErrorHandler* pending_error_handler,
1469 if (flag == Compiler::CLEAR_EXCEPTION) {
1470 return FailAndClearException(isolate);
1471 }
1472
1473 if (!isolate->has_exception()) {
1474 if (pending_error_handler->has_pending_error()) {
1475 pending_error_handler->ReportErrors(isolate, script);
1476 } else {
1477 isolate->StackOverflow();
1478 }
1479 }
1480 return false;
1481}
1482
1483bool FailWithException(Isolate* isolate, Handle<Script> script,
1484 ParseInfo* parse_info,
1486 PrepareException(isolate, parse_info);
1487 return FailWithPreparedException(isolate, script,
1488 parse_info->pending_error_handler(), flag);
1489}
1490
1491void FinalizeUnoptimizedCompilation(
1492 Isolate* isolate, Handle<Script> script,
1493 const UnoptimizedCompileFlags& flags,
1494 const UnoptimizedCompileState* compile_state,
1496 finalize_unoptimized_compilation_data_list) {
1497 if (compile_state->pending_error_handler()->has_pending_warnings()) {
1498 compile_state->pending_error_handler()->ReportWarnings(isolate, script);
1499 }
1500
1501 bool need_source_positions =
1502 v8_flags.stress_lazy_source_positions ||
1503 (!flags.collect_source_positions() && isolate->NeedsSourcePositions());
1504
1505 for (const auto& finalize_data : finalize_unoptimized_compilation_data_list) {
1506 DirectHandle<SharedFunctionInfo> shared_info =
1507 finalize_data.function_handle();
1508 // It's unlikely, but possible, that the bytecode was flushed between being
1509 // allocated and now, so guard against that case, and against it being
1510 // flushed in the middle of this loop.
1511 IsCompiledScope is_compiled_scope(*shared_info, isolate);
1512 if (!is_compiled_scope.is_compiled()) continue;
1513
1514 if (need_source_positions) {
1516 }
1518 if (shared_info->is_toplevel()) {
1519 log_tag = flags.is_eval() ? LogEventListener::CodeTag::kEval
1520 : LogEventListener::CodeTag::kScript;
1521 } else {
1522 log_tag = LogEventListener::CodeTag::kFunction;
1523 }
1524 log_tag = V8FileLogger::ToNativeByScript(log_tag, *script);
1525 if (isolate->interpreted_frames_native_stack() &&
1526 isolate->logger()->is_listening_to_code_events()) {
1527 Compiler::InstallInterpreterTrampolineCopy(isolate, shared_info, log_tag);
1528 }
1529 DirectHandle<CoverageInfo> coverage_info;
1530 if (finalize_data.coverage_info().ToHandle(&coverage_info)) {
1531 isolate->debug()->InstallCoverageInfo(shared_info, coverage_info);
1532 }
1533
1534 LogUnoptimizedCompilation(isolate, shared_info, log_tag,
1535 finalize_data.time_taken_to_execute(),
1536 finalize_data.time_taken_to_finalize());
1537 }
1538}
1539
1540void FinalizeUnoptimizedScriptCompilation(
1541 Isolate* isolate, Handle<Script> script,
1542 const UnoptimizedCompileFlags& flags,
1543 const UnoptimizedCompileState* compile_state,
1545 finalize_unoptimized_compilation_data_list) {
1546 FinalizeUnoptimizedCompilation(isolate, script, flags, compile_state,
1547 finalize_unoptimized_compilation_data_list);
1548
1549 script->set_compilation_state(Script::CompilationState::kCompiled);
1550 DCHECK_IMPLIES(isolate->NeedsSourcePositions(), script->has_line_ends());
1551}
1552
1553void CompileAllWithBaseline(Isolate* isolate,
1555 finalize_unoptimized_compilation_data_list) {
1556 for (const auto& finalize_data : finalize_unoptimized_compilation_data_list) {
1557 Handle<SharedFunctionInfo> shared_info = finalize_data.function_handle();
1558 IsCompiledScope is_compiled_scope(*shared_info, isolate);
1559 if (!is_compiled_scope.is_compiled()) continue;
1560 if (!CanCompileWithBaseline(isolate, *shared_info)) continue;
1562 isolate, shared_info, Compiler::CLEAR_EXCEPTION, &is_compiled_scope);
1563 }
1564}
1565
1566// Create shared function info for top level and shared function infos array for
1567// inner functions.
1568template <typename IsolateT>
1569Handle<SharedFunctionInfo> CreateTopLevelSharedFunctionInfo(
1570 ParseInfo* parse_info, DirectHandle<Script> script, IsolateT* isolate) {
1571 EnsureInfosArrayOnScript(script, parse_info, isolate);
1573 parse_info->literal()->function_token_position());
1574 return isolate->factory()->NewSharedFunctionInfoForLiteral(
1575 parse_info->literal(), script, true);
1576}
1577
1578Handle<SharedFunctionInfo> GetOrCreateTopLevelSharedFunctionInfo(
1579 ParseInfo* parse_info, DirectHandle<Script> script, Isolate* isolate,
1580 IsCompiledScope* is_compiled_scope) {
1581 EnsureInfosArrayOnScript(script, parse_info, isolate);
1582 MaybeHandle<SharedFunctionInfo> maybe_shared =
1583 Script::FindSharedFunctionInfo(script, isolate, parse_info->literal());
1584 if (Handle<SharedFunctionInfo> shared; maybe_shared.ToHandle(&shared)) {
1585 DCHECK_EQ(shared->function_literal_id(),
1586 parse_info->literal()->function_literal_id());
1587 *is_compiled_scope = shared->is_compiled_scope(isolate);
1588 return shared;
1589 }
1590 return CreateTopLevelSharedFunctionInfo(parse_info, script, isolate);
1591}
1592
1593MaybeHandle<SharedFunctionInfo> CompileToplevel(
1594 ParseInfo* parse_info, Handle<Script> script,
1595 MaybeDirectHandle<ScopeInfo> maybe_outer_scope_info, Isolate* isolate,
1596 IsCompiledScope* is_compiled_scope) {
1597 TimerEventScope<TimerEventCompileCode> top_level_timer(isolate);
1598 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
1599 DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
1600
1601 PostponeInterruptsScope postpone(isolate);
1602 DCHECK(!isolate->native_context().is_null());
1603 RCS_SCOPE(isolate, parse_info->flags().is_eval()
1604 ? RuntimeCallCounterId::kCompileEval
1605 : RuntimeCallCounterId::kCompileScript);
1606 VMState<BYTECODE_COMPILER> state(isolate);
1607 if (parse_info->literal() == nullptr &&
1608 !parsing::ParseProgram(parse_info, script, maybe_outer_scope_info,
1610 FailWithException(isolate, script, parse_info,
1612 return MaybeHandle<SharedFunctionInfo>();
1613 }
1614 // Measure how long it takes to do the compilation; only take the
1615 // rest of the function into account to avoid overlap with the
1616 // parsing statistics.
1617 NestedTimedHistogram* rate = parse_info->flags().is_eval()
1618 ? isolate->counters()->compile_eval()
1619 : isolate->counters()->compile();
1620 NestedTimedHistogramScope timer(rate);
1622 parse_info->flags().is_eval() ? "V8.CompileEval" : "V8.Compile");
1623
1624 // Create the SharedFunctionInfo and add it to the script's list.
1625 Handle<SharedFunctionInfo> shared_info =
1626 GetOrCreateTopLevelSharedFunctionInfo(parse_info, script, isolate,
1627 is_compiled_scope);
1628
1630 finalize_unoptimized_compilation_data_list;
1631
1632 // Prepare and execute compilation of the outer-most function.
1633 if (!IterativelyExecuteAndFinalizeUnoptimizedCompilationJobs(
1634 isolate, script, parse_info, isolate->allocator(), is_compiled_scope,
1635 &finalize_unoptimized_compilation_data_list, nullptr)) {
1636 FailWithException(isolate, script, parse_info,
1638 return MaybeHandle<SharedFunctionInfo>();
1639 }
1640
1641 // Character stream shouldn't be used again.
1642 parse_info->ResetCharacterStream();
1643
1644 FinalizeUnoptimizedScriptCompilation(
1645 isolate, script, parse_info->flags(), parse_info->state(),
1646 finalize_unoptimized_compilation_data_list);
1647
1648 if (v8_flags.always_sparkplug) {
1649 CompileAllWithBaseline(isolate, finalize_unoptimized_compilation_data_list);
1650 }
1651
1652 return shared_info;
1653}
1654
1655#ifdef V8_RUNTIME_CALL_STATS
1656RuntimeCallCounterId RuntimeCallCounterIdForCompile(ParseInfo* parse_info) {
1657 if (parse_info->flags().is_toplevel()) {
1658 if (parse_info->flags().is_eval()) {
1659 return RuntimeCallCounterId::kCompileEval;
1660 }
1661 return RuntimeCallCounterId::kCompileScript;
1662 }
1663 return RuntimeCallCounterId::kCompileFunction;
1664}
1665#endif // V8_RUNTIME_CALL_STATS
1666
1667} // namespace
1668
1672
1674 LocalIsolate* isolate, Handle<SharedFunctionInfo> function_handle,
1675 MaybeHandle<CoverageInfo> coverage_info,
1676 base::TimeDelta time_taken_to_execute,
1677 base::TimeDelta time_taken_to_finalize)
1678 : time_taken_to_execute_(time_taken_to_execute),
1679 time_taken_to_finalize_(time_taken_to_finalize),
1680 function_handle_(isolate->heap()->NewPersistentHandle(function_handle)),
1681 coverage_info_(isolate->heap()->NewPersistentMaybeHandle(coverage_info)) {
1682}
1683
1685 LocalIsolate* isolate, Handle<SharedFunctionInfo> function_handle,
1686 std::unique_ptr<UnoptimizedCompilationJob> job)
1687 : function_handle_(isolate->heap()->NewPersistentHandle(function_handle)),
1688 job_(std::move(job)) {}
1689
1691 ScriptStreamingData* streamed_data, Isolate* isolate, ScriptType type,
1693 ScriptCompiler::CompilationDetails* compilation_details,
1694 CompileHintCallback compile_hint_callback, void* compile_hint_callback_data)
1695 : isolate_for_local_isolate_(isolate),
1696 flags_(UnoptimizedCompileFlags::ForToplevelCompile(
1697 isolate, true, construct_language_mode(v8_flags.use_strict),
1698 REPLMode::kNo, type,
1699 (options & ScriptCompiler::CompileOptions::kEagerCompile) == 0 &&
1700 v8_flags.lazy_streaming)),
1701 character_stream_(ScannerStream::For(streamed_data->source_stream.get(),
1702 streamed_data->encoding)),
1703 stack_size_(v8_flags.stack_size),
1704 worker_thread_runtime_call_stats_(
1705 isolate->counters()->worker_thread_runtime_call_stats()),
1706 timer_(isolate->counters()->compile_script_on_background()),
1707 compilation_details_(compilation_details),
1708 start_position_(0),
1709 end_position_(0),
1710 function_literal_id_(kFunctionLiteralIdTopLevel),
1711 compile_hint_callback_(compile_hint_callback),
1712 compile_hint_callback_data_(compile_hint_callback_data) {
1714 flags_.set_produce_compile_hints(true);
1715 }
1718 DCHECK_NOT_NULL(compile_hint_callback);
1719 DCHECK_NOT_NULL(compile_hint_callback_data);
1720 } else {
1721 DCHECK_NULL(compile_hint_callback);
1722 DCHECK_NULL(compile_hint_callback_data);
1723 }
1724 flags_.set_compile_hints_magic_enabled(
1725 options &
1727 flags_.set_compile_hints_per_function_magic_enabled(
1729 kFollowCompileHintsPerFunctionMagicComment);
1730}
1731
1733 Isolate* isolate, Handle<SharedFunctionInfo> shared_info,
1734 std::unique_ptr<Utf16CharacterStream> character_stream,
1735 WorkerThreadRuntimeCallStats* worker_thread_runtime_stats,
1736 TimedHistogram* timer, int max_stack_size)
1737 : isolate_for_local_isolate_(isolate),
1738 // TODO(leszeks): Create this from parent compile flags, to avoid
1739 // accessing the Isolate.
1740 flags_(
1741 UnoptimizedCompileFlags::ForFunctionCompile(isolate, *shared_info)),
1742 character_stream_(std::move(character_stream)),
1743 stack_size_(max_stack_size),
1744 worker_thread_runtime_call_stats_(worker_thread_runtime_stats),
1745 timer_(timer),
1746 compilation_details_(nullptr),
1747 start_position_(shared_info->StartPosition()),
1748 end_position_(shared_info->EndPosition()),
1749 function_literal_id_(shared_info->function_literal_id()) {
1750 DCHECK(!shared_info->is_toplevel());
1752
1754
1755 // Get the script out of the outer ParseInfo and turn it into a persistent
1756 // handle we can transfer to the background thread.
1757 persistent_handles_ = std::make_unique<PersistentHandles>(isolate);
1758 input_shared_info_ = persistent_handles_->NewHandle(shared_info);
1759}
1760
1762
1764 const ScriptDetails& script_details,
1766 Handle<Object> script_name;
1767 if (script_details.name_obj.ToHandle(&script_name)) {
1768 script->set_name(*script_name);
1769 script->set_line_offset(script_details.line_offset);
1770 script->set_column_offset(script_details.column_offset);
1771 }
1772 // The API can provide a source map URL, but a source map URL could also have
1773 // been inferred by the parser from a magic comment. The API source map URL
1774 // takes precedence (as long as it is a non-empty string).
1775 Handle<Object> source_map_url;
1776 if (script_details.source_map_url.ToHandle(&source_map_url) &&
1777 IsString(*source_map_url) &&
1778 Cast<String>(*source_map_url)->length() > 0) {
1779 script->set_source_mapping_url(*source_map_url);
1780 }
1781 Handle<Object> host_defined_options;
1782 if (script_details.host_defined_options.ToHandle(&host_defined_options)) {
1783 // TODO(cbruni, chromium:1244145): Remove once migrated to the context.
1784 if (IsFixedArray(*host_defined_options)) {
1785 script->set_host_defined_options(Cast<FixedArray>(*host_defined_options));
1786 }
1787 }
1788}
1789
1790namespace {
1791
1792#ifdef ENABLE_SLOW_DCHECKS
1793
1794// A class which traverses the object graph for a newly compiled Script and
1795// ensures that it contains pointers to Scripts, ScopeInfos and
1796// SharedFunctionInfos only at the expected locations. Any failure in this
1797// visitor indicates a case that is probably not handled correctly in
1798// BackgroundMergeTask.
1799class MergeAssumptionChecker final : public ObjectVisitor {
1800 public:
1801 explicit MergeAssumptionChecker(LocalIsolate* isolate)
1802 : isolate_(isolate), cage_base_(isolate->cage_base()) {}
1803
1804 void IterateObjects(Tagged<HeapObject> start) {
1805 QueueVisit(start, kNormalObject);
1806 while (to_visit_.size() > 0) {
1807 std::pair<Tagged<HeapObject>, ObjectKind> pair = to_visit_.top();
1808 to_visit_.pop();
1809 Tagged<HeapObject> current = pair.first;
1810 // The Script's infos list and the constant pools for all
1811 // BytecodeArrays are expected to contain pointers to SharedFunctionInfos.
1812 // However, the type of those objects (FixedArray or WeakFixedArray)
1813 // doesn't have enough information to indicate their usage, so we enqueue
1814 // those objects here rather than during VisitPointers.
1815 if (IsScript(current)) {
1816 Tagged<Script> script = Cast<Script>(current);
1817 Tagged<HeapObject> infos = script->infos();
1818 QueueVisit(infos, kScriptInfosList);
1819 // Avoid visiting eval_from_shared_or_wrapped_arguments. This field
1820 // points to data outside the new Script, and doesn't need to be merged.
1821 Tagged<HeapObject> eval_from_shared_or_wrapped_arguments;
1822 if (script->eval_from_shared_or_wrapped_arguments()
1823 .GetHeapObjectIfStrong(
1824 &eval_from_shared_or_wrapped_arguments)) {
1825 visited_.insert(eval_from_shared_or_wrapped_arguments);
1826 }
1827 } else if (IsBytecodeArray(current)) {
1828 Tagged<HeapObject> constants =
1829 Cast<BytecodeArray>(current)->constant_pool();
1830 QueueVisit(constants, kConstantPool);
1831 }
1832 current_object_kind_ = pair.second;
1833 i::VisitObjectBody(isolate_, current, this);
1834 QueueVisit(current->map(), kNormalObject);
1835 }
1836 }
1837
1838 // ObjectVisitor implementation:
1839 void VisitPointers(Tagged<HeapObject> host, ObjectSlot start,
1840 ObjectSlot end) override {
1841 MaybeObjectSlot maybe_start(start);
1842 MaybeObjectSlot maybe_end(end);
1843 VisitPointers(host, maybe_start, maybe_end);
1844 }
1845 void VisitPointers(Tagged<HeapObject> host, MaybeObjectSlot start,
1846 MaybeObjectSlot end) override {
1847 for (MaybeObjectSlot current = start; current != end; ++current) {
1848 Tagged<MaybeObject> maybe_obj = current.load(cage_base_);
1849 Tagged<HeapObject> obj;
1850 bool is_weak = maybe_obj.IsWeak();
1851 if (maybe_obj.GetHeapObject(&obj)) {
1852 if (IsSharedFunctionInfo(obj)) {
1853 CHECK((current_object_kind_ == kConstantPool && !is_weak) ||
1854 (current_object_kind_ == kScriptInfosList && is_weak) ||
1855 (IsScript(host) &&
1856 current.address() ==
1857 host.address() +
1858 Script::kEvalFromSharedOrWrappedArgumentsOffset));
1859 } else if (IsScopeInfo(obj)) {
1860 CHECK((current_object_kind_ == kConstantPool && !is_weak) ||
1861 (current_object_kind_ == kNormalObject && !is_weak) ||
1862 (current_object_kind_ == kScriptInfosList && is_weak));
1863 } else if (IsScript(obj)) {
1864 CHECK(IsSharedFunctionInfo(host) &&
1865 current == MaybeObjectSlot(host.address() +
1866 SharedFunctionInfo::kScriptOffset));
1867 } else if (IsFixedArray(obj) && current_object_kind_ == kConstantPool) {
1868 // Constant pools can contain nested fixed arrays, which in turn can
1869 // point to SFIs.
1870 QueueVisit(obj, kConstantPool);
1871 }
1872
1873 QueueVisit(obj, kNormalObject);
1874 }
1875 }
1876 }
1877
1878 // The object graph for a newly compiled Script shouldn't yet contain any
1879 // Code. If any of these functions are called, then that would indicate that
1880 // the graph was not disjoint from the rest of the heap as expected.
1881 void VisitInstructionStreamPointer(Tagged<Code> host,
1882 InstructionStreamSlot slot) override {
1883 UNREACHABLE();
1884 }
1885 void VisitCodeTarget(Tagged<InstructionStream> host,
1886 RelocInfo* rinfo) override {
1887 UNREACHABLE();
1888 }
1889 void VisitEmbeddedPointer(Tagged<InstructionStream> host,
1890 RelocInfo* rinfo) override {
1891 UNREACHABLE();
1892 }
1893
1894 private:
1895 enum ObjectKind {
1896 kNormalObject,
1897 kConstantPool,
1898 kScriptInfosList,
1899 };
1900
1901 // If the object hasn't yet been added to the worklist, add it. Subsequent
1902 // calls with the same object have no effect, even if kind is different.
1903 void QueueVisit(Tagged<HeapObject> obj, ObjectKind kind) {
1904 if (visited_.insert(obj).second) {
1905 to_visit_.push(std::make_pair(obj, kind));
1906 }
1907 }
1908
1910
1911 LocalIsolate* isolate_;
1912 PtrComprCageBase cage_base_;
1913 std::stack<std::pair<Tagged<HeapObject>, ObjectKind>> to_visit_;
1914
1915 // Objects that are either in to_visit_ or done being visited. It is safe to
1916 // use HeapObject directly here because GC is disallowed while running this
1917 // visitor.
1918 std::unordered_set<Tagged<HeapObject>, Object::Hasher> visited_;
1919
1920 ObjectKind current_object_kind_ = kNormalObject;
1921};
1922
1923#endif // ENABLE_SLOW_DCHECKS
1924
1925} // namespace
1926
1930
1934 UnparkedScope unparked_scope(&isolate);
1935 LocalHandleScope handle_scope(&isolate);
1936
1937 ReusableUnoptimizedCompileState reusable_state(&isolate);
1938
1939 Run(&isolate, &reusable_state);
1940}
1941
1943 LocalHandleScope handle_scope(isolate->main_thread_local_isolate());
1944 ReusableUnoptimizedCompileState reusable_state(isolate);
1945 Run(isolate->main_thread_local_isolate(), &reusable_state);
1946}
1947
1949 LocalIsolate* isolate, ReusableUnoptimizedCompileState* reusable_state) {
1950 TimedHistogramScope timer(
1951 timer_, nullptr,
1954 : nullptr);
1955
1957 "BackgroundCompileTask::Run");
1958 RCS_SCOPE(isolate, RuntimeCallCounterId::kCompileCompileTask,
1959 RuntimeCallStats::CounterMode::kThreadSpecific);
1960
1961 bool toplevel_script_compilation = flags_.is_toplevel();
1962
1963 ParseInfo info(isolate, flags_, &compile_state_, reusable_state,
1965 info.set_character_stream(std::move(character_stream_));
1966 info.SetCompileHintCallbackAndData(compile_hint_callback_,
1968 if (is_streaming_compilation()) info.set_is_streaming_compilation();
1969
1970 if (toplevel_script_compilation) {
1972 DCHECK(input_shared_info_.is_null());
1973
1974 // We don't have the script source, origin, or details yet, so use default
1975 // values for them. These will be fixed up during the main-thread merge.
1976 Handle<Script> script = info.CreateScript(
1977 isolate, isolate->factory()->empty_string(), kNullMaybeHandle,
1978 ScriptOriginOptions(false, false, false, info.flags().is_module()));
1979 script_ = isolate->heap()->NewPersistentHandle(script);
1980 } else {
1982 isolate->heap()->AttachPersistentHandles(std::move(persistent_handles_));
1984 input_shared_info_.ToHandleChecked();
1985 script_ = isolate->heap()->NewPersistentHandle(
1986 Cast<Script>(shared_info->script()));
1987 info.CheckFlagsForFunctionFromScript(*script_);
1988
1989 {
1990 SharedStringAccessGuardIfNeeded access_guard(isolate);
1991 info.set_function_name(info.ast_value_factory()->GetString(
1992 shared_info->Name(), access_guard));
1993 }
1994
1995 // Get preparsed scope data from the function literal.
1996 if (shared_info->HasUncompiledDataWithPreparseData()) {
1997 info.set_consumed_preparse_data(ConsumedPreparseData::For(
1998 isolate,
1999 handle(shared_info->uncompiled_data_with_preparse_data(isolate)
2000 ->preparse_data(isolate),
2001 isolate)));
2002 }
2003 }
2004
2005 // Update the character stream's runtime call stats.
2006 info.character_stream()->set_runtime_call_stats(info.runtime_call_stats());
2007
2008 Parser parser(isolate, &info);
2009 if (flags().is_toplevel()) {
2010 parser.InitializeEmptyScopeChain(&info);
2011 } else {
2012 // TODO(leszeks): Consider keeping Scope zones alive between compile tasks
2013 // and passing the Scope for the FunctionLiteral through here directly
2014 // without copying/deserializing.
2016 input_shared_info_.ToHandleChecked();
2017 MaybeDirectHandle<ScopeInfo> maybe_outer_scope_info;
2018 if (shared_info->HasOuterScopeInfo()) {
2019 maybe_outer_scope_info =
2020 direct_handle(shared_info->GetOuterScopeInfo(), isolate);
2021 }
2022 parser.DeserializeScopeChain(
2023 isolate, &info, maybe_outer_scope_info,
2025 }
2026
2027 parser.ParseOnBackground(isolate, &info, script_, start_position_,
2030
2032 "V8.CompileCodeBackground");
2033 RCS_SCOPE(isolate, RuntimeCallCounterIdForCompile(&info),
2034 RuntimeCallStats::CounterMode::kThreadSpecific);
2035
2037 if (info.literal() != nullptr) {
2038 if (toplevel_script_compilation) {
2039 CreateTopLevelSharedFunctionInfo(&info, script_, isolate);
2040 } else {
2041 // Clone into a placeholder SFI for storing the results.
2042 info.literal()->set_shared_function_info(
2043 isolate->factory()->CloneSharedFunctionInfo(
2044 input_shared_info_.ToHandleChecked()));
2045 }
2046
2047 if (IterativelyExecuteAndFinalizeUnoptimizedCompilationJobs(
2048 isolate, script_, &info, reusable_state->allocator(),
2051 maybe_result = info.literal()->shared_function_info();
2052 }
2053 }
2054
2055 if (maybe_result.is_null()) {
2056 PrepareException(isolate, &info);
2057 } else if (v8_flags.enable_slow_asserts) {
2058#ifdef ENABLE_SLOW_DCHECKS
2059 MergeAssumptionChecker checker(isolate);
2060 checker.IterateObjects(*maybe_result.ToHandleChecked());
2061#endif
2062 }
2063
2064 outer_function_sfi_ = isolate->heap()->NewPersistentMaybeHandle(maybe_result);
2065 DCHECK(isolate->heap()->ContainsPersistentHandle(script_.location()));
2066 persistent_handles_ = isolate->heap()->DetachPersistentHandles();
2067}
2068
2069// A class which traverses the constant pools of newly compiled
2070// SharedFunctionInfos and updates any pointers which need updating.
2072 public:
2074 LocalHeap* local_heap,
2075 DirectHandle<Script> old_script)
2076 : cage_base_(cage_base),
2077 local_heap_(local_heap),
2078 old_script_(old_script) {}
2079
2081 CHECK(IsBytecodeArray(bytecode_array));
2082 bytecode_arrays_to_update_.emplace_back(bytecode_array, local_heap_);
2083 }
2084
2086 RecordScopeInfos(maybe_old_info.GetHeapObjectAssumeWeak());
2087 }
2088
2089 // Record all scope infos relevant for a shared function info or scope info
2090 // (recorded for eval).
2092 if (!v8_flags.reuse_scope_infos) return;
2093 Tagged<ScopeInfo> scope_info;
2094 if (Is<SharedFunctionInfo>(info)) {
2096 // Also record context-having own scope infos for SFIs.
2097 if (!old_sfi->scope_info()->IsEmpty() &&
2098 old_sfi->scope_info()->HasContext()) {
2099 scope_info = old_sfi->scope_info();
2100 } else if (old_sfi->HasOuterScopeInfo()) {
2101 scope_info = old_sfi->GetOuterScopeInfo();
2102 } else {
2103 return;
2104 }
2105 } else {
2106 scope_info = Cast<ScopeInfo>(info);
2107 }
2108
2109 while (true) {
2110 auto it = scope_infos_to_update_.find(scope_info->UniqueIdInScript());
2111 if (it != scope_infos_to_update_.end()) {
2112 // Once we find an already recorded scope info, it need to match the one
2113 // on the chain.
2114 if (V8_UNLIKELY(*it->second != scope_info)) {
2115 info->Print();
2116 (*it->second)->Print();
2117 scope_info->Print();
2118 UNREACHABLE();
2119 }
2120 return;
2121 }
2122 scope_infos_to_update_[scope_info->UniqueIdInScript()] =
2123 handle(scope_info, local_heap_);
2124 if (!scope_info->HasOuterScopeInfo()) break;
2125 scope_info = scope_info->OuterScopeInfo();
2126 }
2127 }
2128
2129 // Runs the update after the setup functions above specified the work to do.
2138
2142
2145 !scope_infos_to_update_.empty();
2146 }
2147
2148 // Find an own scope info for the sfi based on the UniqueIdInScript that the
2149 // own scope info would have. This works even if the SFI doesn't yet have a
2150 // scope info attached by computing UniqueIdInScript from the SFI position.
2151 //
2152 // This should only directly be used for SFIs that already existed on the
2153 // script. Their outer scope info will already be correct.
2155 if (!v8_flags.reuse_scope_infos) return false;
2156 auto it = scope_infos_to_update_.find(sfi->UniqueIdInScript());
2157 if (it == scope_infos_to_update_.end()) return false;
2158 sfi->SetScopeInfo(*it->second);
2159 return true;
2160 }
2161
2162 // Either replace the own scope info of the sfi, or the first outer scope info
2163 // that was recorded.
2164 //
2165 // This has to be used for all newly created SFIs since their outer scope info
2166 // also may need to be reattached.
2168 if (!v8_flags.reuse_scope_infos) return;
2169 if (InstallOwnScopeInfo(sfi)) return;
2170 if (!sfi->HasOuterScopeInfo()) return;
2171
2172 Tagged<ScopeInfo> parent =
2173 sfi->scope_info()->IsEmpty() ? Tagged<ScopeInfo>() : sfi->scope_info();
2174 Tagged<ScopeInfo> outer_info = sfi->GetOuterScopeInfo();
2175
2176 auto it = scope_infos_to_update_.find(outer_info->UniqueIdInScript());
2177 while (it == scope_infos_to_update_.end()) {
2178 if (!outer_info->HasOuterScopeInfo()) return;
2179 parent = outer_info;
2180 outer_info = outer_info->OuterScopeInfo();
2181 it = scope_infos_to_update_.find(outer_info->UniqueIdInScript());
2182 }
2183 if (outer_info == *it->second) return;
2184
2185 VerifyScopeInfo(outer_info, *it->second);
2186
2187 if (parent.is_null()) {
2188 sfi->set_raw_outer_scope_info_or_feedback_metadata(*it->second);
2189 } else {
2190 parent->set_outer_scope_info(*it->second);
2191 }
2192 }
2193
2194 private:
2196 Tagged<ScopeInfo> replacement) {
2197 CHECK_EQ(replacement->EndPosition(), scope_info->EndPosition());
2198 CHECK_EQ(replacement->scope_type(), scope_info->scope_type());
2199 CHECK_EQ(replacement->ContextLength(), scope_info->ContextLength());
2200 }
2201 template <typename TArray>
2203 Tagged<Object> obj = constant_pool->get(i);
2204 if (IsSmi(obj)) return;
2205 Tagged<HeapObject> heap_obj = Cast<HeapObject>(obj);
2206 if (IsFixedArray(heap_obj, cage_base_)) {
2207 // Constant pools can have nested fixed arrays, but such relationships
2208 // are acyclic and never more than a few layers deep, so recursion is
2209 // fine here.
2212 IsSharedFunctionInfo(heap_obj, cage_base_)) {
2214 Cast<SharedFunctionInfo>(heap_obj));
2215 } else if (!scope_infos_to_update_.empty() &&
2216 IsScopeInfo(heap_obj, cage_base_)) {
2218 }
2219 }
2220
2221 template <typename TArray>
2224 Tagged<MaybeObject> maybe_old_sfi =
2225 old_script_->infos()->get(sfi->function_literal_id());
2226 if (maybe_old_sfi.IsWeak()) {
2227 constant_pool->set(
2229 }
2230 }
2231
2232 template <typename TArray>
2234 Tagged<ScopeInfo> scope_info) {
2235 auto it = scope_infos_to_update_.find(scope_info->UniqueIdInScript());
2236 // Try to replace the scope info itself with an already existing version.
2237 if (it != scope_infos_to_update_.end()) {
2238 if (scope_info != *it->second) {
2239 VerifyScopeInfo(scope_info, *it->second);
2240 constant_pool->set(i, *it->second);
2241 }
2242 } else if (scope_info->HasOuterScopeInfo()) {
2243 // If we didn't find a match, but we have an outer scope info, try to
2244 // replace the outer scope info with an already existing outer scope
2245 // info. We only need to look at the direct outer scope info since we'll
2246 // process all scope infos that are created by this compilation task.
2247 Tagged<ScopeInfo> outer = scope_info->OuterScopeInfo();
2248 it = scope_infos_to_update_.find(outer->UniqueIdInScript());
2249 if (it != scope_infos_to_update_.end() && outer != *it->second) {
2250 VerifyScopeInfo(outer, *it->second);
2251 scope_info->set_outer_scope_info(*it->second);
2252 }
2253 }
2254 }
2255
2257 for (int i = 0, length = constant_pool->length(); i < length; ++i) {
2259 }
2260 }
2261
2263 for (int i = 0, length = nested_array->length(); i < length; ++i) {
2264 IterateConstantPoolEntry(nested_array, i);
2265 }
2266 }
2267
2271 std::vector<IndirectHandle<BytecodeArray>> bytecode_arrays_to_update_;
2272
2273 // Indicates whether we have any shared function info to forward.
2275 std::unordered_map<int, IndirectHandle<ScopeInfo>> scope_infos_to_update_;
2276};
2277
2279 Handle<String> source_text,
2280 const ScriptDetails& script_details,
2281 LanguageMode language_mode) {
2283
2284 HandleScope handle_scope(isolate);
2285
2287 isolate->compilation_cache()->LookupScript(source_text, script_details,
2288 language_mode);
2290 if (!lookup_result.script().ToHandle(&script)) {
2291 state_ = kDone;
2292 return;
2293 }
2294
2295 if (lookup_result.is_compiled_scope().is_compiled()) {
2296 // There already exists a compiled top-level SFI, so the main thread will
2297 // discard the background serialization results and use the top-level SFI
2298 // from the cache, assuming the top-level SFI is still compiled by then.
2299 // Thus, there is no need to keep the Script pointer for background merging.
2300 // Do nothing in this case.
2301 state_ = kDone;
2302 } else {
2303 DCHECK(lookup_result.toplevel_sfi().is_null());
2304 // A background merge is required.
2305 SetUpOnMainThread(isolate, script);
2306 }
2307}
2308
2309namespace {
2310void VerifyCodeMerge(Isolate* isolate, DirectHandle<Script> script) {
2311 if (!v8_flags.reuse_scope_infos) return;
2312 // Check that:
2313 // * There aren't any duplicate scope info. Every scope/context should
2314 // correspond to at most one scope info.
2315 // * All published SFIs refer to the old script (i.e. we chose new vs old
2316 // correctly, and updated new SFIs where needed).
2317 // * All constant pool SFI entries point to an SFI referring to the old
2318 // script (i.e. references were updated correctly).
2319 std::unordered_map<int, Tagged<ScopeInfo>> scope_infos;
2320 for (int info_idx = 0; info_idx < script->infos()->length(); info_idx++) {
2321 Tagged<ScopeInfo> scope_info;
2322 if (!script->infos()->get(info_idx).IsWeak()) continue;
2323 Tagged<HeapObject> info =
2324 script->infos()->get(info_idx).GetHeapObjectAssumeWeak();
2325 if (Is<SharedFunctionInfo>(info)) {
2327 CHECK_EQ(sfi->script(), *script);
2328
2329 if (sfi->HasBytecodeArray()) {
2330 Tagged<BytecodeArray> bytecode = sfi->GetBytecodeArray(isolate);
2331 Tagged<TrustedFixedArray> constant_pool = bytecode->constant_pool();
2332 for (int constant_idx = 0; constant_idx < constant_pool->length();
2333 ++constant_idx) {
2334 Tagged<Object> entry = constant_pool->get(constant_idx);
2335 if (Is<SharedFunctionInfo>(entry)) {
2336 Tagged<SharedFunctionInfo> inner_sfi =
2338 int id = inner_sfi->function_literal_id();
2339 CHECK_EQ(MakeWeak(inner_sfi), script->infos()->get(id));
2340 CHECK_EQ(inner_sfi->script(), *script);
2341 }
2342 }
2343 }
2344
2345 if (!sfi->scope_info()->IsEmpty()) {
2346 scope_info = sfi->scope_info();
2347 } else if (sfi->HasOuterScopeInfo()) {
2348 scope_info = sfi->GetOuterScopeInfo();
2349 } else {
2350 continue;
2351 }
2352 } else {
2353 scope_info = Cast<ScopeInfo>(info);
2354 }
2355 while (true) {
2356 auto it = scope_infos.find(scope_info->UniqueIdInScript());
2357 if (it != scope_infos.end()) {
2358 if (*it->second != scope_info) {
2359 isolate->PushParamsAndDie(reinterpret_cast<void*>(it->second->ptr()),
2360 reinterpret_cast<void*>(scope_info.ptr()));
2361 UNREACHABLE();
2362 }
2363 break;
2364 }
2365 scope_infos[scope_info->UniqueIdInScript()] = scope_info;
2366 if (!scope_info->HasOuterScopeInfo()) break;
2367 scope_info = scope_info->OuterScopeInfo();
2368 }
2369 }
2370}
2371} // namespace
2372
2374 Isolate* isolate, DirectHandle<Script> cached_script) {
2375 // Any data sent to the background thread will need to be a persistent handle.
2376#ifdef DEBUG
2377 VerifyCodeMerge(isolate, cached_script);
2378#else
2379 if (v8_flags.verify_code_merge) {
2380 VerifyCodeMerge(isolate, cached_script);
2381 }
2382#endif
2383
2384 persistent_handles_ = std::make_unique<PersistentHandles>(isolate);
2386 cached_script_ = persistent_handles_->NewHandle(*cached_script);
2387}
2388
2390
2394
2396 LocalIsolate* isolate, DirectHandle<Script> new_script) {
2398
2399 LocalHeap* local_heap = isolate->heap();
2400 local_heap->AttachPersistentHandles(std::move(persistent_handles_));
2401 LocalHandleScope handle_scope(local_heap);
2402 DirectHandle<Script> old_script = cached_script_.ToHandleChecked();
2403 ConstantPoolPointerForwarder forwarder(isolate, local_heap, old_script);
2404
2405 {
2407 Tagged<MaybeObject> maybe_old_toplevel_sfi =
2408 old_script->infos()->get(kFunctionLiteralIdTopLevel);
2409 if (maybe_old_toplevel_sfi.IsWeak()) {
2411 maybe_old_toplevel_sfi.GetHeapObjectAssumeWeak());
2413 local_heap->NewPersistentHandle(old_toplevel_sfi);
2414 }
2415 }
2416
2417 // Iterate the SFI lists on both Scripts to set up the forwarding table and
2418 // follow-up worklists for the main thread.
2419 CHECK_EQ(old_script->infos()->length(), new_script->infos()->length());
2420 for (int i = 0; i < old_script->infos()->length(); ++i) {
2422 Tagged<MaybeObject> maybe_new_sfi = new_script->infos()->get(i);
2423 Tagged<MaybeObject> maybe_old_info = old_script->infos()->get(i);
2424 // We might have scope infos in the table if it's deserialized from a code
2425 // cache.
2426 if (maybe_new_sfi.IsWeak() &&
2430 if (maybe_old_info.IsWeak()) {
2432 // The old script and the new script both have SharedFunctionInfos for
2433 // this function literal.
2436 // Make sure to allocate a persistent handle to the old sfi whether or
2437 // not it or the new sfi have bytecode -- this is necessary to keep the
2438 // old sfi reference in the old script list alive, so that pointers to
2439 // the new sfi are redirected to the old sfi.
2440 Handle<SharedFunctionInfo> old_sfi_handle =
2441 local_heap->NewPersistentHandle(old_sfi);
2442 if (old_sfi->HasBytecodeArray()) {
2443 // Reset the old SFI's bytecode age so that it won't likely get
2444 // flushed right away. This operation might be racing against
2445 // concurrent modification by another thread, but such a race is not
2446 // catastrophic.
2447 old_sfi->set_age(0);
2448 } else if (new_sfi->HasBytecodeArray()) {
2449 // Also push the old_sfi to make sure it stays alive / isn't replaced.
2451 {old_sfi_handle, local_heap->NewPersistentHandle(new_sfi)});
2452 Tagged<ScopeInfo> info = old_sfi->scope_info();
2453 if (!info->IsEmpty()) {
2454 new_sfi->SetScopeInfo(info);
2455 } else if (old_sfi->HasOuterScopeInfo()) {
2456 new_sfi->scope_info()->set_outer_scope_info(
2457 old_sfi->GetOuterScopeInfo());
2458 }
2459 forwarder.AddBytecodeArray(new_sfi->GetBytecodeArray(isolate));
2460 }
2461 } else {
2462 // The old script didn't have a SharedFunctionInfo for this function
2463 // literal, so it can use the new SharedFunctionInfo.
2464 new_sfi->set_script(*old_script, kReleaseStore);
2465 used_new_sfis_.push_back(local_heap->NewPersistentHandle(new_sfi));
2466 if (new_sfi->HasBytecodeArray()) {
2467 forwarder.AddBytecodeArray(new_sfi->GetBytecodeArray(isolate));
2468 }
2469 }
2470 }
2471
2472 if (maybe_old_info.IsWeak()) {
2473 forwarder.RecordScopeInfos(maybe_old_info);
2474 // If the old script has a SFI, point to it from the new script to
2475 // indicate we've already seen it and we'll reuse it if necessary (if
2476 // newly compiled bytecode points to it).
2477 new_script->infos()->set(i, maybe_old_info);
2478 }
2479 }
2480
2481 // Since we are walking the script infos weak list both when figuring out
2482 // which SFIs to merge above, and actually merging them below, make sure that
2483 // a GC here which clears any dead weak refs or flushes any bytecode doesn't
2484 // break anything.
2486 // This GC is only synchronous on the main thread at the moment.
2487 DCHECK(isolate->is_main_thread());
2488 local_heap->AsHeap()->CollectAllAvailableGarbage(
2490 }
2491
2492 if (forwarder.HasAnythingToForward()) {
2494 forwarder.UpdateScopeInfo(*new_sfi);
2495 }
2496 for (const auto& new_compiled_data : new_compiled_data_for_cached_sfis_) {
2497 // It's possible that new_compiled_data.cached_sfi had
2498 // scope_info()->IsEmpty() while an inner function has scope info if the
2499 // cached_sfi was recreated when an outer function was recompiled. If so,
2500 // new_compiled_data.new_sfi does not have a reused scope info yet, and
2501 // we'll have found it when we visited the inner function. Try to pick it
2502 // up here.
2503 forwarder.InstallOwnScopeInfo(*new_compiled_data.new_sfi);
2504 }
2505 forwarder.IterateAndForwardPointers();
2506 }
2509}
2510
2512 Isolate* isolate, DirectHandle<Script> new_script) {
2514
2515 HandleScope handle_scope(isolate);
2516 DirectHandle<Script> old_script = cached_script_.ToHandleChecked();
2518 isolate, isolate->main_thread_local_heap(), old_script);
2519
2520 for (const auto& new_compiled_data : new_compiled_data_for_cached_sfis_) {
2521 Tagged<SharedFunctionInfo> sfi = *new_compiled_data.cached_sfi;
2522 if (!sfi->is_compiled() && new_compiled_data.new_sfi->is_compiled()) {
2523 // Updating existing DebugInfos is not supported, but we don't expect
2524 // uncompiled SharedFunctionInfos to contain DebugInfos.
2525 DCHECK(!new_compiled_data.cached_sfi->HasDebugInfo(isolate));
2526 // The goal here is to copy every field except script from
2527 // new_sfi to cached_sfi. The safest way to do so (including a DCHECK that
2528 // no fields were skipped) is to first copy the script from
2529 // cached_sfi to new_sfi, and then copy every field using CopyFrom.
2530 new_compiled_data.new_sfi->set_script(sfi->script(kAcquireLoad),
2532 sfi->CopyFrom(*new_compiled_data.new_sfi, isolate);
2533 }
2534 }
2535
2536 for (int i = 0; i < old_script->infos()->length(); ++i) {
2537 Tagged<MaybeObject> maybe_old_info = old_script->infos()->get(i);
2538 Tagged<MaybeObject> maybe_new_info = new_script->infos()->get(i);
2539 if (maybe_new_info == maybe_old_info) continue;
2541 if (maybe_old_info.IsWeak()) {
2542 // The old script's SFI didn't exist during the background work, but does
2543 // now. This means a re-merge is necessary. Potential references to the
2544 // new script's SFI need to be updated to point to the cached script's SFI
2545 // instead. The cached script's SFI's outer scope infos need to be used by
2546 // the new script's outer SFIs.
2547 if (Is<SharedFunctionInfo>(maybe_old_info.GetHeapObjectAssumeWeak())) {
2549 }
2550 forwarder.RecordScopeInfos(maybe_old_info);
2551 } else {
2552 old_script->infos()->set(i, maybe_new_info);
2553 }
2554 }
2555
2556 // Most of the time, the background merge was sufficient. However, if there
2557 // are any new pointers that need forwarding, a new traversal of the constant
2558 // pools is required.
2559 if (forwarder.HasAnythingToForward()) {
2561 forwarder.UpdateScopeInfo(*new_sfi);
2562 if (new_sfi->HasBytecodeArray(isolate)) {
2563 forwarder.AddBytecodeArray(new_sfi->GetBytecodeArray(isolate));
2564 }
2565 }
2566 for (const auto& new_compiled_data : new_compiled_data_for_cached_sfis_) {
2567 // It's possible that cached_sfi wasn't compiled, but an inner function
2568 // existed that didn't exist when be background merged. In that case, pick
2569 // up the relevant scope infos.
2570 Tagged<SharedFunctionInfo> sfi = *new_compiled_data.cached_sfi;
2571 forwarder.InstallOwnScopeInfo(sfi);
2572 if (new_compiled_data.cached_sfi->HasBytecodeArray(isolate)) {
2573 forwarder.AddBytecodeArray(
2574 new_compiled_data.cached_sfi->GetBytecodeArray(isolate));
2575 }
2576 }
2577 forwarder.IterateAndForwardPointers();
2578 }
2579
2580 Tagged<MaybeObject> maybe_toplevel_sfi =
2581 old_script->infos()->get(kFunctionLiteralIdTopLevel);
2582 CHECK(maybe_toplevel_sfi.IsWeak());
2585 isolate);
2586
2587 state_ = kDone;
2588
2589 if (isolate->NeedsSourcePositions()) {
2590 Script::InitLineEnds(isolate, new_script);
2592 }
2593
2594#ifdef DEBUG
2595 VerifyCodeMerge(isolate, old_script);
2596#else
2597 if (v8_flags.verify_code_merge) {
2598 VerifyCodeMerge(isolate, old_script);
2599 }
2600#endif
2601
2602 return handle_scope.CloseAndEscape(result);
2603}
2604
2606 Isolate* isolate, DirectHandle<String> source,
2607 const ScriptDetails& script_details,
2608 MaybeDirectHandle<Script> maybe_cached_script) {
2609 ScriptOriginOptions origin_options = script_details.origin_options;
2610
2611 DCHECK(flags_.is_toplevel());
2612 DCHECK_EQ(flags_.is_module(), origin_options.IsModule());
2613
2615 Handle<Script> script = script_;
2616
2617 // We might not have been able to finalize all jobs on the background
2618 // thread (e.g. asm.js jobs), so finalize those deferred jobs now.
2619 if (FinalizeDeferredUnoptimizedCompilationJobs(
2623 maybe_result = outer_function_sfi_;
2624 }
2625
2626 if (DirectHandle<Script> cached_script;
2627 maybe_cached_script.ToHandle(&cached_script) && !maybe_result.is_null()) {
2628 BackgroundMergeTask merge;
2629 merge.SetUpOnMainThread(isolate, cached_script);
2631 merge.BeginMergeInBackground(isolate->AsLocalIsolate(), script);
2634 merge.CompleteMergeInForeground(isolate, script);
2635 maybe_result = result;
2636 script = handle(Cast<Script>(result->script()), isolate);
2637 DCHECK(Object::StrictEquals(script->source(), *source));
2638 DCHECK(isolate->factory()->script_list()->Contains(MakeWeak(*script)));
2639 } else {
2640 Script::SetSource(isolate, script, source);
2641 script->set_origin_options(origin_options);
2642
2643 // The one post-hoc fix-up: Add the script to the script list.
2644 DirectHandle<WeakArrayList> scripts = isolate->factory()->script_list();
2645 scripts = WeakArrayList::Append(isolate, scripts,
2647 isolate->heap()->SetRootScriptList(*scripts);
2648
2649 // Set the script fields after finalization, to keep this path the same
2650 // between main-thread and off-thread finalization.
2651 {
2653 SetScriptFieldsFromDetails(isolate, *script, script_details, &no_gc);
2654 LOG(isolate, ScriptDetails(*script));
2655 }
2656 }
2657
2658 ReportStatistics(isolate);
2659
2661 if (!maybe_result.ToHandle(&result)) {
2662 FailWithPreparedException(isolate, script,
2664 return kNullMaybeHandle;
2665 }
2666
2667 FinalizeUnoptimizedScriptCompilation(isolate, script, flags_, &compile_state_,
2669
2670 return handle(*result, isolate);
2671}
2672
2674 Isolate* isolate, Compiler::ClearExceptionFlag flag) {
2675 DCHECK(!flags_.is_toplevel());
2676
2678 DirectHandle<SharedFunctionInfo> input_shared_info =
2679 input_shared_info_.ToHandleChecked();
2680
2681 // The UncompiledData on the input SharedFunctionInfo will have a pointer to
2682 // the LazyCompileDispatcher Job that launched this task, which will now be
2683 // considered complete, so clear that regardless of whether the finalize
2684 // succeeds or not.
2685 input_shared_info->ClearUncompiledDataJobPointer(isolate);
2686
2687 // We might not have been able to finalize all jobs on the background
2688 // thread (e.g. asm.js jobs), so finalize those deferred jobs now.
2689 if (FinalizeDeferredUnoptimizedCompilationJobs(
2693 maybe_result = outer_function_sfi_;
2694 }
2695
2696 ReportStatistics(isolate);
2697
2699 if (!maybe_result.ToHandle(&result)) {
2700 FailWithPreparedException(isolate, script_,
2702 return false;
2703 }
2704
2705 FinalizeUnoptimizedCompilation(isolate, script_, flags_, &compile_state_,
2707
2708 // Move the compiled data from the placeholder SFI back to the real SFI.
2709 input_shared_info->CopyFrom(*result, isolate);
2710
2711 return true;
2712}
2713
2715 // The UncompiledData on the input SharedFunctionInfo will have a pointer to
2716 // the LazyCompileDispatcher Job that launched this task, which is about to be
2717 // deleted, so clear that to avoid the SharedFunctionInfo from pointing to
2718 // deallocated memory.
2719 input_shared_info_.ToHandleChecked()->ClearUncompiledDataJobPointer(
2721}
2722
2724 // Update use-counts.
2725 for (auto feature : use_counts_) {
2726 isolate->CountUsage(feature);
2727 }
2728}
2729
2731 Isolate* isolate, std::unique_ptr<ScriptCompiler::CachedData> cached_data)
2732 : isolate_for_local_isolate_(isolate),
2733 cached_data_(cached_data->data, cached_data->length),
2734 timer_(isolate->counters()->deserialize_script_on_background()) {
2735 // If the passed in cached data has ownership of the buffer, move it to the
2736 // task.
2737 if (cached_data->buffer_policy == ScriptCompiler::CachedData::BufferOwned &&
2739 cached_data->buffer_policy = ScriptCompiler::CachedData::BufferNotOwned;
2740 cached_data_.AcquireDataOwnership();
2741 }
2742}
2743
2747 UnparkedScope unparked_scope(&isolate);
2748 LocalHandleScope handle_scope(&isolate);
2749
2753 if (v8_flags.enable_slow_asserts && off_thread_data_.HasResult()) {
2754#ifdef ENABLE_SLOW_DCHECKS
2755 MergeAssumptionChecker checker(&isolate);
2756 checker.IterateObjects(*off_thread_data_.GetOnlyScript(isolate.heap()));
2757#endif
2758 }
2759}
2760
2762 Isolate* isolate, Handle<String> source_text,
2763 const ScriptDetails& script_details) {
2765 LanguageMode language_mode = construct_language_mode(v8_flags.use_strict);
2766 background_merge_task_.SetUpOnMainThread(isolate, source_text, script_details,
2767 language_mode);
2768}
2769
2771 DCHECK(v8_flags.merge_background_deserialized_script_with_compilation_cache);
2774}
2775
2786
2788 Isolate* isolate, DirectHandle<String> source,
2789 const ScriptDetails& script_details) {
2791 isolate, std::move(off_thread_data_), &cached_data_, source,
2792 script_details, &background_merge_task_);
2793}
2794
2795// ----------------------------------------------------------------------------
2796// Implementation of Compiler
2797
2798// static
2800 Isolate* isolate, DirectHandle<SharedFunctionInfo> shared_info) {
2801 DCHECK(shared_info->is_compiled());
2802 DCHECK(shared_info->HasBytecodeArray());
2803 DCHECK(!shared_info->GetBytecodeArray(isolate)->HasSourcePositionTable());
2804
2805 // Source position collection should be context independent.
2806 NullContextScope null_context_scope(isolate);
2807
2808 // Collecting source positions requires allocating a new source position
2809 // table.
2810 DCHECK(AllowHeapAllocation::IsAllowed());
2811
2812 Handle<BytecodeArray> bytecode =
2813 handle(shared_info->GetBytecodeArray(isolate), isolate);
2814
2815 // TODO(v8:8510): Push the CLEAR_EXCEPTION flag or something like it down into
2816 // the parser so it aborts without setting an exception, which then
2817 // gets thrown. This would avoid the situation where potentially we'd reparse
2818 // several times (running out of stack each time) before hitting this limit.
2819 if (GetCurrentStackPosition() < isolate->stack_guard()->real_climit()) {
2820 // Stack is already exhausted.
2821 bytecode->SetSourcePositionsFailedToCollect();
2822 return false;
2823 }
2824
2825 // Unfinalized scripts don't yet have the proper source string attached and
2826 // thus can't be reparsed.
2827 if (Cast<Script>(shared_info->script())->IsMaybeUnfinalized(isolate)) {
2828 bytecode->SetSourcePositionsFailedToCollect();
2829 return false;
2830 }
2831
2832 DCHECK(AllowCompilation::IsAllowed(isolate));
2833 DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
2834
2835 DCHECK(!isolate->has_exception());
2837 PostponeInterruptsScope postpone(isolate);
2838 RCS_SCOPE(isolate, RuntimeCallCounterId::kCompileCollectSourcePositions);
2840 "V8.CollectSourcePositions");
2842 isolate->counters()->collect_source_positions());
2843
2844 // Set up parse info.
2846 UnoptimizedCompileFlags::ForFunctionCompile(isolate, *shared_info);
2847 flags.set_collect_source_positions(true);
2848 flags.set_is_reparse(true);
2849 // Prevent parallel tasks from being spawned by this job.
2850 flags.set_post_parallel_compile_tasks_for_eager_toplevel(false);
2851 flags.set_post_parallel_compile_tasks_for_lazy(false);
2852
2853 UnoptimizedCompileState compile_state;
2854 ReusableUnoptimizedCompileState reusable_state(isolate);
2855 ParseInfo parse_info(isolate, flags, &compile_state, &reusable_state);
2856
2857 // Parse and update ParseInfo with the results. Don't update parsing
2858 // statistics since we've already parsed the code before.
2859 if (!parsing::ParseAny(&parse_info, shared_info, isolate,
2861 // Parsing failed probably as a result of stack exhaustion.
2862 bytecode->SetSourcePositionsFailedToCollect();
2863 return FailAndClearException(isolate);
2864 }
2865
2866 // Character stream shouldn't be used again.
2867 parse_info.ResetCharacterStream();
2868
2869 // Generate the unoptimized bytecode.
2870 // TODO(v8:8510): Consider forcing preparsing of inner functions to avoid
2871 // wasting time fully parsing them when they won't ever be used.
2872 std::unique_ptr<UnoptimizedCompilationJob> job;
2873 {
2875 &parse_info, parse_info.literal(), bytecode, isolate->allocator(),
2876 isolate->main_thread_local_isolate());
2877
2878 if (!job || job->ExecuteJob() != CompilationJob::SUCCEEDED ||
2879 job->FinalizeJob(shared_info, isolate) != CompilationJob::SUCCEEDED) {
2880 // Recompiling failed probably as a result of stack exhaustion.
2881 bytecode->SetSourcePositionsFailedToCollect();
2882 return FailAndClearException(isolate);
2883 }
2884 }
2885
2886 DCHECK(job->compilation_info()->flags().collect_source_positions());
2887
2888 // If debugging, make sure that instrumented bytecode has the source position
2889 // table set on it as well.
2890 if (std::optional<Tagged<DebugInfo>> debug_info =
2891 shared_info->TryGetDebugInfo(isolate)) {
2892 if (debug_info.value()->HasInstrumentedBytecodeArray()) {
2893 Tagged<TrustedByteArray> source_position_table =
2894 job->compilation_info()->bytecode_array()->SourcePositionTable();
2895 shared_info->GetActiveBytecodeArray(isolate)->set_source_position_table(
2896 source_position_table, kReleaseStore);
2897 }
2898 }
2899
2900 DCHECK(!isolate->has_exception());
2901 DCHECK(shared_info->is_compiled_scope(isolate).is_compiled());
2902 return true;
2903}
2904
2905// static
2907 ClearExceptionFlag flag,
2908 IsCompiledScope* is_compiled_scope,
2909 CreateSourcePositions create_source_positions_flag) {
2910 // We should never reach here if the function is already compiled.
2911 DCHECK(!shared_info->is_compiled());
2912 DCHECK(!is_compiled_scope->is_compiled());
2913 DCHECK(AllowCompilation::IsAllowed(isolate));
2914 DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
2915 DCHECK(!isolate->has_exception());
2916 DCHECK(!shared_info->HasBytecodeArray());
2917
2919 PostponeInterruptsScope postpone(isolate);
2920 TimerEventScope<TimerEventCompileCode> compile_timer(isolate);
2921 RCS_SCOPE(isolate, RuntimeCallCounterId::kCompileFunction);
2922 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
2923 AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy());
2924
2925 Handle<Script> script(Cast<Script>(shared_info->script()), isolate);
2926
2927 // Set up parse info.
2929 UnoptimizedCompileFlags::ForFunctionCompile(isolate, *shared_info);
2930 if (create_source_positions_flag == CreateSourcePositions::kYes) {
2931 flags.set_collect_source_positions(true);
2932 }
2933
2934 UnoptimizedCompileState compile_state;
2935 ReusableUnoptimizedCompileState reusable_state(isolate);
2936 ParseInfo parse_info(isolate, flags, &compile_state, &reusable_state);
2937
2938 // Check if the compiler dispatcher has shared_info enqueued for compile.
2939 LazyCompileDispatcher* dispatcher = isolate->lazy_compile_dispatcher();
2940 if (dispatcher && dispatcher->IsEnqueued(shared_info)) {
2941 if (!dispatcher->FinishNow(shared_info)) {
2942 return FailWithException(isolate, script, &parse_info, flag);
2943 }
2944 *is_compiled_scope = shared_info->is_compiled_scope(isolate);
2945 DCHECK(is_compiled_scope->is_compiled());
2946 return true;
2947 }
2948
2949 if (shared_info->HasUncompiledDataWithPreparseData()) {
2951 isolate, handle(shared_info->uncompiled_data_with_preparse_data(isolate)
2952 ->preparse_data(),
2953 isolate)));
2954 }
2955
2956 // Parse and update ParseInfo with the results.
2957 if (!parsing::ParseAny(&parse_info, shared_info, isolate,
2959 return FailWithException(isolate, script, &parse_info, flag);
2960 }
2961 parse_info.literal()->set_shared_function_info(shared_info);
2962
2963 // Generate the unoptimized bytecode or asm-js data.
2965 finalize_unoptimized_compilation_data_list;
2966
2967 if (!IterativelyExecuteAndFinalizeUnoptimizedCompilationJobs(
2968 isolate, script, &parse_info, isolate->allocator(), is_compiled_scope,
2969 &finalize_unoptimized_compilation_data_list, nullptr)) {
2970 return FailWithException(isolate, script, &parse_info, flag);
2971 }
2972
2973 FinalizeUnoptimizedCompilation(isolate, script, flags, &compile_state,
2974 finalize_unoptimized_compilation_data_list);
2975
2976 if (v8_flags.always_sparkplug) {
2977 CompileAllWithBaseline(isolate, finalize_unoptimized_compilation_data_list);
2978 }
2979
2980 if (script->produce_compile_hints()) {
2981 // Log lazy function compilation.
2983 if (IsUndefined(script->compiled_lazy_function_positions())) {
2984 constexpr int kInitialLazyFunctionPositionListSize = 100;
2985 list = ArrayList::New(isolate, kInitialLazyFunctionPositionListSize);
2986 } else {
2987 list = direct_handle(
2988 Cast<ArrayList>(script->compiled_lazy_function_positions()), isolate);
2989 }
2990 list = ArrayList::Add(isolate, list,
2991 Smi::FromInt(shared_info->StartPosition()));
2992 script->set_compiled_lazy_function_positions(*list);
2993 }
2994
2995 DCHECK(!isolate->has_exception());
2996 DCHECK(is_compiled_scope->is_compiled());
2997 return true;
2998}
2999
3000// static
3002 ClearExceptionFlag flag,
3003 IsCompiledScope* is_compiled_scope) {
3004 // We should never reach here if the function is already compiled or
3005 // optimized.
3006 DCHECK(!function->is_compiled(isolate));
3007 DCHECK_IMPLIES(function->has_feedback_vector() &&
3008 function->IsTieringRequestedOrInProgress(),
3009 function->shared()->is_compiled());
3010 DCHECK_IMPLIES(function->HasAvailableOptimizedCode(isolate),
3011 function->shared()->is_compiled());
3012
3013 // Reset the JSFunction if we are recompiling due to the bytecode having been
3014 // flushed.
3015 function->ResetIfCodeFlushed(isolate);
3016
3017 Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);
3018
3019 // Ensure shared function info is compiled.
3020 *is_compiled_scope = shared_info->is_compiled_scope(isolate);
3021 if (!is_compiled_scope->is_compiled() &&
3022 !Compile(isolate, shared_info, flag, is_compiled_scope)) {
3023 return false;
3024 }
3025
3026 DCHECK(is_compiled_scope->is_compiled());
3027 DirectHandle<Code> code(shared_info->GetCode(isolate), isolate);
3028
3029 // Initialize the feedback cell for this JSFunction and reset the interrupt
3030 // budget for feedback vector allocation even if there is a closure feedback
3031 // cell array. We are re-compiling when we have a closure feedback cell array
3032 // which means we are compiling after a bytecode flush.
3033 // TODO(verwaest/mythria): Investigate if allocating feedback vector
3034 // immediately after a flush would be better.
3035 JSFunction::InitializeFeedbackCell(function, is_compiled_scope, true);
3036 function->ResetTieringRequests();
3037
3038 function->UpdateCode(*code);
3039
3040 // Optimize now if --always-turbofan is enabled.
3041#if V8_ENABLE_WEBASSEMBLY
3042 if (v8_flags.always_turbofan && !function->shared()->HasAsmWasmData()) {
3043#else
3044 if (v8_flags.always_turbofan) {
3045#endif // V8_ENABLE_WEBASSEMBLY
3046 DCHECK(!function->tiering_in_progress());
3047 CompilerTracer::TraceOptimizeForAlwaysOpt(isolate, function,
3049
3050 const CodeKind code_kind = CodeKindForTopTier();
3051 const ConcurrencyMode concurrency_mode = ConcurrencyMode::kSynchronous;
3052
3053 if (v8_flags.stress_concurrent_inlining &&
3054 isolate->concurrent_recompilation_enabled() &&
3055 isolate->node_observer() == nullptr) {
3056 SpawnDuplicateConcurrentJobForStressTesting(isolate, function,
3057 concurrency_mode, code_kind);
3058 }
3059
3060 DirectHandle<Code> maybe_code;
3061 if (GetOrCompileOptimized(isolate, function, concurrency_mode, code_kind)
3062 .ToHandle(&maybe_code)) {
3063 code = maybe_code;
3064 function->UpdateOptimizedCode(isolate, *code);
3065 }
3066 }
3067
3068 // Install a feedback vector if necessary.
3069 if (code->kind() == CodeKind::BASELINE) {
3070 JSFunction::EnsureFeedbackVector(isolate, function, is_compiled_scope);
3071 }
3072
3073 // Check postconditions on success.
3074 DCHECK(!isolate->has_exception());
3075 DCHECK(function->shared()->is_compiled());
3076 DCHECK(function->is_compiled(isolate));
3077 return true;
3078}
3079
3080// static
3084 IsCompiledScope* is_compiled_scope) {
3085 // We shouldn't be passing uncompiled functions into this function.
3086 DCHECK(is_compiled_scope->is_compiled());
3087
3088 // Early return for already baseline-compiled functions.
3089 if (shared->HasBaselineCode()) return true;
3090
3091 // Check if we actually can compile with baseline.
3092 if (!CanCompileWithBaseline(isolate, *shared)) return false;
3093
3094 StackLimitCheck check(isolate);
3095 if (check.JsHasOverflowed(kStackSpaceRequiredForCompilation * KB)) {
3096 if (flag == Compiler::KEEP_EXCEPTION) {
3097 isolate->StackOverflow();
3098 }
3099 return false;
3100 }
3101
3102 CompilerTracer::TraceStartBaselineCompile(isolate, shared);
3104 base::TimeDelta time_taken;
3105 {
3106 base::ScopedTimer timer(
3107 v8_flags.trace_baseline || v8_flags.log_function_events ? &time_taken
3108 : nullptr);
3109 if (!GenerateBaselineCode(isolate, shared).ToHandle(&code)) {
3110 // TODO(leszeks): This can only fail because of an OOM. Do we want to
3111 // report these somehow, or silently ignore them?
3112 return false;
3113 }
3114 shared->set_baseline_code(*code, kReleaseStore);
3115 shared->set_age(0);
3116 }
3117 double time_taken_ms = time_taken.InMillisecondsF();
3118
3119 CompilerTracer::TraceFinishBaselineCompile(isolate, shared, time_taken_ms);
3120
3121 if (IsScript(shared->script())) {
3123 isolate, LogEventListener::CodeTag::kFunction,
3124 direct_handle(Cast<Script>(shared->script()), isolate), shared,
3126 CodeKind::BASELINE, time_taken_ms);
3127 }
3128 return true;
3129}
3130
3131// static
3133 DirectHandle<JSFunction> function,
3134 ClearExceptionFlag flag,
3135 IsCompiledScope* is_compiled_scope) {
3136 Handle<SharedFunctionInfo> shared(function->shared(isolate), isolate);
3137 if (!CompileSharedWithBaseline(isolate, shared, flag, is_compiled_scope)) {
3138 return false;
3139 }
3140
3141 // Baseline code needs a feedback vector.
3142 JSFunction::EnsureFeedbackVector(isolate, function, is_compiled_scope);
3143
3144 Tagged<Code> baseline_code = shared->baseline_code(kAcquireLoad);
3145 DCHECK_EQ(baseline_code->kind(), CodeKind::BASELINE);
3146 function->UpdateCodeKeepTieringRequests(baseline_code);
3147 return true;
3148}
3149
3150// static
3152 ParseInfo* parse_info, Handle<Script> script, Isolate* isolate,
3153 IsCompiledScope* is_compiled_scope) {
3154 return v8::internal::CompileToplevel(parse_info, script, kNullMaybeHandle,
3155 isolate, is_compiled_scope);
3156}
3157
3158// static
3160 Isolate* isolate,
3161 ClearExceptionFlag flag) {
3163 "V8.FinalizeBackgroundCompileTask");
3164 RCS_SCOPE(isolate,
3165 RuntimeCallCounterId::kCompileFinalizeBackgroundCompileTask);
3166
3167 HandleScope scope(isolate);
3168
3169 if (!task->FinalizeFunction(isolate, flag)) return false;
3170
3171 DCHECK(!isolate->has_exception());
3172 return true;
3173}
3174
3175// static
3177 DirectHandle<JSFunction> function,
3178 ConcurrencyMode mode, CodeKind code_kind) {
3179 function->TraceOptimizationStatus("^%s", CodeKindToString(code_kind));
3181 DCHECK(AllowCompilation::IsAllowed(isolate));
3182
3183 if (v8_flags.stress_concurrent_inlining &&
3184 isolate->concurrent_recompilation_enabled() && IsSynchronous(mode) &&
3185 isolate->node_observer() == nullptr) {
3186 SpawnDuplicateConcurrentJobForStressTesting(isolate, function, mode,
3187 code_kind);
3188 }
3189
3190#ifdef DEBUG
3192 DCHECK_IMPLIES(code_kind == CodeKind::MAGLEV,
3193 !function->ActiveTierIsMaglev(isolate));
3194 DCHECK_IMPLIES(code_kind == CodeKind::TURBOFAN_JS,
3195 !function->ActiveTierIsTurbofan(isolate));
3196 }
3197 bool tiering_was_in_progress = function->tiering_in_progress();
3198 DCHECK_IMPLIES(tiering_was_in_progress, mode != ConcurrencyMode::kConcurrent);
3199#endif // DEBUG
3200
3202 if (GetOrCompileOptimized(isolate, function, mode, code_kind)
3203 .ToHandle(&code)) {
3204 function->UpdateOptimizedCode(isolate, *code);
3205 DCHECK_IMPLIES(v8_flags.log_function_events,
3206 function->IsLoggingRequested(isolate));
3207 } else {
3208#ifdef V8_ENABLE_LEAPTIERING
3209 // We can get here from CompileLazy when we have requested optimized code
3210 // which isn't yet ready. Without Leaptiering, we'll already have set the
3211 // function's code to the bytecode/baseline code on the SFI. However, in the
3212 // leaptiering case, we potentially need to do this now.
3213 if (!function->is_compiled(isolate)) {
3214 function->UpdateCodeKeepTieringRequests(
3215 function->shared()->GetCode(isolate));
3216 }
3217#endif // V8_ENABLE_LEAPTIERING
3218 }
3219
3220#ifdef DEBUG
3221 DCHECK(!isolate->has_exception());
3222 DCHECK(function->is_compiled(isolate));
3223 DCHECK(function->shared()->HasBytecodeArray());
3224
3225 DCHECK_IMPLIES(function->IsTieringRequestedOrInProgress() &&
3226 !function->IsLoggingRequested(isolate),
3227 function->tiering_in_progress());
3228 if (!v8_flags.always_turbofan) {
3229 // Before a maglev optimization job is started we might have to compile
3230 // bytecode. This can trigger a turbofan compilation if always_turbofan is
3231 // set. Therefore we need to skip this dcheck in that case.
3232 DCHECK_IMPLIES(!tiering_was_in_progress && function->tiering_in_progress(),
3233 function->ChecksTieringState(isolate));
3234 }
3235 DCHECK_IMPLIES(!tiering_was_in_progress && function->tiering_in_progress(),
3236 IsConcurrent(mode));
3237#endif // DEBUG
3238}
3239
3240// static
3242 ParseInfo* parse_info, Handle<Script> script,
3243 MaybeDirectHandle<ScopeInfo> outer_scope_info, Isolate* isolate) {
3244 IsCompiledScope is_compiled_scope;
3245 return v8::internal::CompileToplevel(parse_info, script, outer_scope_info,
3246 isolate, &is_compiled_scope);
3247}
3248
3249// static
3252 DirectHandle<Context> context, LanguageMode language_mode,
3253 ParseRestriction restriction, int parameters_end_pos, int eval_position,
3254 ParsingWhileDebugging parsing_while_debugging) {
3255 Isolate* isolate = context->GetIsolate();
3256
3257 // The cache lookup key needs to be aware of the separation between the
3258 // parameters and the body to prevent this valid invocation:
3259 // Function("", "function anonymous(\n/**/) {\n}");
3260 // from adding an entry that falsely approves this invalid invocation:
3261 // Function("\n/**/) {\nfunction anonymous(", "}");
3262 // The actual eval_position for indirect eval and CreateDynamicFunction
3263 // is unused (just 0), which means it's an available field to use to indicate
3264 // this separation. But to make sure we're not causing other false hits, we
3265 // negate the scope position.
3266 int eval_cache_position = eval_position;
3267 if (restriction == ONLY_SINGLE_FUNCTION_LITERAL &&
3268 parameters_end_pos != kNoSourcePosition) {
3269 // use the parameters_end_pos as the eval_position in the eval cache.
3270 DCHECK_EQ(eval_position, kNoSourcePosition);
3271 eval_cache_position = -parameters_end_pos;
3272 }
3273 CompilationCache* compilation_cache = isolate->compilation_cache();
3274 InfoCellPair eval_result = compilation_cache->LookupEval(
3275 source, outer_info, context, language_mode, eval_cache_position);
3276 DirectHandle<FeedbackCell> feedback_cell;
3277 if (eval_result.has_feedback_cell()) {
3278 feedback_cell = direct_handle(eval_result.feedback_cell(), isolate);
3279 }
3280
3283 IsCompiledScope is_compiled_scope;
3284 bool allow_eval_cache;
3285 if (eval_result.has_shared()) {
3286 shared_info =
3287 DirectHandle<SharedFunctionInfo>(eval_result.shared(), isolate);
3288 script = Handle<Script>(Cast<Script>(shared_info->script()), isolate);
3289 is_compiled_scope = shared_info->is_compiled_scope(isolate);
3290 allow_eval_cache = true;
3291 } else {
3293 isolate, true, language_mode, REPLMode::kNo, ScriptType::kClassic,
3294 v8_flags.lazy_eval);
3295 flags.set_is_eval(true);
3296 flags.set_parsing_while_debugging(parsing_while_debugging);
3297 DCHECK(!flags.is_module());
3298 flags.set_parse_restriction(restriction);
3299
3300 UnoptimizedCompileState compile_state;
3301 ReusableUnoptimizedCompileState reusable_state(isolate);
3302 ParseInfo parse_info(isolate, flags, &compile_state, &reusable_state);
3303 parse_info.set_parameters_end_pos(parameters_end_pos);
3304
3305 MaybeDirectHandle<ScopeInfo> maybe_outer_scope_info;
3306 if (!IsNativeContext(*context)) {
3307 maybe_outer_scope_info = direct_handle(context->scope_info(), isolate);
3308 }
3309 script = parse_info.CreateScript(
3310 isolate, source, kNullMaybeHandle,
3311 OriginOptionsForEval(outer_info->script(), parsing_while_debugging));
3312 script->set_eval_from_shared(*outer_info);
3313 if (eval_position == kNoSourcePosition) {
3314 // If the position is missing, attempt to get the code offset by
3315 // walking the stack. Do not translate the code offset into source
3316 // position, but store it as negative value for lazy translation.
3317 DebuggableStackFrameIterator it(isolate);
3318 if (!it.done() && it.is_javascript()) {
3319 FrameSummary summary = it.GetTopValidFrame();
3320 script->set_eval_from_shared(
3321 summary.AsJavaScript().function()->shared());
3322 script->set_origin_options(
3323 OriginOptionsForEval(*summary.script(), parsing_while_debugging));
3324 eval_position = -summary.code_offset();
3325 } else {
3326 eval_position = 0;
3327 }
3328 }
3329 script->set_eval_from_position(eval_position);
3330
3331 if (!v8::internal::CompileToplevel(&parse_info, script,
3332 maybe_outer_scope_info, isolate,
3333 &is_compiled_scope)
3334 .ToHandle(&shared_info)) {
3336 }
3337 allow_eval_cache = parse_info.allow_eval_cache();
3338 }
3339
3340 // If caller is strict mode, the result must be in strict mode as well.
3341 DCHECK(is_sloppy(language_mode) || is_strict(shared_info->language_mode()));
3342
3344 if (eval_result.has_shared()) {
3345 if (eval_result.has_feedback_cell()) {
3346 result = Factory::JSFunctionBuilder{isolate, shared_info, context}
3347 .set_feedback_cell(feedback_cell)
3349 .Build();
3350 } else {
3351 result = Factory::JSFunctionBuilder{isolate, shared_info, context}
3353 .Build();
3354 // TODO(mythria): I don't think we need this here. PostInstantiation
3355 // already initializes feedback cell.
3356 JSFunction::InitializeFeedbackCell(result, &is_compiled_scope, true);
3357 if (allow_eval_cache) {
3358 // Make sure to cache this result.
3359 DirectHandle<FeedbackCell> new_feedback_cell(
3360 result->raw_feedback_cell(), isolate);
3361 compilation_cache->PutEval(source, outer_info, context, shared_info,
3362 new_feedback_cell, eval_cache_position);
3363 }
3364 }
3365 } else {
3366 result = Factory::JSFunctionBuilder{isolate, shared_info, context}
3368 .Build();
3369 // TODO(mythria): I don't think we need this here. PostInstantiation
3370 // already initializes feedback cell.
3371 JSFunction::InitializeFeedbackCell(result, &is_compiled_scope, true);
3372 if (allow_eval_cache) {
3373 // Add the SharedFunctionInfo and the LiteralsArray to the eval cache if
3374 // we didn't retrieve from there.
3375 DirectHandle<FeedbackCell> new_feedback_cell(result->raw_feedback_cell(),
3376 isolate);
3377 compilation_cache->PutEval(source, outer_info, context, shared_info,
3378 new_feedback_cell, eval_cache_position);
3379 }
3380 }
3381 CHECK(is_compiled_scope.is_compiled());
3382
3383 return result;
3384}
3385
3386// Check whether embedder allows code generation in this context.
3387// (via v8::Isolate::SetModifyCodeGenerationFromStringsCallback)
3390 Handle<i::Object>* source,
3391 bool is_code_like) {
3392 DCHECK(isolate->modify_code_gen_callback());
3393 DCHECK(source);
3394
3395 // Callback set. Run it, and use the return value as source, or block
3396 // execution if it's not set.
3397 VMState<EXTERNAL> state(isolate);
3398 RCS_SCOPE(isolate, RuntimeCallCounterId::kCodeGenerationFromStringsCallbacks);
3400 isolate->modify_code_gen_callback()(v8::Utils::ToLocal(context),
3401 v8::Utils::ToLocal(*source),
3402 is_code_like);
3403 if (result.codegen_allowed && !result.modified_source.IsEmpty()) {
3404 // Use the new source (which might be the same as the old source).
3405 *source =
3406 Utils::OpenHandle(*result.modified_source.ToLocalChecked(), false);
3407 }
3408 return result.codegen_allowed;
3409}
3410
3411// Run Embedder-mandated checks before generating code from a string.
3412//
3413// Returns a string to be used for compilation, or a flag that an object type
3414// was encountered that is neither a string, nor something the embedder knows
3415// how to handle.
3416//
3417// Returns: (assuming: std::tie(source, unknown_object))
3418// - !source.is_null(): compilation allowed, source contains the source string.
3419// - unknown_object is true: compilation allowed, but we don't know how to
3420// deal with source_object.
3421// - source.is_null() && !unknown_object: compilation should be blocked.
3422//
3423// - !source_is_null() and unknown_object can't be true at the same time.
3424
3425// static
3426std::pair<MaybeDirectHandle<String>, bool>
3429 Handle<i::Object> original_source,
3430 bool is_code_like) {
3431 // Check if the context unconditionally allows code gen from strings.
3432 // allow_code_gen_from_strings can be many things, so we'll always check
3433 // against the 'false' literal, so that e.g. undefined and 'true' are treated
3434 // the same.
3435 if (!IsFalse(context->allow_code_gen_from_strings(), isolate) &&
3436 IsString(*original_source)) {
3437 return {Cast<String>(original_source), false};
3438 }
3439
3440 // Check if the context wants to block or modify this source object.
3441 // Double-check that we really have a string now.
3442 // (Let modify_code_gen_callback decide, if it's been set.)
3443 if (isolate->modify_code_gen_callback()) {
3444 Handle<i::Object> modified_source = original_source;
3445 if (!ModifyCodeGenerationFromStrings(isolate, context, &modified_source,
3446 is_code_like)) {
3447 return {MaybeHandle<String>(), false};
3448 }
3449 if (!IsString(*modified_source)) {
3450 return {MaybeHandle<String>(), true};
3451 }
3452 return {Cast<String>(modified_source), false};
3453 }
3454
3455 if (!IsFalse(context->allow_code_gen_from_strings(), isolate) &&
3456 Object::IsCodeLike(*original_source, isolate)) {
3457 // Codegen is unconditionally allowed, and we're been given a CodeLike
3458 // object. Stringify.
3459 MaybeHandle<String> stringified_source =
3460 Object::ToString(isolate, original_source);
3461 return {stringified_source, stringified_source.is_null()};
3462 }
3463
3464 // If unconditional codegen was disabled, and no callback defined, we block
3465 // strings and allow all other objects.
3466 return {MaybeHandle<String>(), !IsString(*original_source)};
3467}
3468
3469// static
3472 MaybeDirectHandle<String> source, ParseRestriction restriction,
3473 int parameters_end_pos) {
3474 Isolate* const isolate = native_context->GetIsolate();
3475
3476 // Raise an EvalError if we did not receive a string.
3477 if (source.is_null()) {
3478 Handle<Object> error_message =
3479 native_context->ErrorMessageForCodeGenerationFromStrings();
3480 THROW_NEW_ERROR(isolate, NewEvalError(MessageTemplate::kCodeGenFromStrings,
3481 error_message));
3482 }
3483
3484 // Compile source string in the native context.
3485 int eval_position = kNoSourcePosition;
3487 native_context->empty_function()->shared(), isolate);
3489 source.ToHandleChecked(), outer_info, native_context,
3490 LanguageMode::kSloppy, restriction, parameters_end_pos, eval_position);
3491}
3492
3493// static
3496 int parameters_end_pos, bool is_code_like) {
3497 Isolate* const isolate = context->GetIsolate();
3498 MaybeDirectHandle<String> validated_source =
3499 ValidateDynamicCompilationSource(isolate, context, source, is_code_like)
3500 .first;
3501 return GetFunctionFromValidatedString(context, validated_source,
3503 parameters_end_pos);
3504}
3505
3506namespace {
3507
3508struct ScriptCompileTimerScope {
3509 public:
3510 // TODO(leszeks): There are too many blink-specific entries in this enum,
3511 // figure out a way to push produce/hit-isolate-cache/consume/consume-failed
3512 // back up the API and log them in blink instead.
3513 enum class CacheBehaviour {
3514 kProduceCodeCache,
3515 kHitIsolateCacheWhenNoCache,
3516 kConsumeCodeCache,
3517 kConsumeCodeCacheFailed,
3518 kNoCacheBecauseInlineScript,
3519 kNoCacheBecauseScriptTooSmall,
3520 kNoCacheBecauseCacheTooCold,
3521 kNoCacheNoReason,
3522 kNoCacheBecauseNoResource,
3523 kNoCacheBecauseInspector,
3524 kNoCacheBecauseCachingDisabled,
3525 kNoCacheBecauseModule,
3526 kNoCacheBecauseStreamingSource,
3527 kNoCacheBecauseV8Extension,
3528 kHitIsolateCacheWhenProduceCodeCache,
3529 kHitIsolateCacheWhenConsumeCodeCache,
3530 kNoCacheBecauseExtensionModule,
3531 kNoCacheBecausePacScript,
3532 kNoCacheBecauseInDocumentWrite,
3533 kNoCacheBecauseResourceWithNoCacheHandler,
3534 kHitIsolateCacheWhenStreamingSource,
3535 kNoCacheBecauseStaticCodeCache,
3536 kCount
3537 };
3538
3539 ScriptCompileTimerScope(
3540 Isolate* isolate, ScriptCompiler::NoCacheReason no_cache_reason,
3541 ScriptCompiler::CompilationDetails* compilation_details)
3542 : isolate_(isolate),
3543 histogram_scope_(&compilation_details->foreground_time_in_microseconds),
3544 all_scripts_histogram_scope_(isolate->counters()->compile_script()),
3545 no_cache_reason_(no_cache_reason),
3546 hit_isolate_cache_(false),
3547 consuming_code_cache_(false),
3549
3550 ~ScriptCompileTimerScope() {
3551 CacheBehaviour cache_behaviour = GetCacheBehaviour();
3552
3553 Histogram* cache_behaviour_histogram =
3554 isolate_->counters()->compile_script_cache_behaviour();
3555 // Sanity check that the histogram has exactly one bin per enum entry.
3556 DCHECK_EQ(0, cache_behaviour_histogram->min());
3557 DCHECK_EQ(static_cast<int>(CacheBehaviour::kCount),
3558 cache_behaviour_histogram->max() + 1);
3559 DCHECK_EQ(static_cast<int>(CacheBehaviour::kCount),
3560 cache_behaviour_histogram->num_buckets());
3561 cache_behaviour_histogram->AddSample(static_cast<int>(cache_behaviour));
3562
3563 histogram_scope_.set_histogram(
3564 GetCacheBehaviourTimedHistogram(cache_behaviour));
3565 }
3566
3567 void set_hit_isolate_cache() { hit_isolate_cache_ = true; }
3568
3569 void set_consuming_code_cache() { consuming_code_cache_ = true; }
3570
3571 void set_consuming_code_cache_failed() {
3573 }
3574
3575 private:
3576 Isolate* isolate_;
3577 LazyTimedHistogramScope histogram_scope_;
3578 // TODO(leszeks): This timer is the sum of the other times, consider removing
3579 // it to save space.
3580 NestedTimedHistogramScope all_scripts_histogram_scope_;
3581 ScriptCompiler::NoCacheReason no_cache_reason_;
3585
3586 CacheBehaviour GetCacheBehaviour() {
3588 if (hit_isolate_cache_) {
3589 return CacheBehaviour::kHitIsolateCacheWhenConsumeCodeCache;
3590 } else if (consuming_code_cache_failed_) {
3591 return CacheBehaviour::kConsumeCodeCacheFailed;
3592 }
3593 return CacheBehaviour::kConsumeCodeCache;
3594 }
3595
3596 if (hit_isolate_cache_) {
3597 // A roundabout way of knowing the embedder is going to produce a code
3598 // cache (which is done by a separate API call later) is to check whether
3599 // no_cache_reason_ is
3600 // ScriptCompiler::kNoCacheBecauseDeferredProduceCodeCache.
3601 if (no_cache_reason_ ==
3602 ScriptCompiler::kNoCacheBecauseDeferredProduceCodeCache) {
3603 return CacheBehaviour::kHitIsolateCacheWhenProduceCodeCache;
3604 } else if (no_cache_reason_ ==
3605 ScriptCompiler::kNoCacheBecauseStreamingSource) {
3606 return CacheBehaviour::kHitIsolateCacheWhenStreamingSource;
3607 }
3608 return CacheBehaviour::kHitIsolateCacheWhenNoCache;
3609 }
3610
3611 switch (no_cache_reason_) {
3612 case ScriptCompiler::kNoCacheBecauseInlineScript:
3613 return CacheBehaviour::kNoCacheBecauseInlineScript;
3614 case ScriptCompiler::kNoCacheBecauseScriptTooSmall:
3615 return CacheBehaviour::kNoCacheBecauseScriptTooSmall;
3616 case ScriptCompiler::kNoCacheBecauseCacheTooCold:
3617 return CacheBehaviour::kNoCacheBecauseCacheTooCold;
3618 case ScriptCompiler::kNoCacheNoReason:
3619 return CacheBehaviour::kNoCacheNoReason;
3620 case ScriptCompiler::kNoCacheBecauseNoResource:
3621 return CacheBehaviour::kNoCacheBecauseNoResource;
3622 case ScriptCompiler::kNoCacheBecauseInspector:
3623 return CacheBehaviour::kNoCacheBecauseInspector;
3624 case ScriptCompiler::kNoCacheBecauseCachingDisabled:
3625 return CacheBehaviour::kNoCacheBecauseCachingDisabled;
3626 case ScriptCompiler::kNoCacheBecauseModule:
3627 return CacheBehaviour::kNoCacheBecauseModule;
3628 case ScriptCompiler::kNoCacheBecauseStreamingSource:
3629 return CacheBehaviour::kNoCacheBecauseStreamingSource;
3630 case ScriptCompiler::kNoCacheBecauseV8Extension:
3631 return CacheBehaviour::kNoCacheBecauseV8Extension;
3632 case ScriptCompiler::kNoCacheBecauseExtensionModule:
3633 return CacheBehaviour::kNoCacheBecauseExtensionModule;
3634 case ScriptCompiler::kNoCacheBecausePacScript:
3635 return CacheBehaviour::kNoCacheBecausePacScript;
3636 case ScriptCompiler::kNoCacheBecauseInDocumentWrite:
3637 return CacheBehaviour::kNoCacheBecauseInDocumentWrite;
3638 case ScriptCompiler::kNoCacheBecauseResourceWithNoCacheHandler:
3639 return CacheBehaviour::kNoCacheBecauseResourceWithNoCacheHandler;
3640 case ScriptCompiler::kNoCacheBecauseDeferredProduceCodeCache:
3641 return CacheBehaviour::kProduceCodeCache;
3642 case ScriptCompiler::kNoCacheBecauseStaticCodeCache:
3643 return CacheBehaviour::kNoCacheBecauseStaticCodeCache;
3644 }
3645 UNREACHABLE();
3646 }
3647
3648 TimedHistogram* GetCacheBehaviourTimedHistogram(
3649 CacheBehaviour cache_behaviour) {
3650 switch (cache_behaviour) {
3651 case CacheBehaviour::kProduceCodeCache:
3652 // Even if we hit the isolate's compilation cache, we currently recompile
3653 // when we want to produce the code cache.
3654 case CacheBehaviour::kHitIsolateCacheWhenProduceCodeCache:
3655 return isolate_->counters()->compile_script_with_produce_cache();
3656 case CacheBehaviour::kHitIsolateCacheWhenNoCache:
3657 case CacheBehaviour::kHitIsolateCacheWhenConsumeCodeCache:
3658 case CacheBehaviour::kHitIsolateCacheWhenStreamingSource:
3659 return isolate_->counters()->compile_script_with_isolate_cache_hit();
3660 case CacheBehaviour::kConsumeCodeCacheFailed:
3661 return isolate_->counters()->compile_script_consume_failed();
3662 case CacheBehaviour::kConsumeCodeCache:
3663 return isolate_->counters()->compile_script_with_consume_cache();
3664
3665 // Note that this only counts the finalization part of streaming, the
3666 // actual streaming compile is counted by BackgroundCompileTask into
3667 // "compile_script_on_background".
3668 case CacheBehaviour::kNoCacheBecauseStreamingSource:
3669 return isolate_->counters()->compile_script_streaming_finalization();
3670
3671 case CacheBehaviour::kNoCacheBecauseInlineScript:
3672 return isolate_->counters()
3673 ->compile_script_no_cache_because_inline_script();
3674 case CacheBehaviour::kNoCacheBecauseScriptTooSmall:
3675 return isolate_->counters()
3676 ->compile_script_no_cache_because_script_too_small();
3677 case CacheBehaviour::kNoCacheBecauseCacheTooCold:
3678 return isolate_->counters()
3679 ->compile_script_no_cache_because_cache_too_cold();
3680
3681 // Aggregate all the other "no cache" counters into a single histogram, to
3682 // save space.
3683 case CacheBehaviour::kNoCacheNoReason:
3684 case CacheBehaviour::kNoCacheBecauseNoResource:
3685 case CacheBehaviour::kNoCacheBecauseInspector:
3686 case CacheBehaviour::kNoCacheBecauseCachingDisabled:
3687 // TODO(leszeks): Consider counting separately once modules are more
3688 // common.
3689 case CacheBehaviour::kNoCacheBecauseModule:
3690 case CacheBehaviour::kNoCacheBecauseV8Extension:
3691 case CacheBehaviour::kNoCacheBecauseExtensionModule:
3692 case CacheBehaviour::kNoCacheBecausePacScript:
3693 case CacheBehaviour::kNoCacheBecauseInDocumentWrite:
3694 case CacheBehaviour::kNoCacheBecauseResourceWithNoCacheHandler:
3695 case CacheBehaviour::kNoCacheBecauseStaticCodeCache:
3696 return isolate_->counters()->compile_script_no_cache_other();
3697
3698 case CacheBehaviour::kCount:
3699 UNREACHABLE();
3700 }
3701 UNREACHABLE();
3702 }
3703};
3704
3705Handle<Script> NewScript(Isolate* isolate, ParseInfo* parse_info,
3706 DirectHandle<String> source,
3707 ScriptDetails script_details, NativesFlag natives) {
3708 // Create a script object describing the script to be compiled.
3709 Handle<Script> script = parse_info->CreateScript(
3710 isolate, source, script_details.wrapped_arguments,
3711 script_details.origin_options, natives);
3713 SetScriptFieldsFromDetails(isolate, *script, script_details, &no_gc);
3714 LOG(isolate, ScriptDetails(*script));
3715 return script;
3716}
3717
3718MaybeDirectHandle<SharedFunctionInfo> CompileScriptOnMainThread(
3719 const UnoptimizedCompileFlags flags, DirectHandle<String> source,
3720 const ScriptDetails& script_details, NativesFlag natives,
3721 v8::Extension* extension, Isolate* isolate,
3722 MaybeHandle<Script> maybe_script, IsCompiledScope* is_compiled_scope,
3723 CompileHintCallback compile_hint_callback = nullptr,
3724 void* compile_hint_callback_data = nullptr) {
3725 UnoptimizedCompileState compile_state;
3726 ReusableUnoptimizedCompileState reusable_state(isolate);
3727 ParseInfo parse_info(isolate, flags, &compile_state, &reusable_state);
3728 parse_info.set_extension(extension);
3729 parse_info.SetCompileHintCallbackAndData(compile_hint_callback,
3730 compile_hint_callback_data);
3731
3733 if (!maybe_script.ToHandle(&script)) {
3734 script = NewScript(isolate, &parse_info, source, script_details, natives);
3735 }
3736 DCHECK_EQ(parse_info.flags().is_repl_mode(), script->is_repl_mode());
3737
3738 return Compiler::CompileToplevel(&parse_info, script, isolate,
3739 is_compiled_scope);
3740}
3741
3742class StressBackgroundCompileThread : public ParkingThread {
3743 public:
3744 StressBackgroundCompileThread(Isolate* isolate, Handle<String> source,
3745 const ScriptDetails& script_details)
3746 : ParkingThread(
3747 base::Thread::Options("StressBackgroundCompileThread", 2 * i::MB)),
3748 source_(source),
3749 streamed_source_(std::make_unique<SourceStream>(source, isolate),
3750 v8::ScriptCompiler::StreamedSource::TWO_BYTE) {
3751 ScriptType type = script_details.origin_options.IsModule()
3752 ? ScriptType::kModule
3753 : ScriptType::kClassic;
3754 data()->task = std::make_unique<i::BackgroundCompileTask>(
3755 data(), isolate, type,
3756 ScriptCompiler::CompileOptions::kNoCompileOptions,
3758 }
3759
3760 void Run() override { data()->task->Run(); }
3761
3762 ScriptStreamingData* data() { return streamed_source_.impl(); }
3763
3764 private:
3765 // Dummy external source stream which returns the whole source in one go.
3766 // TODO(leszeks): Also test chunking the data.
3767 class SourceStream : public v8::ScriptCompiler::ExternalSourceStream {
3768 public:
3769 SourceStream(DirectHandle<String> source, Isolate* isolate) : done_(false) {
3770 source_length_ = source->length();
3771 source_buffer_ = std::make_unique<uint16_t[]>(source_length_);
3772 String::WriteToFlat(*source, source_buffer_.get(), 0, source_length_);
3773 }
3774
3775 size_t GetMoreData(const uint8_t** src) override {
3776 if (done_) {
3777 return 0;
3778 }
3779 *src = reinterpret_cast<uint8_t*>(source_buffer_.release());
3780 done_ = true;
3781
3782 return source_length_ * 2;
3783 }
3784
3785 private:
3787 std::unique_ptr<uint16_t[]> source_buffer_;
3788 bool done_;
3789 };
3790
3791 Handle<String> source_;
3793};
3794
3795bool CanBackgroundCompile(const ScriptDetails& script_details,
3797 ScriptCompiler::CompileOptions compile_options,
3798 NativesFlag natives) {
3799 // TODO(leszeks): Remove the module check once background compilation of
3800 // modules is supported.
3801 return !script_details.origin_options.IsModule() && !extension &&
3802 script_details.repl_mode == REPLMode::kNo &&
3803 (compile_options == ScriptCompiler::kNoCompileOptions) &&
3804 natives == NOT_NATIVES_CODE;
3805}
3806
3807bool CompilationExceptionIsRangeError(Isolate* isolate,
3808 DirectHandle<Object> obj) {
3809 if (!IsJSError(*obj, isolate)) return false;
3810 DirectHandle<JSReceiver> js_obj = Cast<JSReceiver>(obj);
3811 DirectHandle<JSReceiver> constructor;
3812 if (!JSReceiver::GetConstructor(isolate, js_obj).ToHandle(&constructor)) {
3813 return false;
3814 }
3815 return *constructor == *isolate->range_error_function();
3816}
3817
3818MaybeDirectHandle<SharedFunctionInfo>
3819CompileScriptOnBothBackgroundAndMainThread(Handle<String> source,
3820 const ScriptDetails& script_details,
3821 Isolate* isolate,
3822 IsCompiledScope* is_compiled_scope) {
3823 // Start a background thread compiling the script.
3824 StressBackgroundCompileThread background_compile_thread(isolate, source,
3825 script_details);
3826
3827 UnoptimizedCompileFlags flags_copy =
3828 background_compile_thread.data()->task->flags();
3829
3830 CHECK(background_compile_thread.Start());
3831 MaybeDirectHandle<SharedFunctionInfo> main_thread_maybe_result;
3832 bool main_thread_had_stack_overflow = false;
3833 // In parallel, compile on the main thread to flush out any data races.
3834 {
3835 IsCompiledScope inner_is_compiled_scope;
3836 // The background thread should also create any relevant exceptions, so we
3837 // can ignore the main-thread created ones.
3838 // TODO(leszeks): Maybe verify that any thrown (or unthrown) exceptions are
3839 // equivalent.
3840 TryCatch ignore_try_catch(reinterpret_cast<v8::Isolate*>(isolate));
3841 flags_copy.set_script_id(Script::kTemporaryScriptId);
3842 main_thread_maybe_result = CompileScriptOnMainThread(
3843 flags_copy, source, script_details, NOT_NATIVES_CODE, nullptr, isolate,
3844 MaybeHandle<Script>(), &inner_is_compiled_scope);
3845 if (main_thread_maybe_result.is_null()) {
3846 // Assume all range errors are stack overflows.
3847 main_thread_had_stack_overflow = CompilationExceptionIsRangeError(
3848 isolate, direct_handle(isolate->exception(), isolate));
3849 isolate->clear_exception();
3850 }
3851 }
3852
3853 // Join with background thread and finalize compilation.
3854 background_compile_thread.ParkedJoin(isolate->main_thread_local_isolate());
3855
3856 ScriptCompiler::CompilationDetails compilation_details;
3857 MaybeDirectHandle<SharedFunctionInfo> maybe_result =
3859 isolate, source, script_details, background_compile_thread.data(),
3860 &compilation_details);
3861
3862 // Either both compiles should succeed, or both should fail. The one exception
3863 // to this is that the main-thread compilation might stack overflow while the
3864 // background compilation doesn't, so relax the check to include this case.
3865 // TODO(leszeks): Compare the contents of the results of the two compiles.
3866 if (main_thread_had_stack_overflow) {
3867 CHECK(main_thread_maybe_result.is_null());
3868 } else {
3869 CHECK_EQ(maybe_result.is_null(), main_thread_maybe_result.is_null());
3870 }
3871
3872 DirectHandle<SharedFunctionInfo> result;
3873 if (maybe_result.ToHandle(&result)) {
3874 // The BackgroundCompileTask's IsCompiledScope will keep the result alive
3875 // until it dies at the end of this function, after which this new
3876 // IsCompiledScope can take over.
3877 *is_compiled_scope = result->is_compiled_scope(isolate);
3878 }
3879
3880 return maybe_result;
3881}
3882
3883namespace {
3884ScriptCompiler::InMemoryCacheResult CategorizeLookupResult(
3885 const CompilationCacheScript::LookupResult& lookup_result) {
3886 return !lookup_result.toplevel_sfi().is_null()
3888 : !lookup_result.script().is_null()
3891}
3892} // namespace
3893
3894MaybeDirectHandle<SharedFunctionInfo> GetSharedFunctionInfoForScriptImpl(
3895 Isolate* isolate, Handle<String> source,
3896 const ScriptDetails& script_details, v8::Extension* extension,
3897 AlignedCachedData* cached_data, BackgroundDeserializeTask* deserialize_task,
3898 v8::CompileHintCallback compile_hint_callback,
3899 void* compile_hint_callback_data,
3900 ScriptCompiler::CompileOptions compile_options,
3901 ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag natives,
3902 ScriptCompiler::CompilationDetails* compilation_details) {
3903 ScriptCompileTimerScope compile_timer(isolate, no_cache_reason,
3904 compilation_details);
3905
3906 if (compile_options & ScriptCompiler::kConsumeCodeCache) {
3907 // Have to have exactly one of cached_data or deserialize_task.
3908 DCHECK(cached_data || deserialize_task);
3909 DCHECK(!(cached_data && deserialize_task));
3911 } else {
3912 DCHECK_NULL(cached_data);
3913 DCHECK_NULL(deserialize_task);
3914 }
3915
3916 if (compile_options & ScriptCompiler::kConsumeCompileHints) {
3917 DCHECK_NOT_NULL(compile_hint_callback);
3918 DCHECK_NOT_NULL(compile_hint_callback_data);
3919 } else {
3920 DCHECK_NULL(compile_hint_callback);
3921 DCHECK_NULL(compile_hint_callback_data);
3922 }
3923
3924 compilation_details->background_time_in_microseconds =
3925 deserialize_task ? deserialize_task->background_time_in_microseconds()
3926 : 0;
3927
3928 LanguageMode language_mode = construct_language_mode(v8_flags.use_strict);
3929 CompilationCache* compilation_cache = isolate->compilation_cache();
3930
3931 // For extensions or REPL mode scripts neither do a compilation cache lookup,
3932 // nor put the compilation result back into the cache.
3933 const bool use_compilation_cache =
3934 extension == nullptr && script_details.repl_mode == REPLMode::kNo;
3935 MaybeDirectHandle<SharedFunctionInfo> maybe_result;
3936 MaybeHandle<Script> maybe_script;
3937 IsCompiledScope is_compiled_scope;
3938 if (use_compilation_cache) {
3939 bool can_consume_code_cache =
3940 compile_options & ScriptCompiler::kConsumeCodeCache;
3941 if (can_consume_code_cache) {
3942 compile_timer.set_consuming_code_cache();
3943 }
3944
3945 // First check per-isolate compilation cache.
3947 compilation_cache->LookupScript(source, script_details, language_mode);
3948 compilation_details->in_memory_cache_result =
3949 CategorizeLookupResult(lookup_result);
3950 maybe_script = lookup_result.script();
3951 maybe_result = lookup_result.toplevel_sfi();
3952 is_compiled_scope = lookup_result.is_compiled_scope();
3953 if (!maybe_result.is_null()) {
3954 compile_timer.set_hit_isolate_cache();
3955 } else if (can_consume_code_cache) {
3956 compile_timer.set_consuming_code_cache();
3957 // Then check cached code provided by embedder.
3958 NestedTimedHistogramScope timer(
3959 isolate->counters()->compile_deserialize());
3960 RCS_SCOPE(isolate, RuntimeCallCounterId::kCompileDeserialize);
3962 "V8.CompileDeserialize");
3963 if (deserialize_task) {
3964 // If there's a cache consume task, finish it.
3965 maybe_result =
3966 deserialize_task->Finish(isolate, source, script_details);
3967 // It is possible at this point that there is a Script object for this
3968 // script in the compilation cache (held in the variable maybe_script),
3969 // which does not match maybe_result->script(). This could happen any of
3970 // three ways:
3971 // 1. The embedder didn't call MergeWithExistingScript.
3972 // 2. At the time the embedder called SourceTextAvailable, there was not
3973 // yet a Script in the compilation cache, but it arrived sometime
3974 // later.
3975 // 3. At the time the embedder called SourceTextAvailable, there was a
3976 // Script available, and the new content has been merged into that
3977 // Script. However, since then, the Script was replaced in the
3978 // compilation cache, such as by another evaluation of the script
3979 // hitting case 2, or DevTools clearing the cache.
3980 // This is okay; the new Script object will replace the current Script
3981 // held by the compilation cache. Both Scripts may remain in use
3982 // indefinitely, causing increased memory usage, but these cases are
3983 // sufficiently unlikely, and ensuring a correct merge in the third case
3984 // would be non-trivial.
3985 } else {
3986 maybe_result = CodeSerializer::Deserialize(
3987 isolate, cached_data, source, script_details, maybe_script);
3988 }
3989
3990 bool consuming_code_cache_succeeded = false;
3991 DirectHandle<SharedFunctionInfo> result;
3992 if (maybe_result.ToHandle(&result)) {
3993 is_compiled_scope = result->is_compiled_scope(isolate);
3994 if (is_compiled_scope.is_compiled()) {
3995 consuming_code_cache_succeeded = true;
3996 // Promote to per-isolate compilation cache.
3997 compilation_cache->PutScript(source, language_mode, result);
3998 }
3999 }
4000 if (!consuming_code_cache_succeeded) {
4001 // Deserializer failed. Fall through to compile.
4002 compile_timer.set_consuming_code_cache_failed();
4003 }
4004 }
4005 }
4006
4007 if (maybe_result.is_null()) {
4008 // No cache entry found compile the script.
4009 if (v8_flags.stress_background_compile &&
4010 CanBackgroundCompile(script_details, extension, compile_options,
4011 natives)) {
4012 // If the --stress-background-compile flag is set, do the actual
4013 // compilation on a background thread, and wait for its result.
4014 maybe_result = CompileScriptOnBothBackgroundAndMainThread(
4015 source, script_details, isolate, &is_compiled_scope);
4016 } else {
4017 UnoptimizedCompileFlags flags =
4019 isolate, natives == NOT_NATIVES_CODE, language_mode,
4020 script_details.repl_mode,
4021 script_details.origin_options.IsModule() ? ScriptType::kModule
4023 v8_flags.lazy);
4024
4025 flags.set_is_eager(compile_options & ScriptCompiler::kEagerCompile);
4026 flags.set_compile_hints_magic_enabled(
4028 flags.set_compile_hints_per_function_magic_enabled(
4029 compile_options &
4031
4032 if (DirectHandle<Script> script; maybe_script.ToHandle(&script)) {
4033 flags.set_script_id(script->id());
4034 }
4035
4036 maybe_result = CompileScriptOnMainThread(
4037 flags, source, script_details, natives, extension, isolate,
4038 maybe_script, &is_compiled_scope, compile_hint_callback,
4039 compile_hint_callback_data);
4040 }
4041
4042 // Add the result to the isolate cache.
4043 DirectHandle<SharedFunctionInfo> result;
4044 if (use_compilation_cache && maybe_result.ToHandle(&result)) {
4045 DCHECK(is_compiled_scope.is_compiled());
4046 compilation_cache->PutScript(source, language_mode, result);
4047 } else if (maybe_result.is_null() && natives != EXTENSION_CODE) {
4048 isolate->ReportPendingMessages();
4049 }
4050 }
4051 DirectHandle<SharedFunctionInfo> result;
4053 maybe_result.ToHandle(&result)) {
4054 Cast<Script>(result->script())->set_produce_compile_hints(true);
4055 }
4056
4057 return maybe_result;
4058}
4059
4060} // namespace
4061
4063 Isolate* isolate, Handle<String> source,
4064 const ScriptDetails& script_details,
4065 ScriptCompiler::CompileOptions compile_options,
4066 ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag natives,
4067 ScriptCompiler::CompilationDetails* compilation_details) {
4068 return GetSharedFunctionInfoForScriptImpl(
4069 isolate, source, script_details, nullptr, nullptr, nullptr, nullptr,
4070 nullptr, compile_options, no_cache_reason, natives, compilation_details);
4071}
4072
4075 Isolate* isolate, Handle<String> source,
4076 const ScriptDetails& script_details, v8::Extension* extension,
4077 ScriptCompiler::CompileOptions compile_options, NativesFlag natives,
4078 ScriptCompiler::CompilationDetails* compilation_details) {
4079 return GetSharedFunctionInfoForScriptImpl(
4080 isolate, source, script_details, extension, nullptr, nullptr, nullptr,
4081 nullptr, compile_options, ScriptCompiler::kNoCacheBecauseV8Extension,
4082 natives, compilation_details);
4083}
4084
4087 Isolate* isolate, Handle<String> source,
4088 const ScriptDetails& script_details, AlignedCachedData* cached_data,
4089 ScriptCompiler::CompileOptions compile_options,
4090 ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag natives,
4091 ScriptCompiler::CompilationDetails* compilation_details) {
4092 return GetSharedFunctionInfoForScriptImpl(
4093 isolate, source, script_details, nullptr, cached_data, nullptr, nullptr,
4094 nullptr, compile_options, no_cache_reason, natives, compilation_details);
4095}
4096
4099 Isolate* isolate, Handle<String> source,
4100 const ScriptDetails& script_details,
4101 BackgroundDeserializeTask* deserialize_task,
4102 ScriptCompiler::CompileOptions compile_options,
4103 ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag natives,
4104 ScriptCompiler::CompilationDetails* compilation_details) {
4105 return GetSharedFunctionInfoForScriptImpl(
4106 isolate, source, script_details, nullptr, nullptr, deserialize_task,
4107 nullptr, nullptr, compile_options, no_cache_reason, natives,
4108 compilation_details);
4109}
4110
4113 Isolate* isolate, Handle<String> source,
4114 const ScriptDetails& script_details,
4115 v8::CompileHintCallback compile_hint_callback,
4116 void* compile_hint_callback_data,
4117 ScriptCompiler::CompileOptions compile_options,
4118 ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag natives,
4119 ScriptCompiler::CompilationDetails* compilation_details) {
4120 return GetSharedFunctionInfoForScriptImpl(
4121 isolate, source, script_details, nullptr, nullptr, nullptr,
4122 compile_hint_callback, compile_hint_callback_data, compile_options,
4123 no_cache_reason, natives, compilation_details);
4124}
4125
4126// static
4128 Handle<String> source, DirectHandle<Context> context,
4129 const ScriptDetails& script_details, AlignedCachedData* cached_data,
4130 v8::ScriptCompiler::CompileOptions compile_options,
4131 v8::ScriptCompiler::NoCacheReason no_cache_reason) {
4132 Isolate* isolate = context->GetIsolate();
4133 ScriptCompiler::CompilationDetails compilation_details;
4134 ScriptCompileTimerScope compile_timer(isolate, no_cache_reason,
4135 &compilation_details);
4136
4137 if (compile_options & ScriptCompiler::kConsumeCodeCache) {
4138 DCHECK(cached_data);
4139 DCHECK_EQ(script_details.repl_mode, REPLMode::kNo);
4140 } else {
4141 DCHECK_NULL(cached_data);
4142 }
4143
4144 LanguageMode language_mode = construct_language_mode(v8_flags.use_strict);
4145 DCHECK(!script_details.wrapped_arguments.is_null());
4149 IsCompiledScope is_compiled_scope;
4150 bool can_consume_code_cache =
4151 compile_options & ScriptCompiler::kConsumeCodeCache;
4152 CompilationCache* compilation_cache = isolate->compilation_cache();
4153 // First check per-isolate compilation cache.
4155 compilation_cache->LookupScript(source, script_details, language_mode);
4156 maybe_result = lookup_result.toplevel_sfi();
4157 if (maybe_result.ToHandle(&result)) {
4158 is_compiled_scope = result->is_compiled_scope(isolate);
4159 compile_timer.set_hit_isolate_cache();
4160 } else if (can_consume_code_cache) {
4161 compile_timer.set_consuming_code_cache();
4162 // Then check cached code provided by embedder.
4163 NestedTimedHistogramScope timer(isolate->counters()->compile_deserialize());
4164 RCS_SCOPE(isolate, RuntimeCallCounterId::kCompileDeserialize);
4166 "V8.CompileDeserialize");
4167 maybe_result = CodeSerializer::Deserialize(isolate, cached_data, source,
4168 script_details);
4169 bool consuming_code_cache_succeeded = false;
4170 if (maybe_result.ToHandle(&result)) {
4171 is_compiled_scope = result->is_compiled_scope(isolate);
4172 if (is_compiled_scope.is_compiled()) {
4173 consuming_code_cache_succeeded = true;
4174 // Promote to per-isolate compilation cache.
4175 compilation_cache->PutScript(source, language_mode, result);
4176 }
4177 }
4178 if (!consuming_code_cache_succeeded) {
4179 // Deserializer failed. Fall through to compile.
4180 compile_timer.set_consuming_code_cache_failed();
4181 }
4182 }
4183
4184 if (maybe_result.is_null()) {
4186 isolate, true, language_mode, script_details.repl_mode,
4188 flags.set_is_eval(true); // Use an eval scope as declaration scope.
4189 flags.set_function_syntax_kind(FunctionSyntaxKind::kWrapped);
4190 // TODO(delphick): Remove this and instead make the wrapped and wrapper
4191 // functions fully non-lazy instead thus preventing source positions from
4192 // being omitted.
4193 flags.set_collect_source_positions(true);
4194 flags.set_is_eager(compile_options & ScriptCompiler::kEagerCompile);
4195
4196 UnoptimizedCompileState compile_state;
4197 ReusableUnoptimizedCompileState reusable_state(isolate);
4198 ParseInfo parse_info(isolate, flags, &compile_state, &reusable_state);
4199
4200 MaybeDirectHandle<ScopeInfo> maybe_outer_scope_info;
4201 if (!IsNativeContext(*context)) {
4202 maybe_outer_scope_info = direct_handle(context->scope_info(), isolate);
4203 }
4204 script = NewScript(isolate, &parse_info, source, script_details,
4206
4208 maybe_result = v8::internal::CompileToplevel(&parse_info, script,
4209 maybe_outer_scope_info,
4210 isolate, &is_compiled_scope);
4211 if (maybe_result.is_null()) isolate->ReportPendingMessages();
4212 ASSIGN_RETURN_ON_EXCEPTION(isolate, top_level, maybe_result);
4213
4214 SharedFunctionInfo::ScriptIterator infos(isolate, *script);
4215 for (Tagged<SharedFunctionInfo> info = infos.Next(); !info.is_null();
4216 info = infos.Next()) {
4217 if (info->is_wrapped()) {
4218 result = direct_handle(info, isolate);
4219 break;
4220 }
4221 }
4222 DCHECK(!result.is_null());
4223
4224 is_compiled_scope = result->is_compiled_scope(isolate);
4225 script = Handle<Script>(Cast<Script>(result->script()), isolate);
4226 // Add the result to the isolate cache if there's no context extension.
4227 if (maybe_outer_scope_info.is_null()) {
4228 compilation_cache->PutScript(source, language_mode, result);
4229 }
4230 }
4231
4232 DCHECK(is_compiled_scope.is_compiled());
4233
4234 return Factory::JSFunctionBuilder{isolate, result, context}
4236 .Build();
4237}
4238
4239// static
4242 Isolate* isolate, Handle<String> source,
4243 const ScriptDetails& script_details, ScriptStreamingData* streaming_data,
4244 ScriptCompiler::CompilationDetails* compilation_details) {
4245 DCHECK(!script_details.origin_options.IsWasm());
4246
4247 ScriptCompileTimerScope compile_timer(
4249 compilation_details);
4250 PostponeInterruptsScope postpone(isolate);
4251
4252 BackgroundCompileTask* task = streaming_data->task.get();
4253
4255 MaybeDirectHandle<Script> maybe_cached_script;
4256 // Check if compile cache already holds the SFI, if so no need to finalize
4257 // the code compiled on the background thread.
4258 CompilationCache* compilation_cache = isolate->compilation_cache();
4259 {
4261 "V8.StreamingFinalization.CheckCache");
4263 compilation_cache->LookupScript(source, script_details,
4264 task->flags().outer_language_mode());
4265 compilation_details->in_memory_cache_result =
4266 CategorizeLookupResult(lookup_result);
4267
4268 if (!lookup_result.toplevel_sfi().is_null()) {
4269 maybe_result = lookup_result.toplevel_sfi();
4270 }
4271
4272 if (!maybe_result.is_null()) {
4273 compile_timer.set_hit_isolate_cache();
4274 } else {
4275 maybe_cached_script = lookup_result.script();
4276 }
4277 }
4278
4279 if (maybe_result.is_null()) {
4280 // No cache entry found, finalize compilation of the script and add it to
4281 // the isolate cache.
4282 RCS_SCOPE(isolate,
4283 RuntimeCallCounterId::kCompilePublishBackgroundFinalization);
4285 "V8.OffThreadFinalization.Publish");
4286
4287 maybe_result = task->FinalizeScript(isolate, source, script_details,
4288 maybe_cached_script);
4289
4291 if (maybe_result.ToHandle(&result)) {
4292 if (task->flags().produce_compile_hints()) {
4293 Cast<Script>(result->script())->set_produce_compile_hints(true);
4294 }
4295
4296 // Add compiled code to the isolate cache.
4298 "V8.StreamingFinalization.AddToCache");
4299 compilation_cache->PutScript(source, task->flags().outer_language_mode(),
4300 result);
4301 }
4302 }
4303
4305 "V8.StreamingFinalization.Release");
4306 streaming_data->Release();
4307 return maybe_result;
4308} // namespace internal
4309
4310// static
4311template <typename IsolateT>
4313 FunctionLiteral* literal, DirectHandle<Script> script, IsolateT* isolate) {
4314 // If we're parallel compiling functions, we might already have attached a SFI
4315 // to this literal.
4316 if (!literal->shared_function_info().is_null()) {
4317 return literal->shared_function_info();
4318 }
4319 // Precondition: code has been parsed and scopes have been analyzed.
4321
4322 // Find any previously allocated shared function info for the given literal.
4323 maybe_existing = Script::FindSharedFunctionInfo(script, isolate, literal);
4324
4325 // If we found an existing shared function info, return it.
4327 if (maybe_existing.ToHandle(&existing)) {
4328 // If the function has been uncompiled (bytecode flushed) it will have lost
4329 // any preparsed data. If we produced preparsed data during this compile for
4330 // this function, replace the uncompiled data with one that includes it.
4331 if (literal->produced_preparse_data() != nullptr &&
4332 existing->HasUncompiledDataWithoutPreparseData()) {
4333 DirectHandle<UncompiledData> existing_uncompiled_data(
4334 existing->uncompiled_data(isolate), isolate);
4335 DCHECK_EQ(literal->start_position(),
4336 existing_uncompiled_data->start_position());
4337 DCHECK_EQ(literal->end_position(),
4338 existing_uncompiled_data->end_position());
4339 // Use existing uncompiled data's inferred name as it may be more
4340 // accurate than the literal we preparsed.
4341 Handle<String> inferred_name =
4342 handle(existing_uncompiled_data->inferred_name(), isolate);
4343 Handle<PreparseData> preparse_data =
4344 literal->produced_preparse_data()->Serialize(isolate);
4345 DirectHandle<UncompiledData> new_uncompiled_data =
4346 isolate->factory()->NewUncompiledDataWithPreparseData(
4347 inferred_name, existing_uncompiled_data->start_position(),
4348 existing_uncompiled_data->end_position(), preparse_data);
4349 existing->set_uncompiled_data(*new_uncompiled_data);
4350 }
4351 return existing;
4352 }
4353
4354 // Allocate a shared function info object which will be compiled lazily.
4356 isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script,
4357 false);
4358 return result;
4359}
4360
4365 LocalIsolate* isolate);
4366
4367// static
4369 Isolate* isolate, DirectHandle<JSFunction> function,
4370 BytecodeOffset osr_offset, ConcurrencyMode mode, CodeKind code_kind) {
4371 DCHECK(IsOSR(osr_offset));
4372
4373 if (V8_UNLIKELY(isolate->serializer_enabled())) return {};
4374 if (V8_UNLIKELY(function->shared()->optimization_disabled())) return {};
4375
4376 // TODO(chromium:1031479): Currently, OSR triggering mechanism is tied to the
4377 // bytecode array. So, it might be possible to mark closure in one native
4378 // context and optimize a closure from a different native context. So check if
4379 // there is a feedback vector before OSRing. We don't expect this to happen
4380 // often.
4381 if (V8_UNLIKELY(!function->has_feedback_vector())) return {};
4382
4383 CompilerTracer::TraceOptimizeOSRStarted(isolate, function, osr_offset, mode);
4385 GetOrCompileOptimized(isolate, function, mode, code_kind, osr_offset);
4386
4387 if (result.is_null()) {
4388 CompilerTracer::TraceOptimizeOSRUnavailable(isolate, function, osr_offset,
4389 mode);
4390 } else {
4391 DCHECK_GE(result.ToHandleChecked()->kind(), CodeKind::MAGLEV);
4392 CompilerTracer::TraceOptimizeOSRAvailable(isolate, function, osr_offset,
4393 mode);
4394 }
4395
4396 return result;
4397}
4398
4399// static
4403 "V8.OptimizeConcurrentDispose", job->trace_id(),
4406 function->SetTieringInProgress(false, job->compilation_info()->osr_offset());
4407}
4408
4409// static
4411 Isolate* isolate) {
4412 VMState<COMPILER> state(isolate);
4413 OptimizedCompilationInfo* compilation_info = job->compilation_info();
4414
4416 RCS_SCOPE(isolate, RuntimeCallCounterId::kOptimizeConcurrentFinalize);
4418 "V8.OptimizeConcurrentFinalize", job->trace_id(),
4420
4421 DirectHandle<JSFunction> function = compilation_info->closure();
4422 DirectHandle<SharedFunctionInfo> shared = compilation_info->shared_info();
4423
4424 const bool use_result = !compilation_info->discard_result_for_testing();
4425 const BytecodeOffset osr_offset = compilation_info->osr_offset();
4426
4427 DCHECK(!shared->HasBreakInfo(isolate));
4428
4429 // 1) Optimization on the concurrent thread may have failed.
4430 // 2) The function may have already been optimized by OSR. Simply continue.
4431 // Except when OSR already disabled optimization for some reason.
4432 // 3) The code may have already been invalidated due to dependency change.
4433 // 4) InstructionStream generation may have failed.
4435 if (shared->optimization_disabled()) {
4436 job->RetryOptimization(BailoutReason::kOptimizationDisabled);
4437 } else if (job->FinalizeJob(isolate) == CompilationJob::SUCCEEDED) {
4439 job->RecordFunctionCompilation(LogEventListener::CodeTag::kFunction,
4440 isolate);
4441 if (V8_LIKELY(use_result)) {
4442 function->SetTieringInProgress(false,
4443 job->compilation_info()->osr_offset());
4444 if (!V8_ENABLE_LEAPTIERING_BOOL || IsOSR(osr_offset)) {
4445 OptimizedCodeCache::Insert(
4446 isolate, *compilation_info->closure(),
4447 compilation_info->osr_offset(), *compilation_info->code(),
4448 compilation_info->function_context_specializing());
4449 }
4450 CompilerTracer::TraceCompletedJob(isolate, compilation_info);
4451 if (IsOSR(osr_offset)) {
4452 CompilerTracer::TraceOptimizeOSRFinished(isolate, function,
4453 osr_offset);
4454 } else {
4455 function->UpdateOptimizedCode(isolate, *compilation_info->code());
4456 }
4457 }
4458 return;
4459 }
4460 }
4461
4463 CompilerTracer::TraceAbortedJob(isolate, compilation_info,
4464 job->prepare_in_ms(), job->execute_in_ms(),
4465 job->finalize_in_ms());
4466 if (V8_LIKELY(use_result)) {
4467 function->SetTieringInProgress(false,
4468 job->compilation_info()->osr_offset());
4469 if (!IsOSR(osr_offset)) {
4470 function->UpdateCode(shared->GetCode(isolate));
4471 }
4472 }
4473}
4474
4475// static
4476void Compiler::DisposeMaglevCompilationJob(maglev::MaglevCompilationJob* job,
4477 Isolate* isolate) {
4478#ifdef V8_ENABLE_MAGLEV
4479 DirectHandle<JSFunction> function = job->function();
4480 function->SetTieringInProgress(false, job->osr_offset());
4481#endif // V8_ENABLE_MAGLEV
4482}
4483
4484// static
4485void Compiler::FinalizeMaglevCompilationJob(maglev::MaglevCompilationJob* job,
4486 Isolate* isolate) {
4487#ifdef V8_ENABLE_MAGLEV
4488 VMState<COMPILER> state(isolate);
4489
4490 DirectHandle<JSFunction> function = job->function();
4491 BytecodeOffset osr_offset = job->osr_offset();
4492
4493 if (function->ActiveTierIsTurbofan(isolate) && !job->is_osr()) {
4494 function->SetTieringInProgress(false, osr_offset);
4495 CompilerTracer::TraceAbortedMaglevCompile(
4496 isolate, function, BailoutReason::kHigherTierAvailable);
4497 return;
4498 }
4499 // Discard code compiled for a discarded native context without finalization.
4500 if (function->native_context()->global_object()->IsDetached()) {
4501 CompilerTracer::TraceAbortedMaglevCompile(
4502 isolate, function, BailoutReason::kDetachedNativeContext);
4503 return;
4504 }
4505
4506 const CompilationJob::Status status = job->FinalizeJob(isolate);
4507
4508 // TODO(v8:7700): Use the result and check if job succeed
4509 // when all the bytecodes are implemented.
4510 USE(status);
4511
4512 if (status == CompilationJob::SUCCEEDED) {
4513 DirectHandle<SharedFunctionInfo> shared(function->shared(), isolate);
4514 DCHECK(!shared->HasBreakInfo(isolate));
4515
4516 // Note the finalized InstructionStream object has already been installed on
4517 // the function by MaglevCompilationJob::FinalizeJobImpl.
4518
4519 DirectHandle<Code> code = job->code().ToHandleChecked();
4520 if (!job->is_osr()) {
4521 job->function()->UpdateOptimizedCode(isolate, *code);
4522 }
4523
4524 DCHECK(code->is_maglevved());
4525 if (!V8_ENABLE_LEAPTIERING_BOOL || IsOSR(osr_offset)) {
4526 OptimizedCodeCache::Insert(isolate, *function, osr_offset, *code,
4527 job->specialize_to_function_context());
4528 }
4529
4530 RecordMaglevFunctionCompilation(isolate, function,
4531 Cast<AbstractCode>(code));
4532 job->RecordCompilationStats(isolate);
4533 if (v8_flags.profile_guided_optimization &&
4534 shared->cached_tiering_decision() <=
4536 shared->set_cached_tiering_decision(CachedTieringDecision::kEarlyMaglev);
4537 }
4538 CompilerTracer::TraceFinishMaglevCompile(
4539 isolate, function, job->is_osr(), job->prepare_in_ms(),
4540 job->execute_in_ms(), job->finalize_in_ms());
4541 } else {
4542 CompilerTracer::TraceAbortedMaglevCompile(isolate, function,
4543 job->bailout_reason_);
4544 }
4545 function->SetTieringInProgress(false, osr_offset);
4546#endif
4547}
4548
4549// static
4551 DirectHandle<JSFunction> function,
4552 IsCompiledScope* is_compiled_scope) {
4553 DirectHandle<SharedFunctionInfo> shared(function->shared(), isolate);
4554
4555 // If code is compiled to bytecode (i.e., isn't asm.js), then allocate a
4556 // feedback and check for optimized code.
4557 if (is_compiled_scope->is_compiled() && shared->HasBytecodeArray()) {
4558 // Don't reset budget if there is a closure feedback cell array already. We
4559 // are just creating a new closure that shares the same feedback cell.
4560 JSFunction::InitializeFeedbackCell(function, is_compiled_scope, false);
4561
4562#ifndef V8_ENABLE_LEAPTIERING
4563 if (function->has_feedback_vector()) {
4564 // Evict any deoptimized code on feedback vector. We need to do this after
4565 // creating the closure, since any heap allocations could trigger a GC and
4566 // deoptimized the code on the feedback vector. So check for any
4567 // deoptimized code just before installing it on the function.
4568 function->feedback_vector()->EvictOptimizedCodeMarkedForDeoptimization(
4569 isolate, *shared, "new function from shared function info");
4570 Tagged<Code> code = function->feedback_vector()->optimized_code(isolate);
4571 if (!code.is_null()) {
4572 // Caching of optimized code enabled and optimized code found.
4573 DCHECK(!code->marked_for_deoptimization());
4574 DCHECK(function->shared()->is_compiled());
4575 function->UpdateOptimizedCode(isolate, code);
4576 }
4577 }
4578#endif // !V8_ENABLE_LEAPTIERING
4579
4580 if (v8_flags.always_turbofan && shared->allows_lazy_compilation() &&
4581 !shared->optimization_disabled() &&
4582 !function->HasAvailableOptimizedCode(isolate)) {
4583 CompilerTracer::TraceMarkForAlwaysOpt(isolate, function);
4584 JSFunction::EnsureFeedbackVector(isolate, function, is_compiled_scope);
4585 function->RequestOptimization(isolate, CodeKind::TURBOFAN_JS,
4587 }
4588 }
4589
4590 if (shared->is_toplevel() || shared->is_wrapped()) {
4591 // If it's a top-level script, report compilation to the debugger.
4592 DirectHandle<Script> script(Cast<Script>(shared->script()), isolate);
4593 isolate->debug()->OnAfterCompile(script);
4594 bool source_rundown_enabled;
4596 TRACE_DISABLED_BY_DEFAULT("devtools.v8-source-rundown"),
4597 &source_rundown_enabled);
4598 if (source_rundown_enabled) {
4599 script->TraceScriptRundown();
4600 }
4601 bool source_rundown_sources_enabled;
4603 TRACE_DISABLED_BY_DEFAULT("devtools.v8-source-rundown-sources"),
4604 &source_rundown_sources_enabled);
4605 if (source_rundown_sources_enabled) {
4606 script->TraceScriptRundownSources();
4607 }
4608 }
4609}
4610
4611// ----------------------------------------------------------------------------
4612// Implementation of ScriptStreamingData
4613
4615 std::unique_ptr<ScriptCompiler::ExternalSourceStream> source_stream,
4617 : source_stream(std::move(source_stream)), encoding(encoding) {}
4618
4620
4622
4623} // namespace internal
4624} // namespace v8
Isolate * isolate_
interpreter::Bytecode bytecode
Definition builtins.cc:43
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
Builtins::Kind kind
Definition builtins.cc:40
#define BUILTIN_CODE(isolate, name)
Definition builtins.h:45
#define SBXCHECK(condition)
Definition check.h:61
@ kTurboFanOsrCompileStarted
Definition v8-isolate.h:584
internal::ScriptStreamingData * impl() const
Definition v8-script.h:590
CompilationDetails & compilation_details()
Definition v8-script.h:596
@ kFollowCompileHintsMagicComment
Definition v8-script.h:679
@ kFollowCompileHintsPerFunctionMagicComment
Definition v8-script.h:680
bool IsModule() const
Definition v8-message.h:46
static v8::internal::Handle< To > OpenHandle(v8::Local< From > handle)
Definition api.h:274
double InMillisecondsF() const
Definition time.cc:226
int64_t InMicroseconds() const
Definition time.cc:251
static bool IsHighResolution()
Definition time.cc:763
static V8_EXPORT_PRIVATE DirectHandle< ArrayList > Add(Isolate *isolate, DirectHandle< ArrayList > array, Tagged< Smi > obj, AllocationType allocation=AllocationType::kYoung)
static DirectHandle< ArrayList > New(IsolateT *isolate, int capacity, AllocationType allocation=AllocationType::kYoung)
static std::unique_ptr< UnoptimizedCompilationJob > NewCompilationJob(ParseInfo *parse_info, FunctionLiteral *literal, AccountingAllocator *allocator)
Definition asm-js.cc:305
BackgroundCompileTask(ScriptStreamingData *data, Isolate *isolate, v8::ScriptType type, ScriptCompiler::CompileOptions options, ScriptCompiler::CompilationDetails *compilation_details, CompileHintCallback compile_hint_callback=nullptr, void *compile_hint_callback_data=nullptr)
Definition compiler.cc:1690
void ReportStatistics(Isolate *isolate)
Definition compiler.cc:2723
std::unique_ptr< Utf16CharacterStream > character_stream_
Definition compiler.h:637
MaybeIndirectHandle< SharedFunctionInfo > outer_function_sfi_
Definition compiler.h:645
ScriptCompiler::CompilationDetails * compilation_details_
Definition compiler.h:641
UnoptimizedCompileFlags flags_
Definition compiler.h:635
bool FinalizeFunction(Isolate *isolate, Compiler::ClearExceptionFlag flag)
Definition compiler.cc:2673
DeferredFinalizationJobDataList jobs_to_retry_finalization_on_main_thread_
Definition compiler.h:649
MaybeHandle< SharedFunctionInfo > FinalizeScript(Isolate *isolate, DirectHandle< String > source, const ScriptDetails &script_details, MaybeDirectHandle< Script > maybe_cached_script)
Definition compiler.cc:2605
UnoptimizedCompileState compile_state_
Definition compiler.h:636
FinalizeUnoptimizedCompilationDataList finalize_unoptimized_compilation_data_
Definition compiler.h:648
CompileHintCallback compile_hint_callback_
Definition compiler.h:659
UnoptimizedCompileFlags flags() const
Definition compiler.h:623
void RunOnMainThread(Isolate *isolate)
Definition compiler.cc:1942
std::unique_ptr< PersistentHandles > persistent_handles_
Definition compiler.h:644
IndirectHandle< Script > script_
Definition compiler.h:646
base::SmallVector< v8::Isolate::UseCounterFeature, 8 > use_counts_
Definition compiler.h:650
MaybeIndirectHandle< SharedFunctionInfo > input_shared_info_
Definition compiler.h:654
CodeSerializer::OffThreadDeserializeData off_thread_data_
Definition compiler.h:722
MaybeDirectHandle< SharedFunctionInfo > Finish(Isolate *isolate, DirectHandle< String > source, const ScriptDetails &script_details)
Definition compiler.cc:2787
BackgroundMergeTask background_merge_task_
Definition compiler.h:723
BackgroundDeserializeTask(Isolate *isolate, std::unique_ptr< ScriptCompiler::CachedData > data)
Definition compiler.cc:2730
void SourceTextAvailable(Isolate *isolate, Handle< String > source_text, const ScriptDetails &script_details)
Definition compiler.cc:2761
static void ForceGCDuringNextMergeForTesting()
Definition compiler.cc:2391
std::vector< NewCompiledDataForCachedSfi > new_compiled_data_for_cached_sfis_
void SetUpOnMainThread(Isolate *isolate, Handle< String > source_text, const ScriptDetails &script_details, LanguageMode language_mode)
Definition compiler.cc:2278
std::unique_ptr< PersistentHandles > persistent_handles_
void BeginMergeInBackground(LocalIsolate *isolate, DirectHandle< Script > new_script)
Definition compiler.cc:2395
Handle< SharedFunctionInfo > CompleteMergeInForeground(Isolate *isolate, DirectHandle< Script > new_script)
Definition compiler.cc:2511
std::vector< Handle< SharedFunctionInfo > > used_new_sfis_
MaybeHandle< SharedFunctionInfo > toplevel_sfi_from_cached_script_
static DirectHandle< Code > CreateInterpreterEntryTrampolineForProfiling(Isolate *isolate)
Definition builtins.cc:430
static constexpr BytecodeOffset None()
Definition utils.h:675
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< SharedFunctionInfo > FinishOffThreadDeserialize(Isolate *isolate, OffThreadDeserializeData &&data, AlignedCachedData *cached_data, DirectHandle< String > source, const ScriptDetails &script_details, BackgroundMergeTask *background_merge_task=nullptr)
static V8_WARN_UNUSED_RESULT OffThreadDeserializeData StartDeserializeOffThread(LocalIsolate *isolate, AlignedCachedData *cached_data)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< SharedFunctionInfo > Deserialize(Isolate *isolate, AlignedCachedData *cached_data, DirectHandle< String > source, const ScriptDetails &script_details, MaybeDirectHandle< Script > maybe_cached_script={})
MaybeHandle< SharedFunctionInfo > toplevel_sfi() const
CompilationCacheScriptLookupResult LookupResult
CompilationCacheScript::LookupResult LookupScript(Handle< String > source, const ScriptDetails &script_details, LanguageMode language_mode)
void PutScript(Handle< String > source, LanguageMode language_mode, DirectHandle< SharedFunctionInfo > function_info)
InfoCellPair LookupEval(DirectHandle< String > source, DirectHandle< SharedFunctionInfo > outer_info, DirectHandle< Context > context, LanguageMode language_mode, int position)
void PutEval(DirectHandle< String > source, DirectHandle< SharedFunctionInfo > outer_info, DirectHandle< Context > context, DirectHandle< SharedFunctionInfo > function_info, DirectHandle< FeedbackCell > feedback_cell, int position)
V8_EXPORT_PRIVATE ~CompilationHandleScope()
Definition compiler.cc:1669
PersistentHandlesScope persistent_
Definition compiler.h:578
OptimizedCompilationInfo * info_
Definition compiler.h:579
V8_WARN_UNUSED_RESULT Status UpdateState(Status status, State next_state)
Definition compiler.h:306
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< JSFunction > GetFunctionFromValidatedString(DirectHandle< NativeContext > context, MaybeDirectHandle< String > source, ParseRestriction restriction, int parameters_end_pos)
Definition compiler.cc:3470
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< JSFunction > GetFunctionFromEval(DirectHandle< String > source, DirectHandle< SharedFunctionInfo > outer_info, DirectHandle< Context > context, LanguageMode language_mode, ParseRestriction restriction, int parameters_end_pos, int eval_position, ParsingWhileDebugging parsing_while_debugging=ParsingWhileDebugging::kNo)
Definition compiler.cc:3250
static bool CompileSharedWithBaseline(Isolate *isolate, Handle< SharedFunctionInfo > shared, ClearExceptionFlag flag, IsCompiledScope *is_compiled_scope)
Definition compiler.cc:3081
static bool CompileBaseline(Isolate *isolate, DirectHandle< JSFunction > function, ClearExceptionFlag flag, IsCompiledScope *is_compiled_scope)
Definition compiler.cc:3132
static void CompileOptimized(Isolate *isolate, DirectHandle< JSFunction > function, ConcurrencyMode mode, CodeKind code_kind)
Definition compiler.cc:3176
static MaybeDirectHandle< SharedFunctionInfo > GetSharedFunctionInfoForScriptWithCompileHints(Isolate *isolate, Handle< String > source, const ScriptDetails &script_details, v8::CompileHintCallback compile_hint_callback, void *compile_hint_callback_data, ScriptCompiler::CompileOptions compile_options, ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag is_natives_code, ScriptCompiler::CompilationDetails *compilation_details)
Definition compiler.cc:4112
static V8_WARN_UNUSED_RESULT std::pair< MaybeDirectHandle< String >, bool > ValidateDynamicCompilationSource(Isolate *isolate, DirectHandle< NativeContext > context, Handle< i::Object > source_object, bool is_code_like=false)
Definition compiler.cc:3427
static bool Compile(Isolate *isolate, Handle< SharedFunctionInfo > shared, ClearExceptionFlag flag, IsCompiledScope *is_compiled_scope, CreateSourcePositions create_source_positions_flag=CreateSourcePositions::kNo)
Definition compiler.cc:2906
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< JSFunction > GetFunctionFromString(DirectHandle< NativeContext > context, Handle< i::Object > source, int parameters_end_pos, bool is_code_like)
Definition compiler.cc:3494
static MaybeDirectHandle< SharedFunctionInfo > GetSharedFunctionInfoForScriptWithExtension(Isolate *isolate, Handle< String > source, const ScriptDetails &script_details, v8::Extension *extension, ScriptCompiler::CompileOptions compile_options, NativesFlag is_natives_code, ScriptCompiler::CompilationDetails *compilation_details)
Definition compiler.cc:4074
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< SharedFunctionInfo > CompileForLiveEdit(ParseInfo *parse_info, Handle< Script > script, MaybeDirectHandle< ScopeInfo > outer_scope_info, Isolate *isolate)
Definition compiler.cc:3241
static bool CollectSourcePositions(Isolate *isolate, DirectHandle< SharedFunctionInfo > shared)
Definition compiler.cc:2799
static void FinalizeTurbofanCompilationJob(TurbofanCompilationJob *job, Isolate *isolate)
Definition compiler.cc:4410
static void InstallInterpreterTrampolineCopy(Isolate *isolate, DirectHandle< SharedFunctionInfo > shared_info, LogEventListener::CodeTag log_tag)
Definition compiler.cc:681
static DirectHandle< SharedFunctionInfo > GetSharedFunctionInfo(FunctionLiteral *node, DirectHandle< Script > script, IsolateT *isolate)
Definition compiler.cc:4312
static MaybeDirectHandle< SharedFunctionInfo > GetSharedFunctionInfoForScriptWithDeserializeTask(Isolate *isolate, Handle< String > source, const ScriptDetails &script_details, BackgroundDeserializeTask *deserialize_task, ScriptCompiler::CompileOptions compile_options, ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag is_natives_code, ScriptCompiler::CompilationDetails *compilation_details)
Definition compiler.cc:4098
static void DisposeTurbofanCompilationJob(Isolate *isolate, TurbofanCompilationJob *job)
Definition compiler.cc:4400
static MaybeDirectHandle< SharedFunctionInfo > GetSharedFunctionInfoForStreamedScript(Isolate *isolate, Handle< String > source, const ScriptDetails &script_details, ScriptStreamingData *streaming_data, ScriptCompiler::CompilationDetails *compilation_details)
Definition compiler.cc:4241
static void FinalizeMaglevCompilationJob(maglev::MaglevCompilationJob *job, Isolate *isolate)
Definition compiler.cc:4485
static bool FinalizeBackgroundCompileTask(BackgroundCompileTask *task, Isolate *isolate, ClearExceptionFlag flag)
Definition compiler.cc:3159
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< JSFunction > GetWrappedFunction(Handle< String > source, DirectHandle< Context > context, const ScriptDetails &script_details, AlignedCachedData *cached_data, v8::ScriptCompiler::CompileOptions compile_options, v8::ScriptCompiler::NoCacheReason no_cache_reason)
Definition compiler.cc:4127
static MaybeDirectHandle< SharedFunctionInfo > GetSharedFunctionInfoForScript(Isolate *isolate, Handle< String > source, const ScriptDetails &script_details, ScriptCompiler::CompileOptions compile_options, ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag is_natives_code, ScriptCompiler::CompilationDetails *compilation_details)
Definition compiler.cc:4062
static V8_WARN_UNUSED_RESULT MaybeHandle< Code > CompileOptimizedOSR(Isolate *isolate, DirectHandle< JSFunction > function, BytecodeOffset osr_offset, ConcurrencyMode mode, CodeKind code_kind)
Definition compiler.cc:4368
static void PostInstantiation(Isolate *isolate, DirectHandle< JSFunction > function, IsCompiledScope *is_compiled_scope)
Definition compiler.cc:4550
static MaybeHandle< SharedFunctionInfo > CompileToplevel(ParseInfo *parse_info, Handle< Script > script, Isolate *isolate, IsCompiledScope *is_compiled_scope)
Definition compiler.cc:3151
static void LogFunctionCompilation(Isolate *isolate, LogEventListener::CodeTag code_type, DirectHandle< Script > script, DirectHandle< SharedFunctionInfo > shared, DirectHandle< FeedbackVector > vector, DirectHandle< AbstractCode > abstract_code, CodeKind kind, double time_taken_ms)
Definition compiler.cc:298
static void DisposeMaglevCompilationJob(maglev::MaglevCompilationJob *job, Isolate *isolate)
Definition compiler.cc:4476
static MaybeDirectHandle< SharedFunctionInfo > GetSharedFunctionInfoForScriptWithCachedData(Isolate *isolate, Handle< String > source, const ScriptDetails &script_details, AlignedCachedData *cached_data, ScriptCompiler::CompileOptions compile_options, ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag is_natives_code, ScriptCompiler::CompilationDetails *compilation_details)
Definition compiler.cc:4086
std::unordered_map< int, IndirectHandle< ScopeInfo > > scope_infos_to_update_
Definition compiler.cc:2275
void VisitSharedFunctionInfo(Tagged< TArray > constant_pool, int i, Tagged< SharedFunctionInfo > sfi)
Definition compiler.cc:2222
void VisitScopeInfo(Tagged< TArray > constant_pool, int i, Tagged< ScopeInfo > scope_info)
Definition compiler.cc:2233
void VerifyScopeInfo(Tagged< ScopeInfo > scope_info, Tagged< ScopeInfo > replacement)
Definition compiler.cc:2195
void RecordScopeInfos(Tagged< HeapObject > info)
Definition compiler.cc:2091
bool InstallOwnScopeInfo(Tagged< SharedFunctionInfo > sfi)
Definition compiler.cc:2154
void IterateConstantPoolEntry(Tagged< TArray > constant_pool, int i)
Definition compiler.cc:2202
void UpdateScopeInfo(Tagged< SharedFunctionInfo > sfi)
Definition compiler.cc:2167
void RecordScopeInfos(Tagged< MaybeObject > maybe_old_info)
Definition compiler.cc:2085
ConstantPoolPointerForwarder(PtrComprCageBase cage_base, LocalHeap *local_heap, DirectHandle< Script > old_script)
Definition compiler.cc:2073
void AddBytecodeArray(Tagged< BytecodeArray > bytecode_array)
Definition compiler.cc:2080
void IterateConstantPool(Tagged< TrustedFixedArray > constant_pool)
Definition compiler.cc:2256
void IterateConstantPoolNestedArray(Tagged< FixedArray > nested_array)
Definition compiler.cc:2262
std::vector< IndirectHandle< BytecodeArray > > bytecode_arrays_to_update_
Definition compiler.cc:2271
static V8_EXPORT_PRIVATE std::unique_ptr< ConsumedPreparseData > For(Isolate *isolate, Handle< PreparseData > data)
static V8_EXPORT_PRIVATE void AllocateScopeInfos(ParseInfo *info, DirectHandle< Script > script, IsolateT *isolate)
DeferredFinalizationJobData(Isolate *isolate, DirectHandle< SharedFunctionInfo > function_handle, std::unique_ptr< UnoptimizedCompilationJob > job)
Definition compiler.h:547
JSFunctionBuilder & set_feedback_cell(DirectHandle< FeedbackCell > v)
Definition factory.h:1124
JSFunctionBuilder & set_allocation_type(AllocationType v)
Definition factory.h:1120
V8_WARN_UNUSED_RESULT Handle< JSFunction > Build()
Definition factory.cc:4732
static V8_EXPORT_PRIVATE Handle< FeedbackMetadata > New(IsolateT *isolate, const FeedbackVectorSpec *spec)
FinalizeUnoptimizedCompilationData(Isolate *isolate, Handle< SharedFunctionInfo > function_handle, MaybeHandle< CoverageInfo > coverage_info, base::TimeDelta time_taken_to_execute, base::TimeDelta time_taken_to_finalize)
Definition compiler.h:504
Handle< Object > script() const
bool has_duplicate_parameters() const
Definition ast.h:2369
Handle< SharedFunctionInfo > shared_function_info() const
Definition ast.h:2356
V8_EXPORT_PRIVATE LanguageMode language_mode() const
Definition ast.cc:227
bool has_static_private_methods_or_accessors() const
Definition ast.h:2424
bool class_scope_has_private_brand() const
Definition ast.cc:268
bool requires_instance_members_initializer() const
Definition ast.h:2416
DeclarationScope * scope() const
Definition ast.h:2315
void set_shared_function_info(Handle< SharedFunctionInfo > shared_function_info)
Definition ast.cc:202
HandleType< T > CloseAndEscape(HandleType< T > handle_value)
V8_EXPORT_PRIVATE void CollectAllAvailableGarbage(GarbageCollectionReason gc_reason)
Definition heap.cc:1327
Tagged< FeedbackCell > feedback_cell() const
Tagged< SharedFunctionInfo > shared() const
ThreadId thread_id() const
Definition isolate.h:821
static V8_EXPORT_PRIVATE void EnsureFeedbackVector(Isolate *isolate, DirectHandle< JSFunction > function, IsCompiledScope *compiled_scope)
FeedbackVector eventually. Generally this shouldn't be used to get the.
static void InitializeFeedbackCell(DirectHandle< JSFunction > function, IsCompiledScope *compiled_scope, bool reset_budget_for_feedback_allocation)
static MaybeDirectHandle< JSFunction > GetConstructor(Isolate *isolate, DirectHandle< JSReceiver > receiver)
std::unique_ptr< PersistentHandles > DetachPersistentHandles()
Heap * heap() const
Definition local-heap.h:122
Heap * AsHeap() const
Definition local-heap.h:123
IndirectHandle< T > NewPersistentHandle(Tagged< T > object)
Definition local-heap.h:73
void AttachPersistentHandles(std::unique_ptr< PersistentHandles > persistent_handles)
static bool IsMarkedForManualOptimization(Isolate *isolate, Tagged< JSFunction > function)
V8_WARN_UNUSED_RESULT V8_INLINE bool ToHandle(DirectHandle< S > *out) const
V8_INLINE bool is_null() const
V8_INLINE Handle< T > ToHandleChecked() const
static MaybeObjectDirectHandle Weak(Tagged< Object > object, Isolate *isolate)
static V8_WARN_UNUSED_RESULT HandleType< String >::MaybeType ToString(Isolate *isolate, HandleType< T > input)
static V8_EXPORT_PRIVATE bool StrictEquals(Tagged< Object > obj, Tagged< Object > that)
Definition objects.cc:986
static bool IsCodeLike(Tagged< Object > obj, Isolate *isolate)
Definition objects.cc:1860
IndirectHandle< SharedFunctionInfo > shared_info() const
void set_persistent_handles(std::unique_ptr< PersistentHandles > persistent_handles)
IndirectHandle< JSFunction > closure() const
void RegisterWeakObjectsInOptimizedCode(Isolate *isolate, DirectHandle< NativeContext > context, DirectHandle< Code > code, GlobalHandleVector< Map > maps)
Definition compiler.cc:504
V8_WARN_UNUSED_RESULT base::TimeDelta ElapsedTime() const
Definition compiler.h:433
GlobalHandleVector< Map > CollectRetainedMaps(Isolate *isolate, DirectHandle< Code > code)
Definition compiler.cc:484
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT Status FinalizeJob(Isolate *isolate)
Definition compiler.cc:474
virtual Status PrepareJobImpl(Isolate *isolate)=0
virtual Status FinalizeJobImpl(Isolate *isolate)=0
virtual Status ExecuteJobImpl(RuntimeCallStats *stats, LocalIsolate *local_heap)=0
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT Status PrepareJob(Isolate *isolate)
Definition compiler.cc:453
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT Status ExecuteJob(RuntimeCallStats *stats, LocalIsolate *local_isolate=nullptr)
Definition compiler.cc:463
AccountingAllocator * allocator() const
Definition parse-info.h:253
bool allow_eval_cache() const
Definition parse-info.h:277
FunctionLiteral * literal() const
Definition parse-info.h:319
void set_consumed_preparse_data(std::unique_ptr< ConsumedPreparseData > data)
Definition parse-info.h:298
Handle< Script > CreateScript(IsolateT *isolate, DirectHandle< String > source, MaybeDirectHandle< FixedArray > maybe_wrapped_arguments, ScriptOriginOptions origin_options, NativesFlag natives=NOT_NATIVES_CODE)
void set_parameters_end_pos(int parameters_end_pos)
Definition parse-info.h:325
void UpdateStatistics(Isolate *isolate, DirectHandle< Script > script)
Definition parser.cc:3413
void DeserializeScopeChain(IsolateT *isolate, ParseInfo *info, MaybeDirectHandle< ScopeInfo > maybe_outer_scope_info, Scope::DeserializationMode mode=Scope::DeserializationMode::kScopesOnly)
Definition parser.cc:624
void InitializeEmptyScopeChain(ParseInfo *info)
Definition parser.cc:614
void ParseOnBackground(LocalIsolate *isolate, ParseInfo *info, DirectHandle< Script > script, int start_position, int end_position, int function_literal_id)
Definition parser.cc:3464
V8_EXPORT_PRIVATE std::unique_ptr< PersistentHandles > Detach()
static constexpr bool IsEmbeddedObjectMode(Mode mode)
Definition reloc-info.h:209
static int EmbeddedObjectModeMask()
Definition reloc-info.h:378
AccountingAllocator * allocator() const
Definition parse-info.h:207
Handle< ScopeInfo > scope_info() const
Definition scopes.h:581
static void InitLineEnds(Isolate *isolate, DirectHandle< Script > script)
Definition script-inl.h:201
static constexpr int kTemporaryScriptId
Definition script.h:42
static MaybeHandle< SharedFunctionInfo > FindSharedFunctionInfo(DirectHandle< Script > script, IsolateT *isolate, FunctionLiteral *function_literal)
Definition objects.cc:4763
static void SetSource(Isolate *isolate, DirectHandle< Script > script, DirectHandle< String > source)
Definition objects.cc:4349
static bool GetPositionInfo(DirectHandle< Script > script, int position, PositionInfo *info, OffsetFlag offset_flag=OffsetFlag::kWithOffset)
Definition objects.cc:4367
V8_EXPORT_PRIVATE Tagged< SharedFunctionInfo > Next()
static void EnsureSourcePositionsAvailable(Isolate *isolate, DirectHandle< SharedFunctionInfo > shared_info)
static void CreateAndSetUncompiledData(IsolateT *isolate, FunctionLiteral *lit)
static Handle< String > DebugName(Isolate *isolate, DirectHandle< SharedFunctionInfo > shared)
static constexpr Tagged< Smi > FromInt(int value)
Definition smi.h:38
V8_INLINE constexpr StorageType ptr() const
constexpr bool IsWeak() const
Tagged< HeapObject > GetHeapObjectAssumeWeak() const
V8_INLINE constexpr bool is_null() const
Definition tagged.h:502
static ThreadId Current()
Definition thread-id.h:32
OptimizedCompilationInfo *const compilation_info_
Definition compiler.h:498
Status RetryOptimization(BailoutReason reason)
Definition compiler.cc:531
Status AbortOptimization(BailoutReason reason)
Definition compiler.cc:538
V8_EXPORT_PRIVATE TurbofanCompilationJob(Isolate *isolate, OptimizedCompilationInfo *compilation_info, State initial_state)
Definition compiler.cc:523
void RecordFunctionCompilation(LogEventListener::CodeTag code_type, Isolate *isolate) const
Definition compiler.cc:631
OptimizedCompilationInfo * compilation_info() const
Definition compiler.h:469
void RecordCompilationStats(ConcurrencyMode mode, Isolate *isolate) const
Definition compiler.cc:547
DirectHandle< AsmWasmData > asm_wasm_data() const
V8_WARN_UNUSED_RESULT Status FinalizeJob(DirectHandle< SharedFunctionInfo > shared_info, Isolate *isolate)
Definition compiler.cc:398
V8_WARN_UNUSED_RESULT Status ExecuteJob()
Definition compiler.cc:390
virtual Status FinalizeJobImpl(DirectHandle< SharedFunctionInfo > shared_info, Isolate *isolate)=0
static UnoptimizedCompileFlags ForToplevelCompile(Isolate *isolate, bool is_user_javascript, LanguageMode language_mode, REPLMode repl_mode, ScriptType type, bool lazy)
Definition parse-info.cc:88
static UnoptimizedCompileFlags ForFunctionCompile(Isolate *isolate, Tagged< SharedFunctionInfo > shared)
Definition parse-info.cc:46
const PendingCompilationErrorHandler * pending_error_handler() const
Definition parse-info.h:165
static V8_INLINE CodeTag ToNativeByScript(CodeTag tag, Tagged< Script > script)
Definition log-inl.h:18
static V8_WARN_UNUSED_RESULT DirectHandle< WeakArrayList > Append(Isolate *isolate, DirectHandle< WeakArrayList > array, MaybeObjectDirectHandle value, AllocationType allocation=AllocationType::kYoung)
static std::unique_ptr< UnoptimizedCompilationJob > NewSourcePositionCollectionJob(ParseInfo *parse_info, FunctionLiteral *literal, Handle< BytecodeArray > existing_bytecode, AccountingAllocator *allocator, LocalIsolate *local_isolate)
static std::unique_ptr< UnoptimizedCompilationJob > NewCompilationJob(ParseInfo *parse_info, FunctionLiteral *literal, Handle< Script > script, AccountingAllocator *allocator, std::vector< FunctionLiteral * > *eager_inner_literals, LocalIsolate *local_isolate)
#define PROFILE(the_isolate, Call)
Definition code-events.h:59
Handle< Code > code
AlignedCachedData * cached_data_
#define V8_ENABLE_LEAPTIERING_BOOL
Definition globals.h:151
JSRegExp::Flags flags_
LazyTimedHistogramScope histogram_scope_
Definition compiler.cc:3577
v8::ScriptCompiler::StreamedSource streamed_source_
Definition compiler.cc:3792
std::unique_ptr< uint16_t[]> source_buffer_
Definition compiler.cc:3787
bool hit_isolate_cache_
Definition compiler.cc:3582
uint32_t source_length_
Definition compiler.cc:3786
bool consuming_code_cache_failed_
Definition compiler.cc:3584
bool done_
Definition compiler.cc:3788
Handle< String > source_
Definition compiler.cc:3791
NestedTimedHistogramScope all_scripts_histogram_scope_
Definition compiler.cc:3580
bool consuming_code_cache_
Definition compiler.cc:3583
ScriptCompiler::NoCacheReason no_cache_reason_
Definition compiler.cc:3581
int start
Handle< SharedFunctionInfo > info
int end
LineAndColumn current
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call)
Definition isolate.h:291
#define THROW_NEW_ERROR(isolate, call)
Definition isolate.h:307
DisallowGarbageCollection no_gc_
Isolate * isolate
std::string extension
SharedFunctionInfoRef shared
ZoneVector< RpoNumber > & result
LiftoffAssembler::CacheState state
FunctionLiteral * literal
Definition liveedit.cc:294
#define LOG(isolate, Call)
Definition log.h:78
base::ElapsedTimer timer_
STL namespace.
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
Definition graph.h:1231
std::unique_ptr< TurbofanCompilationJob > NewCompilationJob(Isolate *isolate, Handle< JSFunction > function, IsScriptAvailable has_script, BytecodeOffset osr_offset)
static bool IsMaglevEnabled()
Definition compiler.h:57
bool ParseAny(ParseInfo *info, DirectHandle< SharedFunctionInfo > shared_info, Isolate *isolate, ReportStatisticsMode mode)
Definition parsing.cc:98
bool ParseProgram(ParseInfo *info, DirectHandle< Script > script, MaybeDirectHandle< ScopeInfo > maybe_outer_scope_info, Isolate *isolate, ReportStatisticsMode mode)
Definition parsing.cc:39
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
static bool force_gc_during_next_merge_for_testing_
Definition compiler.cc:2389
constexpr bool CodeKindCanOSR(CodeKind kind)
Definition code-kind.h:91
constexpr const char * ToString(DeoptimizeKind kind)
Definition globals.h:880
constexpr NullMaybeHandleType kNullMaybeHandle
constexpr bool CodeKindIsOptimizedJSFunction(CodeKind kind)
Definition code-kind.h:66
PerThreadAssertScopeDebugOnly< false, SAFEPOINTS_ASSERT, HEAP_ALLOCATION_ASSERT > DisallowGarbageCollection
void VisitObjectBody(Isolate *isolate, Tagged< HeapObject > object, ObjectVisitor *visitor)
bool is_sloppy(LanguageMode language_mode)
Definition globals.h:773
constexpr int kNoSourcePosition
Definition globals.h:850
bool Is(IndirectHandle< U > value)
Definition handles-inl.h:51
void PrintF(const char *format,...)
Definition utils.cc:39
const char * CodeKindToString(CodeKind kind)
Definition code-kind.cc:10
Tagged(T object) -> Tagged< T >
constexpr bool CodeKindIsStoredInOptimizedCodeCache(CodeKind kind)
Definition code-kind.h:101
constexpr bool IsSynchronous(ConcurrencyMode mode)
Definition globals.h:2596
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
Definition objects.h:665
V8_INLINE IndirectHandle< T > indirect_handle(DirectHandle< T > handle)
Definition handles.h:757
MaybeDirectHandle< Code > GenerateBaselineCode(Isolate *isolate, Handle< SharedFunctionInfo > shared)
Definition baseline.cc:87
bool ModifyCodeGenerationFromStrings(Isolate *isolate, DirectHandle< NativeContext > context, Handle< i::Object > *source, bool is_code_like)
Definition compiler.cc:3388
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in name
Definition flags.cc:2086
void Print(Tagged< Object > obj)
Definition objects.h:774
void SetScriptFieldsFromDetails(Isolate *isolate, Tagged< Script > script, const ScriptDetails &script_details, DisallowGarbageCollection *no_gc)
Definition compiler.cc:1763
CodeKind CodeKindForTopTier()
Definition code-kind.h:124
@ ONLY_SINGLE_FUNCTION_LITERAL
Definition globals.h:1655
uintptr_t GetCurrentStackPosition()
Definition utils.cc:222
void ShortPrint(Tagged< Object > obj, FILE *out)
Definition objects.cc:1865
const char * GetBailoutReason(BailoutReason reason)
std::vector< DeferredFinalizationJobData > DeferredFinalizationJobDataList
Definition compiler.h:582
Tagged< MaybeWeak< T > > MakeWeak(Tagged< T > value)
Definition tagged.h:893
constexpr int kFunctionLiteralIdTopLevel
Definition globals.h:2767
bool is_strict(LanguageMode language_mode)
Definition globals.h:777
V8_EXPORT_PRIVATE FlagValues v8_flags
std::vector< FinalizeUnoptimizedCompilationData > FinalizeUnoptimizedCompilationDataList
Definition compiler.h:542
LanguageMode construct_language_mode(bool strict_bit)
Definition globals.h:786
constexpr int kStackSpaceRequiredForCompilation
Definition globals.h:207
SlotTraits::TMaybeObjectSlot MaybeObjectSlot
Definition globals.h:1248
constexpr bool IsConcurrent(ConcurrencyMode mode)
Definition globals.h:2599
bool CanCompileWithBaseline(Isolate *isolate, Tagged< SharedFunctionInfo > shared)
Definition baseline.cc:82
kInterpreterTrampolineOffset script
!IsContextMap !IsContextMap native_context
Definition map-inl.h:877
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
static constexpr ReleaseStoreTag kReleaseStore
Definition globals.h:2910
Local< T > Handle
static constexpr RelaxedLoadTag kRelaxedLoad
Definition globals.h:2909
static constexpr RelaxedStoreTag kRelaxedStore
Definition globals.h:2911
static constexpr AcquireLoadTag kAcquireLoad
Definition globals.h:2908
bool(*)(int, void *) CompileHintCallback
ScriptType
Definition v8-script.h:397
HeapObjectSet *const visited_
#define RCS_SCOPE(...)
#define UNREACHABLE()
Definition logging.h:67
#define DCHECK_NULL(val)
Definition logging.h:491
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define USE(...)
Definition macros.h:293
InMemoryCacheResult in_memory_cache_result
Definition v8-script.h:481
DirectHandle< Script > GetOnlyScript(LocalHeap *heap)
MaybeHandle< Object > name_obj
MaybeHandle< Object > source_map_url
const ScriptOriginOptions origin_options
MaybeHandle< Object > host_defined_options
MaybeHandle< FixedArray > wrapped_arguments
std::unique_ptr< BackgroundCompileTask > task
Definition compiler.h:680
ScriptStreamingData(std::unique_ptr< ScriptCompiler::ExternalSourceStream > source_stream, ScriptCompiler::StreamedSource::Encoding encoding)
Definition compiler.cc:4614
#define TRACE_EVENT0(category_group, name)
#define TRACE_DISABLED_BY_DEFAULT(name)
#define TRACE_EVENT_WITH_FLOW0(category_group, name, bind_id, flow_flags)
#define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret)
#define TRACE_EVENT_FLAG_FLOW_OUT
#define TRACE_EVENT_FLAG_FLOW_IN
const uint64_t trace_id_
#define V8_LIKELY(condition)
Definition v8config.h:661
#define V8_WARN_UNUSED_RESULT
Definition v8config.h:671
#define V8_UNLIKELY(condition)
Definition v8config.h:660