22size_t EmitSection(
SectionCode code, ZoneBuffer* buffer) {
24 buffer->write_u8(code);
27 return buffer->reserve_u32v();
31void FixupSection(ZoneBuffer* buffer,
size_t start) {
32 buffer->patch_u32v(
start,
static_cast<uint32_t
>(buffer->offset() -
start -
39 return kExprGlobalGet;
49 return kExprS128Const;
67 return kExprStructNew;
69 return kExprStructNewDefault;
73 return kExprArrayNewDefault;
75 return kExprArrayNewFixed;
79 return kExprStringConst;
81 return kExprAnyConvertExtern;
83 return kExprExternConvertAny;
87void WriteInitializerExpressionWithoutEnd(ZoneBuffer* buffer,
88 const WasmInitExpr& init) {
89 switch (init.kind()) {
91 buffer->write_u8(kExprI32Const);
92 buffer->write_i32v(init.immediate().i32_const);
95 buffer->write_u8(kExprI64Const);
96 buffer->write_i64v(init.immediate().i64_const);
99 buffer->write_u8(kExprF32Const);
100 buffer->write_f32(init.immediate().f32_const);
103 buffer->write_u8(kExprF64Const);
104 buffer->write_f64(init.immediate().f64_const);
107 buffer->write_u8(kSimdPrefix);
108 buffer->write_u8(kExprS128Const & 0xFF);
109 buffer->write(init.immediate().s128_const.data(),
kSimd128Size);
117 WriteInitializerExpressionWithoutEnd(buffer, (*init.operands())[0]);
118 WriteInitializerExpressionWithoutEnd(buffer, (*init.operands())[1]);
119 buffer->write_u8(FromInitExprOperator(init.kind()));
122 buffer->write_u8(kExprGlobalGet);
123 buffer->write_u32v(init.immediate().index);
126 buffer->write_u8(kExprRefNull);
127 if (init.heap_type().encoding_needs_exact()) buffer->write_u8(
kExactCode);
128 buffer->write_i32v(init.heap_type().code());
131 buffer->write_u8(kExprRefFunc);
132 buffer->write_u32v(init.immediate().index);
138 if (init.operands() !=
nullptr) {
139 for (
const WasmInitExpr& operand : *init.operands()) {
140 WriteInitializerExpressionWithoutEnd(buffer, operand);
143 WasmOpcode opcode = FromInitExprOperator(init.kind());
146 buffer->write_u8(kGCPrefix);
147 buffer->write_u8(
static_cast<uint8_t
>(opcode));
148 buffer->write_u32v(init.immediate().index);
152 static_assert((kExprArrayNewFixed >> 8) == kGCPrefix);
153 static_assert((kExprArrayNewFixed & 0x80) == 0);
154 for (
const WasmInitExpr& operand : *init.operands()) {
155 WriteInitializerExpressionWithoutEnd(buffer, operand);
157 buffer->write_u8(kGCPrefix);
158 buffer->write_u8(
static_cast<uint8_t
>(kExprArrayNewFixed));
159 buffer->write_u32v(init.immediate().index);
160 buffer->write_u32v(
static_cast<uint32_t
>(init.operands()->size()));
166 WriteInitializerExpressionWithoutEnd(buffer, (*init.operands())[0]);
167 WasmOpcode opcode = FromInitExprOperator(init.kind());
170 buffer->write_u8(kGCPrefix);
171 buffer->write_u8(opcode);
175 buffer->write_u8(kGCPrefix);
176 buffer->write_u32v(kExprStringConst & 0xFF);
177 buffer->write_u32v(init.immediate().index);
182void WriteInitializerExpression(ZoneBuffer* buffer,
const WasmInitExpr& init) {
183 WriteInitializerExpressionWithoutEnd(buffer, init);
184 buffer->write_u8(kExprEnd);
193 body_(builder->zone(), 256),
194 i32_temps_(builder->zone()),
195 i64_temps_(builder->zone()),
196 f32_temps_(builder->zone()),
197 f64_temps_(builder->zone()),
198 direct_calls_(builder->zone()),
199 asm_offsets_(builder->zone(), 8) {}
254 if (opcode > 0xFFFF) {
265 const uint8_t immediate) {
271 const uint8_t imm2) {
292void WriteValueType(ZoneBuffer* buffer,
const ValueType& type) {
293 buffer->write_u8(type.value_type_code());
294 if (type.encoding_needs_shared()) {
297 if (type.encoding_needs_heap_type()) {
298 WriteHeapType(buffer, type.heap_type());
304 WriteHeapType(&
body_, type);
308 WriteValueType(&
body_, type);
333 call.direct_index =
index;
341 WriteInitializerExpression(&
body_, init_expr);
349 size_t to_number_position) {
354 uint32_t byte_offset =
static_cast<uint32_t
>(
body_.
size());
358 DCHECK_GE(std::numeric_limits<uint32_t>::max(), call_position);
359 uint32_t call_position_u32 =
static_cast<uint32_t
>(call_position);
362 DCHECK_GE(std::numeric_limits<uint32_t>::max(), to_number_position);
363 uint32_t to_number_position_u32 =
static_cast<uint32_t
>(to_number_position);
369 size_t function_position) {
371 DCHECK_GE(std::numeric_limits<uint32_t>::max(), function_position);
372 uint32_t function_position_u32 =
static_cast<uint32_t
>(function_position);
382 uint8_t hint_byte =
static_cast<uint8_t
>(strategy) |
383 static_cast<uint8_t
>(baseline) << 2 |
384 static_cast<uint8_t
>(
top_tier) << 4;
402 uint8_t** ptr = buffer->
pos_ptr();
404 (*ptr) += locals_size;
423 size_t func_start_size =
437 function_imports_(zone),
438 global_imports_(zone),
443 data_segments_(zone),
444 element_segments_(zone),
447 signature_map_(zone),
448 current_recursive_group_start_(-1),
449 recursive_groups_(zone),
450 start_function_index_(-1) {}
469 for (uint32_t
i = 0;
i <
size;
i++) {
479 for (uint32_t
i = 0;
i <
size;
i++) {
488 types_.emplace_back(
sig, supertype, is_final,
false);
503 uint32_t except_index =
static_cast<uint32_t
>(
tags_.size());
504 tags_.push_back(type_index);
511 uint32_t index =
static_cast<uint32_t
>(
types_.size());
512 types_.emplace_back(type, supertype, is_final,
false);
518 uint32_t index =
static_cast<uint32_t
>(
types_.size());
519 types_.emplace_back(type, supertype, is_final,
false);
526 uint32_t old_min_size =
tables_[table_index].min_size;
528 return std::numeric_limits<uint32_t>::max();
531 tables_[table_index].max_size =
532 std::max(old_min_size +
count,
tables_[table_index].max_size);
537 tables_.push_back({.type =
type, .min_size = min_size});
538 return static_cast<uint32_t
>(
tables_.size() - 1);
545 .min_size = min_size,
546 .max_size = max_size,
548 .address_type = address_type});
549 return static_cast<uint32_t
>(
tables_.size() - 1);
556 .min_size = min_size,
557 .max_size = max_size,
559 .address_type = address_type,
561 return static_cast<uint32_t
>(
tables_.size() - 1);
565 memories_.push_back({.min_pages = min_pages});
566 return static_cast<uint32_t
>(
memories_.size() - 1);
571 {.min_pages = min_pages, .max_pages = max_pages, .has_max_pages =
true});
572 return static_cast<uint32_t
>(
memories_.size() - 1);
578 return static_cast<uint32_t
>(
memories_.size() - 1);
582 uint32_t max_pages) {
583 memories_.push_back({.min_pages = min_pages,
584 .max_pages = max_pages,
585 .has_max_pages =
true,
587 return static_cast<uint32_t
>(
memories_.size() - 1);
596 uint32_t table_index, uint32_t index_in_table,
597 uint32_t direct_function_index,
603 direct_function_index);
610 DCHECK(adding_imports_allowed_);
621 .type_code = type.value_type_code(),
622 .mutability = mutability});
632 DCHECK_LE(index, std::numeric_limits<int>::max());
634 {.name =
name, .kind =
kind, .index =
static_cast<int>(
index)});
640 uint32_t index =
AddGlobal(type, mutability, init);
649 adding_imports_allowed_ =
false;
659 globals_.push_back({.type =
type, .mutability = mutability, .init = init});
660 return static_cast<uint32_t
>(
globals_.size() - 1);
685 while (next_rec_group &&
i == next_rec_group->
start_index) {
690 : next_rec_group + 1;
695 if (type.supertype.valid()) {
700 }
else if (!type.is_final) {
709 for (
auto param :
sig->parameters()) {
710 WriteValueType(buffer, param);
713 for (
auto ret :
sig->returns()) {
714 WriteValueType(buffer, ret);
719 const StructType* struct_type = type.struct_type;
722 for (uint32_t j = 0; j < struct_type->
field_count(); j++) {
723 WriteValueType(buffer, struct_type->
field(j));
729 const ArrayType* array_type = type.array_type;
736 const ContType* cont_type = type.cont_type;
745 while (next_rec_group) {
754 FixupSection(buffer,
start);
766 buffer->
write_u8(
import.mutability ? 1 : 0);
774 FixupSection(buffer,
start);
778 uint32_t num_function_names = 0;
783 function->WriteSignature(buffer);
784 if (!function->name_.empty()) ++num_function_names;
786 FixupSection(buffer,
start);
798 WriteValueType(buffer, table.type);
799 uint8_t limits_byte = (table.is_table64() ? 4 : 0) |
800 (table.is_shared ? 2 : 0) |
801 (table.has_maximum ? 1 : 0);
803 auto WriteValToBuffer = [&](uint32_t val) {
806 WriteValToBuffer(table.min_size);
807 if (table.has_maximum) {
808 WriteValToBuffer(table.max_size);
811 WriteInitializerExpression(buffer, *table.init);
814 FixupSection(buffer,
start);
822 uint8_t limits_byte = (memory.is_memory64() ? 4 : 0) |
823 (memory.is_shared ? 2 : 0) |
824 (memory.has_max_pages ? 1 : 0);
826 auto WriteValToBuffer = [&](uint32_t val) {
827 memory.is_memory64() ? buffer->
write_u64v(val)
830 WriteValToBuffer(memory.min_pages);
831 if (memory.has_max_pages) {
832 WriteValToBuffer(memory.max_pages);
835 FixupSection(buffer,
start);
839 if (!
tags_.empty()) {
846 FixupSection(buffer,
start);
855 WriteValueType(buffer, global.type);
856 buffer->
write_u8(global.mutability ? 1 : 0);
857 WriteInitializerExpression(buffer, global.init);
859 FixupSection(buffer,
start);
886 FixupSection(buffer,
start);
893 FixupSection(buffer,
start);
910 uint8_t expressions_as_elements_mask = 0b100;
911 buffer->
write_u8(kind_mask | expressions_as_elements_mask);
914 WriteInitializerExpression(buffer, segment.
offset);
916 WriteValueType(buffer, segment.type);
925 bool needs_function_offset =
926 segment.indexing_mode ==
930 entry.
index + (needs_function_offset
938 FixupSection(buffer,
start);
951 bool emit_compilation_hints =
false;
954 emit_compilation_hints =
true;
958 if (emit_compilation_hints) {
973 FixupSection(buffer,
start);
981 function->WriteBody(buffer);
983 FixupSection(buffer,
start);
1003 FixupSection(buffer,
start);
1021 buffer->
write_size(num_imports + num_function_names);
1022 uint32_t function_index = 0;
1023 for (; function_index < num_imports; ++function_index) {
1025 DCHECK(!import->name.empty());
1029 if (num_function_names > 0) {
1033 if (!function->name_.empty()) {
1040 FixupSection(buffer, functions_start);
1041 FixupSection(buffer,
start);
1050 function->WriteAsmWasmOffsetTable(buffer);
void push_back(const T &value)
ValueType element_type() const
ModuleTypeIndex contfun_typeindex() const
static size_t sizeof_u32v(size_t val)
void set_sig(const FunctionSig *s)
size_t Emit(uint8_t *buffer) const
uint32_t AddLocals(uint32_t count, ValueType type)
bool mutability(uint32_t index) const
uint32_t field_count() const
ValueType field(uint32_t index) const
void EmitHeapType(HeapType type)
void EmitTeeLocal(uint32_t index)
void SetCompilationHint(WasmCompilationHintStrategy strategy, WasmCompilationHintTier baseline, WasmCompilationHintTier top_tier)
void EmitFromInitializerExpression(const WasmInitExpr &init_expr)
void EmitGetLocal(uint32_t index)
void EmitF64Const(double val)
void EmitValueType(ValueType type)
void EmitF32Const(float val)
ModuleTypeIndex sig_index() const
void SetSignature(const FunctionSig *sig)
ModuleTypeIndex signature_index_
uint32_t last_asm_byte_offset_
void EmitU32V(uint32_t val)
void EmitWithU8U8(WasmOpcode opcode, const uint8_t imm1, const uint8_t imm2)
void EmitDirectCallIndex(uint32_t index)
void EmitWithI32V(WasmOpcode opcode, int32_t immediate)
void WriteAsmWasmOffsetTable(ZoneBuffer *buffer) const
void EmitWithPrefix(WasmOpcode opcode)
WasmModuleBuilder * builder_
void SetAsmFunctionStartPosition(size_t function_position)
void EmitI32V(int32_t val)
void EmitCode(const uint8_t *code, uint32_t code_size)
WasmFunctionBuilder(WasmModuleBuilder *builder)
void AddAsmWasmOffset(size_t call_position, size_t to_number_position)
void EmitSetLocal(uint32_t index)
uint32_t last_asm_source_position_
uint32_t asm_func_start_source_position_
void EmitU64V(uint64_t val)
void EmitWithU32V(WasmOpcode opcode, uint32_t immediate)
void EmitI64Const(int64_t val)
void EmitWithU8(WasmOpcode opcode, const uint8_t immediate)
void SetName(base::Vector< const char > name)
void WriteBody(ZoneBuffer *buffer) const
void EmitI32Const(int32_t val)
void WriteSignature(ZoneBuffer *buffer) const
base::Vector< const char > name_
ZoneVector< DirectCallIndex > direct_calls_
uint32_t AddLocal(ValueType type)
void DeleteCodeAfter(size_t position)
void Emit(WasmOpcode opcode)
ZoneVector< Entry > entries
FunctionIndexingMode indexing_mode
@ kRelativeToDeclaredFunctions
ModuleTypeIndex AddSignature(const FunctionSig *sig, bool is_final, ModuleTypeIndex supertype=kNoSuperType)
uint32_t AddImport(base::Vector< const char > name, const FunctionSig *sig, base::Vector< const char > module={})
ZoneUnorderedMap< FunctionSig, ModuleTypeIndex > signature_map_
void AddExport(base::Vector< const char > name, ImportExportKindCode kind, uint32_t index)
WasmModuleBuilder(Zone *zone)
ZoneVector< ModuleTypeIndex > tags_
ModuleTypeIndex AddArrayType(ArrayType *type, bool is_final, ModuleTypeIndex supertype=kNoSuperType)
uint32_t AddGlobal(ValueType type, bool mutability, WasmInitExpr init)
uint32_t AddTag(const FunctionSig *type)
uint32_t AddElementSegment(WasmElemSegment segment)
void WriteTo(ZoneBuffer *buffer) const
ModuleTypeIndex ForceAddSignature(const FunctionSig *sig, bool is_final, ModuleTypeIndex supertype=kNoSuperType)
void MarkStartFunction(WasmFunctionBuilder *builder)
uint32_t IncreaseTableMinSize(uint32_t table_index, uint32_t count)
int start_function_index_
uint32_t AddMemory64(uint32_t min_pages)
ZoneVector< WasmTable > tables_
uint32_t AddMemory(uint32_t min_pages)
void AddDataSegment(const uint8_t *data, uint32_t size, uint32_t dest)
void ExportImportedFunction(base::Vector< const char > name, int import_index)
ZoneVector< WasmGlobalImport > global_imports_
WasmFunctionBuilder * AddFunction(const FunctionSig *sig=nullptr)
uint32_t AddTable(ValueType type, uint32_t min_size)
ZoneVector< WasmExport > exports_
ZoneVector< RecGroup > recursive_groups_
ModuleTypeIndex AddStructType(StructType *type, bool is_final, ModuleTypeIndex supertype=kNoSuperType)
ZoneVector< WasmMemory > memories_
ZoneVector< WasmElemSegment > element_segments_
void SetIndirectFunction(uint32_t table_index, uint32_t index_in_table, uint32_t direct_function_index, WasmElemSegment::FunctionIndexingMode indexing_mode)
ZoneVector< WasmDataSegment > data_segments_
ZoneVector< TypeDefinition > types_
uint32_t AddGlobalImport(base::Vector< const char > name, ValueType type, bool mutability, base::Vector< const char > module={})
ZoneVector< WasmFunctionImport > function_imports_
ZoneVector< WasmFunctionBuilder * > functions_
ZoneVector< WasmGlobal > globals_
void AddPassiveDataSegment(const uint8_t *data, uint32_t size)
void WriteAsmJsOffsetTable(ZoneBuffer *buffer) const
uint32_t AddExportedGlobal(ValueType type, bool mutability, WasmInitExpr init, base::Vector< const char > name)
void write_u64v(uint64_t val)
void write_i32v(int32_t val)
void patch_u32v(size_t offset, uint32_t val)
void write_f64(double val)
void write_u32(uint32_t x)
void write_u32v(uint32_t val)
void write_size(size_t val)
void EnsureSpace(size_t size)
void write_string(base::Vector< const char > name)
void Truncate(size_t size)
void write_f32(float val)
void write_i64v(int64_t val)
void write(const uint8_t *data, size_t size)
Vector< const char > CStrVector(const char *data)
constexpr uint8_t kNoCompilationHint
constexpr uint32_t kWasmMagic
constexpr uint8_t kWasmRecursiveTypeGroupCode
uint32_t max_table_size()
constexpr uint8_t kSharedFlagCode
constexpr uint8_t kWasmSubtypeCode
constexpr uint8_t kWasmContTypeCode
constexpr size_t kPaddedVarInt32Size
constexpr IndependentHeapType kWasmFuncRef
constexpr uint8_t kWasmStructTypeCode
constexpr uint8_t kWasmSubtypeFinalCode
constexpr uint8_t kWasmFunctionTypeCode
constexpr uint8_t kDefaultCompilationHint
constexpr uint32_t kWasmVersion
WasmCompilationHintStrategy
constexpr uint8_t kWasmArrayTypeCode
constexpr size_t kMaxVarInt32Size
constexpr uint32_t kExceptionAttribute
constexpr int kSimd128Size
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
kWasmInternalFunctionIndirectPointerTag kProtectedInstanceDataOffset sig
refactor address components for immediate indexing make OptimizeMaglevOnNextCall optimize to turbofan instead of maglev filter for tracing turbofan compilation nullptr
constexpr uint32_t kMaxUInt32
std::vector< ValueType > locals_
const std::vector< ModuleTypeIndex > & functions_
std::vector< ValueType > globals_
#define DCHECK_LE(v1, v2)
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
ZoneVector< uint8_t > data
enum v8::internal::wasm::WasmModuleBuilder::WasmElemSegment::Entry::Kind kind
const wasm::FunctionBody & body_