32#if V8_ENABLE_WEBASSEMBLY
40#define FORWARD_DECLARE(Name, Argc) \
41 Address Builtin_##Name(int argc, Address* args, Isolate* isolate);
47using BuiltinCompilationScheduler =
48 compiler::CodeAssembler::BuiltinCompilationScheduler;
50const int kBufferSize = 128 *
KB;
52AssemblerOptions BuiltinAssemblerOptions(Isolate* isolate,
Builtin builtin) {
54 CHECK(!options.isolate_independent_code);
55 CHECK(!options.collect_win64_unwind_info);
57#if V8_ENABLE_WEBASSEMBLY
59 builtin == Builtin::kJSToWasmWrapper ||
60 builtin == Builtin::kJSToWasmHandleReturns ||
61 builtin == Builtin::kWasmToJsWrapperCSA) {
62 options.is_wasm =
true;
65 if (!isolate->IsGeneratingEmbeddedBuiltins()) {
69 const base::AddressRegion& code_region = isolate->heap()->code_region();
70 bool pc_relative_calls_fit_in_code_range =
71 !code_region.is_empty() &&
72 std::ceil(
static_cast<float>(code_region.size() / MB)) <=
82 options.use_pc_relative_calls_and_jumps_for_mksnapshot =
83 pc_relative_calls_fit_in_code_range;
86 options.isolate_independent_code =
true;
87 options.collect_win64_unwind_info =
true;
89 if (builtin == Builtin::kInterpreterEntryTrampolineForProfiling) {
100using MacroAssemblerGenerator = void (*)(MacroAssembler*);
102 void (*)(compiler::turboshaft::PipelineData*, Isolate*,
103 compiler::turboshaft::Graph&,
Zone*);
107DirectHandle<Code> BuildPlaceholder(Isolate* isolate,
Builtin builtin) {
108 HandleScope scope(isolate);
109 uint8_t buffer[kBufferSize];
112 DCHECK(!masm.has_frame());
121 masm.GetCode(isolate, &desc);
122 Handle<Code> code = Factory::CodeBuilder(isolate, desc, CodeKind::BUILTIN)
123 .set_self_reference(masm.CodeObject())
124 .set_builtin(builtin)
126 return scope.CloseAndEscape(code);
130 Isolate* isolate,
Builtin builtin, MacroAssemblerGenerator generator,
131 const char* s_name) {
132 HandleScope scope(isolate);
133 uint8_t buffer[kBufferSize];
135 MacroAssembler masm(isolate, BuiltinAssemblerOptions(isolate, builtin),
138 masm.set_builtin(builtin);
139 DCHECK(!masm.has_frame());
143 int handler_table_offset = 0;
152 &masm, 0, isolate->builtins()->js_entry_handler_offset());
153#if V8_ENABLE_DRUMBRAKE
154 }
else if (builtin == Builtin::kWasmInterpreterCWasmEntry) {
158 isolate->builtins()->cwasm_interpreter_entry_handler_offset());
161#if V8_ENABLE_WEBASSEMBLY && \
162 (V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_IA32 || \
163 V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_RISCV64 || V8_TARGET_ARCH_LOONG64 || \
164 V8_TARGET_ARCH_PPC64 || V8_TARGET_ARCH_S390X || V8_TARGET_ARCH_RISCV32)
165 if (builtin == Builtin::kWasmReturnPromiseOnSuspendAsm) {
168 &masm, 0, isolate->builtins()->jspi_prompt_handler_offset());
173 masm.GetCode(isolate->main_thread_local_isolate(), &desc,
176 DirectHandle<Code> code =
177 Factory::CodeBuilder(isolate, desc, CodeKind::BUILTIN)
178 .set_self_reference(masm.CodeObject())
179 .set_builtin(builtin)
181#if defined(V8_OS_WIN64)
182 isolate->SetBuiltinUnwindData(builtin, masm.GetUnwindInfo());
188 Address builtin_address,
const char* name) {
189 HandleScope scope(isolate);
190 uint8_t buffer[kBufferSize];
191 MacroAssembler masm(isolate, BuiltinAssemblerOptions(isolate, builtin),
194 masm.set_builtin(builtin);
195 DCHECK(!masm.has_frame());
199 masm.GetCode(isolate, &desc);
200 DirectHandle<Code> code =
201 Factory::CodeBuilder(isolate, desc, CodeKind::BUILTIN)
202 .set_self_reference(masm.CodeObject())
203 .set_builtin(builtin)
204 .set_parameter_count(formal_parameter_count)
211 Isolate* isolate,
Builtin builtin,
214 HandleScope scope(isolate);
215 DirectHandle<Code> code =
217 isolate, builtin, generator,
222 name, BuiltinAssemblerOptions(isolate, builtin));
226void CompileJSLinkageCodeStubBuiltin(Isolate* isolate,
Builtin builtin,
227 CodeAssemblerGenerator generator,
228 CodeAssemblerInstaller installer,
int argc,
229 const char* name,
int finalize_order,
230 BuiltinCompilationScheduler& scheduler) {
233 USE(&BuildWithTurboshaftAssemblerJS);
234 std::unique_ptr<TurbofanCompilationJob> job(
236 isolate, builtin, generator, installer,
237 BuiltinAssemblerOptions(isolate, builtin), argc, name,
239 scheduler.CompileCode(isolate, std::move(job));
244 Isolate* isolate,
Builtin builtin,
247 HandleScope scope(isolate);
248 DirectHandle<Code> code =
250 isolate, builtin, generator,
251 [interface_descriptor](
Zone* zone) {
252 CallInterfaceDescriptor descriptor(interface_descriptor);
253 DCHECK_LE(0, descriptor.GetRegisterParameterCount());
255 zone, descriptor, descriptor.GetStackParameterCount(),
259 name, BuiltinAssemblerOptions(isolate, builtin));
264void CompileCSLinkageCodeStubBuiltin(Isolate* isolate,
Builtin builtin,
265 CodeAssemblerGenerator generator,
266 CodeAssemblerInstaller installer,
268 const char* name,
int finalize_order,
269 BuiltinCompilationScheduler& scheduler) {
272 USE(&BuildWithTurboshaftAssemblerCS);
273 std::unique_ptr<TurbofanCompilationJob> job(
275 isolate, builtin, generator, installer,
276 BuiltinAssemblerOptions(isolate, builtin), interface_descriptor, name,
278 scheduler.CompileCode(isolate, std::move(job));
281void CompileBytecodeHandler(
285 BuiltinCompilationScheduler& scheduler) {
289 operand_scale](compiler::CodeAssemblerState*
state) {
292 std::unique_ptr<TurbofanCompilationJob> job(
294 isolate, builtin, generator, installer,
295 BuiltinAssemblerOptions(isolate, builtin), name,
297 scheduler.CompileCode(isolate, std::move(job));
306 builtins->set_code(builtin, code);
314 Builtins* builtins = isolate->builtins();
326 Builtins* builtins = isolate->builtins();
328 static const int kRelocMask =
339 istream.
address(), istream->Size(),
341 bool flush_icache =
false;
343 code->constant_pool(), kRelocMask);
344 !it.
done(); it.next()) {
352 if (!target_code->is_builtin())
continue;
359 if (!IsCode(
object, cage_base))
continue;
361 if (!target->is_builtin())
continue;
370 code->instruction_size());
377 Builtins* builtins = isolate->builtins();
378 DCHECK(!builtins->initialized_);
380 if (
v8_flags.dump_builtins_hashes_to_file) {
382 std::ofstream(
v8_flags.dump_builtins_hashes_to_file, std::ios_base::trunc);
393 auto install_generated_builtin = [&generated_builtins,
isolate](
400 int builtins_built_without_job_count = 0;
401 int job_creation_order = 0;
402 BuiltinCompilationScheduler scheduler;
405#define BUILD_CPP_WITHOUT_JOB(Name, Argc) \
406 code = BuildAdaptor(isolate, Builtin::k##Name, \
407 FUNCTION_ADDR(Builtin_##Name), #Name); \
408 generated_builtins[Builtins::ToInt(Builtin::k##Name)] = \
409 handle(code, isolate); \
410 builtins_built_without_job_count++;
412#define BUILD_TSJ_WITHOUT_JOB(Name, Argc, ...) \
413 code = BuildWithTurboshaftAssemblerJS( \
414 isolate, Builtin::k##Name, &Builtins::Generate_##Name, Argc, #Name); \
415 AddBuiltin(builtins, Builtin::k##Name, code); \
416 builtins_built_without_job_count++;
418#define BUILD_TFJ_WITH_JOB(Name, Argc, ...) \
419 CompileJSLinkageCodeStubBuiltin(isolate, Builtin::k##Name, \
420 &Builtins::Generate_##Name, \
421 install_generated_builtin, Argc, #Name, \
422 job_creation_order++, scheduler);
424#define BUILD_TSC_WITHOUT_JOB(Name, InterfaceDescriptor) \
426 code = BuildWithTurboshaftAssemblerCS( \
427 isolate, Builtin::k##Name, &Builtins::Generate_##Name, \
428 CallDescriptors::InterfaceDescriptor, #Name); \
429 generated_builtins[Builtins::ToInt(Builtin::k##Name)] = \
430 handle(code, isolate); \
431 builtins_built_without_job_count++;
433#define BUILD_TFC_WITH_JOB(Name, InterfaceDescriptor) \
435 CompileCSLinkageCodeStubBuiltin( \
436 isolate, Builtin::k##Name, &Builtins::Generate_##Name, \
437 install_generated_builtin, CallDescriptors::InterfaceDescriptor, #Name, \
438 job_creation_order++, scheduler);
440#define BUILD_TFS_WITH_JOB(Name, ...) \
442 CompileCSLinkageCodeStubBuiltin( \
443 isolate, Builtin::k##Name, &Builtins::Generate_##Name, \
444 install_generated_builtin, CallDescriptors::Name, #Name, \
445 job_creation_order++, scheduler);
447#define BUILD_TFH_WITH_JOB(Name, InterfaceDescriptor) \
449 CompileCSLinkageCodeStubBuiltin( \
450 isolate, Builtin::k##Name, &Builtins::Generate_##Name, \
451 install_generated_builtin, CallDescriptors::InterfaceDescriptor, #Name, \
452 job_creation_order++, scheduler);
454#define BUILD_BCH_WITH_JOB(Name, OperandScale, Bytecode) \
455 CompileBytecodeHandler(isolate, Builtin::k##Name, OperandScale, Bytecode, \
456 install_generated_builtin, job_creation_order++, \
459#define BUILD_ASM_WITHOUT_JOB(Name, InterfaceDescriptor) \
460 code = BuildWithMacroAssembler(isolate, Builtin::k##Name, \
461 Builtins::Generate_##Name, #Name); \
462 generated_builtins[Builtins::ToInt(Builtin::k##Name)] = \
463 handle(code, isolate); \
464 builtins_built_without_job_count++;
477#undef BUILD_CPP_WITHOUT_JOB
478#undef BUILD_TSJ_WITHOUT_JOB
479#undef BUILD_TFJ_WITH_JOB
480#undef BUILD_TSC_WITHOUT_JOB
481#undef BUILD_TFC_WITH_JOB
482#undef BUILD_TFS_WITH_JOB
483#undef BUILD_TFH_WITH_JOB
484#undef BUILD_BCH_WITH_JOB
485#undef BUILD_ASM_WITHOUT_JOB
488 scheduler.AwaitAndFinalizeCurrentBatch(isolate);
490 scheduler.builtins_installed_count());
501 builtins->MarkInitialized();
#define BUILTIN_LIST_C(V)
interpreter::Bytecode bytecode
#define FORWARD_DECLARE(Name, Argc)
static constexpr SafepointTableBuilderBase * kNoSafepointTable
static V8_EXPORT_PRIVATE Kind KindOf(Builtin builtin)
static constexpr bool IsJSEntryVariant(Builtin builtin)
static constexpr int kBuiltinCount
static constexpr Builtin kFirst
static int GetFormalParameterCount(Builtin builtin)
static void Generate_Adaptor(MacroAssembler *masm, int formal_parameter_count, Address builtin_address)
static constexpr bool IsIsolateIndependent(Builtin builtin)
static constexpr int ToInt(Builtin id)
static constexpr Builtin kLast
static V8_EXPORT_PRIVATE const char * name(Builtin builtin)
static Tagged< Code > FromTargetAddress(Address address)
static void EmitReturnEntry(Assembler *masm, int offset, int handler)
static int EmitReturnTableStart(Assembler *masm)
static const ProfileDataFromFile * TryRead(const char *name)
static constexpr bool IsRelativeCodeTarget(Mode mode)
static constexpr bool IsCodeTargetMode(Mode mode)
static constexpr int ModeMask(Mode mode)
V8_INLINE Address target_address()
static constexpr bool IsEmbeddedObjectMode(Mode mode)
V8_INLINE Tagged< HeapObject > target_object(PtrComprCageBase cage_base)
@ COMPRESSED_EMBEDDED_OBJECT
static void SetupBuiltinsInternal(Isolate *isolate)
static void ReplacePlaceholders(Isolate *isolate)
static void PopulateWithPlaceholders(Isolate *isolate)
static void AddBuiltin(Builtins *builtins, Builtin builtin, Tagged< Code > code)
static constexpr Tagged< Smi > zero()
static ThreadId Current()
static WritableJitAllocation LookupJitAllocation(Address addr, size_t size, JitAllocationType type, bool enforce_write_api=false)
V8_INLINE void set_target_object(Tagged< InstructionStream > host, Tagged< HeapObject > target, WriteBarrierMode write_barrier_mode=UPDATE_WRITE_BARRIER, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
void set_target_address(Tagged< InstructionStream > host, Address target, WriteBarrierMode write_barrier_mode=UPDATE_WRITE_BARRIER, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
static CallDescriptor * GetStubCallDescriptor(Zone *zone, const CallInterfaceDescriptor &descriptor, int stack_parameter_count, CallDescriptor::Flags flags, Operator::Properties properties=Operator::kNoProperties, StubCallMode stub_mode=StubCallMode::kCallCodeObject)
static CallDescriptor * GetJSCallDescriptor(Zone *zone, bool is_osr, int parameter_count, CallDescriptor::Flags flags, Operator::Properties properties=Operator::kNoProperties)
static std::unique_ptr< TurbofanCompilationJob > NewBytecodeHandlerCompilationJob(Isolate *isolate, Builtin builtin, CodeAssemblerGenerator generator, CodeAssemblerInstaller installer, const AssemblerOptions &assembler_options, const char *name, const ProfileDataFromFile *profile_data, int finalize_order)
std::function< void(Builtin builtin, Handle< Code > code)> CodeAssemblerInstaller
static std::unique_ptr< TurbofanCompilationJob > NewCSLinkageCodeStubBuiltinCompilationJob(Isolate *isolate, Builtin builtin, CodeAssemblerGenerator generator, CodeAssemblerInstaller installer, const AssemblerOptions &assembler_options, CallDescriptors::Key interface_descriptor, const char *name, const ProfileDataFromFile *profile_data, int finalize_order)
std::function< void(compiler::CodeAssemblerState *)> CodeAssemblerGenerator
static std::unique_ptr< TurbofanCompilationJob > NewJSLinkageCodeStubBuiltinCompilationJob(Isolate *isolate, Builtin builtin, CodeAssemblerGenerator generator, CodeAssemblerInstaller installer, const AssemblerOptions &assembler_options, int argc, const char *name, const ProfileDataFromFile *profile_data, int finalize_order)
static bool BytecodeHasHandler(Bytecode bytecode, OperandScale operand_scale)
static bool IsWasmBuiltinId(Builtin id)
DirectHandle< Object > new_target
DirectHandle< JSReceiver > options
LiftoffAssembler::CacheState state
DirectHandle< Code > BuildWithTurboshaftAssemblerImpl(Isolate *isolate, Builtin builtin, TurboshaftAssemblerGenerator generator, std::function< compiler::CallDescriptor *(Zone *)> call_descriptor_builder, const char *name, const AssemblerOptions &options, CodeKind code_kind, std::optional< BytecodeHandlerData > bytecode_handler_data)
void(*)(compiler::turboshaft::PipelineData *, Isolate *, compiler::turboshaft::Graph &, Zone *) TurboshaftAssemblerGenerator
void GenerateBytecodeHandler(compiler::CodeAssemblerState *state, Bytecode bytecode, OperandScale operand_scale)
Tagged(T object) -> Tagged< T >
void FlushInstructionCache(void *start, size_t size)
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
refactor address components for immediate indexing make OptimizeMaglevOnNextCall optimize to turbofan instead of maglev filter for tracing turbofan compilation trace turbo cfg trace TurboFan s graph trimmer trace TurboFan s control equivalence trace TurboFan s register allocator trace stack load store counters for optimized code in run fuzzing &&concurrent_recompilation trace_turbo trace_turbo_scheduled trace_turbo_stack_accesses verify TurboFan machine graph of code stubs enable FixedArray bounds checks print TurboFan statistics of wasm compilations maximum cumulative size of bytecode considered for inlining scale factor of bytecode size used to calculate the inlining budget * KB
constexpr size_t kMaxPCRelativeCodeRangeInMB
V8_EXPORT_PRIVATE FlagValues v8_flags
constexpr Register kJavaScriptCallCodeStartRegister
std::unique_ptr< AssemblerBuffer > ExternalAssemblerBuffer(void *start, int size)
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
#define BUILD_TFJ_WITH_JOB(Name, Argc,...)
#define BUILD_TSJ_WITHOUT_JOB(Name, Argc,...)
#define BUILD_BCH_WITH_JOB(Name, OperandScale, Bytecode)
#define BUILD_TFC_WITH_JOB(Name, InterfaceDescriptor)
#define BUILD_TSC_WITHOUT_JOB(Name, InterfaceDescriptor)
#define BUILD_ASM_WITHOUT_JOB(Name, InterfaceDescriptor)
#define BUILD_CPP_WITHOUT_JOB(Name, Argc)
#define BUILD_TFH_WITH_JOB(Name, InterfaceDescriptor)
#define BUILD_TFS_WITH_JOB(Name,...)
#define DCHECK_LE(v1, v2)
#define DCHECK_IMPLIES(v1, v2)
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
static AssemblerOptions Default(Isolate *isolate)