26using compiler::CallDescriptor;
27using compiler::Operator;
28using compiler::turboshaft::ConditionWithHint;
31using compiler::turboshaft::Label;
32using compiler::turboshaft::LoadOp;
33using compiler::turboshaft::MemoryRepresentation;
34using TSBlock = compiler::turboshaft::Block;
35using compiler::turboshaft::OpEffects;
38using compiler::turboshaft::RegisterRepresentation;
39using compiler::turboshaft::StoreOp;
40using compiler::turboshaft::TSCallDescriptor;
41using compiler::turboshaft::Tuple;
42using compiler::turboshaft::V;
49 CallInterfaceDescriptor interface_descriptor =
54 interface_descriptor.GetStackParameterCount(),
73 __ NumberConstant(
static_cast<int32_t
>(abort_reason));
75 __ NoContextConstant());
111 return __ Load(exported_function_data,
114 WasmExportedFunctionData::kFunctionIndexOffset);
120 ?
__ BitcastWord32ToWord64(
__ Word32ShiftLeft(
122 :
__ Word64ShiftLeft(
__ ChangeInt32ToInt64(value),
131 template <
typename Descriptor,
typename... Args>
147 template <
typename Descriptor,
typename... Args>
157 return __ Call(call_target, {
args...}, ts_call_descriptor);
176 __ ChangeInt32ToIntPtr(
__ template Projection<0>(add)));
196 switch (type.kind()) {
206 switch (type.heap_representation_non_shared()) {
234 kWasmInternalFunctionIndirectPointerTag,
235 WasmFuncRef::kTrustedInternalOffset));
239 WasmInternalFunction::kExternalOffset));
240 IF (
__ TaggedEqual(maybe_external,
LOAD_ROOT(UndefinedValue))) {
243 Builtin::kWasmInternalFunctionCreateExternal,
246 return maybe_external;
252 switch (type.heap_representation_non_shared()) {
287 kWasmInternalFunctionIndirectPointerTag,
288 WasmFuncRef::kTrustedInternalOffset));
292 WasmInternalFunction::kExternalOffset);
293 IF (
__ TaggedEqual(maybe_external,
LOAD_ROOT(UndefinedValue))) {
296 Builtin::kWasmInternalFunctionCreateExternal,
351 args[0] = implicit_first_arg;
353 descriptor,
OpEffects().CanCallAnything());
355 if (
sig->return_count() == 1) {
357 }
else if (
sig->return_count() > 1) {
358 for (uint32_t
i = 0;
i <
sig->return_count();
i++) {
367 bool set_in_wasm_flag) {
368 const int rets_count =
static_cast<int>(
sig_->return_count());
373 std::optional<ModifyThreadInWasmFlagScope>
374 modify_thread_in_wasm_flag_builder;
375 if (set_in_wasm_flag) {
376 modify_thread_in_wasm_flag_builder.emplace(
this,
Asm());
382 WasmExportedFunctionData::kProtectedInternalOffset));
389 if (
sig_->return_count() == 0) {
391 }
else if (
sig_->return_count() == 1) {
392 jsval = do_conversion ?
ToJS(rets[0],
sig_->GetReturn(), js_context)
395 int32_t return_count =
static_cast<int32_t
>(
sig_->return_count());
402 JSObject::kElementsOffset);
404 for (
int i = 0;
i < return_count; ++
i) {
406 __ StoreFixedArrayElement(fixed_array,
i, value,
414 bool do_conversion =
true,
417 bool set_in_wasm_flag =
true) {
418 const int wasm_param_count =
static_cast<int>(
sig_->parameter_count());
420 __ Bind(
__ NewBlock());
432 JSFunction::kSharedFunctionInfoOffset);
436 kWasmFunctionDataIndirectPointerTag,
437 SharedFunctionInfo::kTrustedFunctionDataOffset));
449 const int args_count = wasm_param_count + 1;
454 bool include_fast_path =
460 for (
int i = 0;
i < wasm_param_count; ++
i) {
466 if (include_fast_path) {
472 for (
int i = 0;
i < wasm_param_count; ++
i) {
478 for (
int i = 0;
i < wasm_param_count; ++
i) {
480 args[
i + 1] = wasm_param;
484 do_conversion, set_in_wasm_flag);
491 for (
int i = 0;
i < wasm_param_count; ++
i) {
494 FromJS(params[
i + 1], js_context,
sig_->GetParam(
i), frame_state);
503 wasm_param =
__ TruncateFloat64ToFloat32(wasm_param);
505 args[
i + 1] = wasm_param;
510 do_conversion, set_in_wasm_flag);
513 if (include_fast_path) {
524 int wasm_count =
static_cast<int>(
sig_->parameter_count());
526 __ Bind(
__ NewBlock());
529 for (
int i = 0;
i < wasm_count; ++
i) {
531 wasm_params[
i] = (
__ Parameter(1 +
i, rep));
536 WasmImportData::kNativeContextOffset);
548 int pushed_count = std::max(expected_arity, wasm_count);
551 bool has_dispatch_handle =
556 (has_dispatch_handle ? 1 : 0));
565 for (
int i = wasm_count;
i < expected_arity; ++
i) {
571 WasmImportData::kCallableOffset);
596#ifdef V8_JS_LINKAGE_INCLUDES_DISPATCH_HANDLE
610 args[0] = callable_node;
613 args[2] = undefined_node;
652 if (
sig_->return_count() <= 1) {
653 val =
sig_->return_count() == 0
654 ?
__ Word32Constant(0)
660 for (
unsigned i = 0;
i <
sig_->return_count(); ++
i) {
661 wasm_values[
i] =
FromJS(
__ LoadFixedArrayElement(fixed_array,
i),
667 if (
sig_->return_count() <= 1) {
675 __ Bind(
__ NewBlock());
681 for (
int i = 0; i < static_cast<int>(
sig_->parameter_count()); ++
i) {
688 param_bytes += type.value_kind_size();
690 int return_bytes = 0;
692 return_bytes += type.value_kind_size();
695 int stack_slot_bytes = std::max(param_bytes, return_bytes);
696 OpIndex values = stack_slot_bytes == 0
697 ?
__ IntPtrConstant(0)
701 for (
size_t i = 0;
i <
sig_->parameter_count(); ++
i) {
707 offset += type.value_kind_size();
711 __ LoadTaggedField(incoming_params[0], WasmImportData::kCallableOffset);
716 kWasmFunctionDataIndirectPointerTag,
717 SharedFunctionInfo::kTrustedFunctionDataOffset));
719 function_data, WasmCapiFunctionData::kEmbedderDataOffset);
722 OpIndex isolate_root =
__ LoadRootRegister();
736 CallC(&host_sig, call_target, {host_data_foreign, values});
740 IF_NOT (
__ WordPtrEqual(return_value,
__ IntPtrConstant(0))) {
741 WasmRethrowExplicitContextDescriptor interface_descriptor;
744 interface_descriptor.GetStackParameterCount(),
755 WasmImportData::kNativeContextOffset);
756 __ Call(rethrow_call_target, {return_value, context}, ts_call_descriptor);
761 size_t return_count =
sig_->return_count();
762 if (return_count == 0) {
763 __ Return(
__ Word32Constant(0));
767 for (
size_t i = 0;
i < return_count; ++
i) {
771 offset += type.value_kind_size();
787 ?
__ Word32ShiftRightArithmetic(value,
790 TruncateWordPtrToWord32(
__ WordPtrShiftRightArithmetic(
795 return __ template LoadField<Float64>(
800 switch (type.kind()) {
806 result =
__ ChangeInt32ToFloat32(
__ UntagSmi(input));
815 result =
__ ChangeInt32ToFloat64(
__ UntagSmi(input));
842 auto done =
__ NewBlock();
843 auto type_error =
__ NewBlock();
846 if (type.is_nullable()) {
847 auto not_null =
__ NewBlock();
848 __ GotoIfNot(
__ TaggedEqual(input,
LOAD_ROOT(NullValue)), not_null);
854 OpIndex check =
__ Uint32LessThan(instance_type,
872 Builtin::kWasmTaggedToFloat64, frame_state.
value(),
875 Builtin::kWasmTaggedToFloat64,
895 Builtin::kWasmTaggedNonSmiToInt32, frame_state.
value(),
931 return frame_state.
valid()
934 :
__ Call(target, {input, context}, ts_call_descriptor);
939 switch (type.kind()) {
942 switch (type.heap_representation_non_shared()) {
945 if (type.kind() ==
kRef) {
972 std::initializer_list<const OpIndex> inputs = {
973 input,
__ IntPtrConstant(
974 IntToSmi(
static_cast<int>(type.raw_bit_field())))};
981 return __ TruncateFloat64ToFloat32(
1007 const int wasm_count =
static_cast<int>(
sig_->parameter_count());
1008 for (
int i = 0;
i < wasm_count; ++
i) {
1010 switch (type.kind()) {
1031#ifdef V8_MAP_PACKING
1033 map_word =
__ BitcastTaggedToWordPtrForTagAndSmiBits(map_word);
1036 map_word,
__ IntPtrConstant(Internals::kMapWordXorMask),
1037 WordRepresentation::UintPtr());
1046#ifdef V8_MAP_PACKING
1047 return UnpackMapWord(map_word);
1055 switch (type.kind()) {
1067 V<Word32> is_heap_number =
__ TaggedEqual(heap_number_map, map);
1068 __ GotoIf(
LIKELY(is_heap_number), done);
1092 for (
size_t i = 0;
i < wasm_params.
size(); ++
i) {
1101 JSFunction::kSharedFunctionInfoOffset);
1111 SharedFunctionInfo::kFlagsOffset);
1112 OpIndex strict_check =
__ Word32BitwiseAnd(
1113 flags,
__ Word32Constant(SharedFunctionInfo::IsNativeBit::kMask |
1114 SharedFunctionInfo::IsStrictBit::kMask));
1119 strict_d = undefined_node;
1130 JSFunction::kContextOffset);
1142 WasmImportData::kNativeContextOffset);
1144 OpIndex promise_ctor =
__ LoadFixedArrayElement(
1148 auto* resolve_call_desc =
1149 GetBuiltinCallDescriptor(Builtin::kPromiseResolve,
__ graph_zone());
1158 static_cast<int32_t
>(MessageTemplate::kWasmSuspendError)));
1163 if (
v8_flags.stress_wasm_stack_switching) {
1165 __ LoadTaggedField(suspender, WasmSuspenderObject::kResumeOffset),
1167 IF (for_stress_testing) {
1169 static_cast<int32_t
>(MessageTemplate::kWasmSuspendJSFrames)));
1179 OpIndex has_js_frames =
__ WordPtrEqual(
__ IntPtrConstant(0), *old_sp);
1180 IF (has_js_frames) {
1182 static_cast<int32_t
>(MessageTemplate::kWasmSuspendJSFrames)));
1189 WasmSuspenderObject::kResumeOffset);
1192 WasmSuspenderObject::kRejectOffset);
1196 auto* then_call_desc =
1197 GetBuiltinCallDescriptor(Builtin::kPerformPromiseThen,
__ graph_zone());
1205 auto* suspend_call_descriptor =
1206 GetBuiltinCallDescriptor(Builtin::kWasmSuspend,
__ graph_zone());
1213 *old_sp = old_sp_var;
1222 iterable, length, context);
1227 int alignment =
offset % type.value_kind_size();
1229 type.machine_representation());
1234 value =
__ BitcastTaggedToWordPtr(value);
1251 WasmFunctionData::kProtectedInternalOffset));
1254 WasmInternalFunction::kRawCallTargetOffset);
1255 constexpr size_t entry_size_log2 =
1258 __ ExternalConstant(ExternalReference::wasm_code_pointer_table()),
1264 int alignment =
offset % type.value_kind_size();
1266 type.machine_representation());
1292 if (wrapper_info.
code_kind == CodeKind::JS_TO_WASM_FUNCTION) {
1294 }
else if (wrapper_info.
code_kind == CodeKind::WASM_TO_JS_FUNCTION) {
1298 }
else if (wrapper_info.
code_kind == CodeKind::WASM_TO_CAPI_FUNCTION) {
#define SBXCHECK_LT(lhs, rhs)
void resize(size_t new_size)
constexpr UnderlyingType & value() &
static CallInterfaceDescriptor CallInterfaceDescriptorFor(Builtin builtin)
auto Returns(ReturnTypes... return_types) const
static constexpr uint32_t thread_in_wasm_flag_address_offset()
static uint32_t c_entry_fp_offset()
static const int kInitialMaxFastElementArray
static constexpr MachineType Pointer()
static constexpr MachineType AnyTagged()
static constexpr Tagged< Smi > FromInt(int value)
static constexpr Tagged< Smi > FromIntptr(intptr_t value)
static FieldAccess ForHeapNumberValue()
static constexpr int GetJSCallContextParamIndex(int parameter_count)
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 constexpr int kJSCallClosureParamIndex
static CallDescriptor * GetJSCallDescriptor(Zone *zone, bool is_osr, int parameter_count, CallDescriptor::Flags flags, Operator::Properties properties=Operator::kNoProperties)
compiler::CallDescriptor * GetBigIntToI64Descriptor(bool needs_frame_state)
static constexpr MemoryRepresentation FromMachineRepresentation(MachineRepresentation rep)
static constexpr MemoryRepresentation AnyTagged()
static constexpr MemoryRepresentation Uint32()
static constexpr MemoryRepresentation TaggedSigned()
static constexpr MemoryRepresentation Int32()
static constexpr MemoryRepresentation Uint16()
static constexpr MemoryRepresentation TaggedPointer()
static constexpr MemoryRepresentation UintPtr()
static constexpr OpIndex Invalid()
constexpr bool valid() const
constexpr OpIndex value() const
static constexpr OptionalOpIndex Nullopt()
constexpr bool valid() const
static constexpr RegisterRepresentation WordPtr()
static constexpr RegisterRepresentation Tagged()
static bool IsUnalignedStoreSupported(MemoryRepresentation repr)
static bool IsUnalignedLoadSupported(MemoryRepresentation repr)
OpIndex Load(OpIndex base, OptionalOpIndex index, LoadOp::Kind kind, MemoryRepresentation loaded_rep, RegisterRepresentation result_rep, int32_t offset=0, uint8_t element_size_log2=0)
OpIndex LoadRootRegister()
static V< T > Cast(V< U > index)
static const int kLastUsedBit
compiler::WasmCallDescriptors * call_descriptors()
V< BigInt > BuildChangeInt64ToBigInt(V< Word64 > input, StubCallMode stub_mode)
RegisterRepresentation RepresentationFor(ValueTypeBase type)
V< WordPtr > BuildSwitchToTheCentralStack(V< WordPtr > old_limit)
std::pair< V< WordPtr >, V< WordPtr > > BuildSwitchToTheCentralStackIfNeeded()
OpIndex GetBuiltinPointerTarget(Builtin builtin)
V< WordPtr > GetTargetForBuiltinCall(Builtin builtin, StubCallMode stub_mode)
std::pair< V< Word32 >, V< ExposedTrustedObject > > BuildFunctionTargetAndImplicitArg(V< WasmInternalFunction > internal_function)
OpIndex CallRuntime(Zone *zone, Runtime::FunctionId f, std::initializer_list< const OpIndex > args, V< Context > context)
void BuildSwitchBackFromCentralStack(V< WordPtr > old_sp, V< WordPtr > old_limit)
void BuildModifyThreadInWasmFlagHelper(Zone *zone, OpIndex thread_in_wasm_flag_address, bool new_value)
OpIndex CallC(const MachineSignature *sig, ExternalReference ref, std::initializer_list< OpIndex > args)
void BuildModifyThreadInWasmFlag(Zone *zone, bool new_value)
ModifyThreadInWasmFlagScope(WasmWrapperTSGraphBuilder *wasm_wrapper_graph_builder, Assembler &asm_)
V< WordPtr > thread_in_wasm_flag_address_
ModifyThreadInWasmFlagScope(const ModifyThreadInWasmFlagScope &)=delete
~ModifyThreadInWasmFlagScope()
WasmWrapperTSGraphBuilder * wasm_wrapper_graph_builder_
OpIndex BuildChangeTaggedToInt32(OpIndex value, OpIndex context, compiler::turboshaft::OptionalOpIndex frame_state)
OpIndex LoadSharedFunctionInfo(V< Object > js_function)
V< Context > LoadContextFromJSFunction(V< JSFunction > js_function)
OpIndex BuildReceiverNode(OpIndex callable_node, OpIndex native_context, V< Undefined > undefined_node)
CallDescriptor * GetBigIntToI64CallDescriptor(bool needs_frame_state)
OpIndex CallBuiltin(Builtin name, Operator::Properties properties, Args... args)
void AbortIfNot(V< Word32 > condition, AbortReason abort_reason)
V< WordPtr > BuildLoadCallTargetFromExportedFunctionData(V< WasmFunctionData > function_data)
V< Word32 > BuildSmiShiftBitsConstant()
bool QualifiesForFastTransform()
void BuildJSToWasmWrapper(bool do_conversion=true, compiler::turboshaft::OptionalOpIndex frame_state=compiler::turboshaft::OptionalOpIndex::Nullopt(), bool set_in_wasm_flag=true)
V< Float64 > BuildChangeTaggedToFloat64(OpIndex value, OpIndex context, compiler::turboshaft::OptionalOpIndex frame_state)
void BuildWasmToJSWrapper(ImportCallKind kind, int expected_arity, Suspend suspend)
OpIndex BuildCheckString(OpIndex input, OpIndex js_context, CanonicalValueType type)
V< Number > BuildChangeFloat64ToNumber(V< Float64 > value)
const OpIndex SafeLoad(OpIndex base, int offset, CanonicalValueType type)
V< Smi > BuildChangeInt32ToSmi(V< Word32 > value)
OpIndex FromJSFast(OpIndex input, CanonicalValueType type)
V< Word32 > BuildChangeSmiToInt32(OpIndex value)
int AddArgumentNodes(base::Vector< OpIndex > args, int pos, base::SmallVector< OpIndex, 16 > wasm_params, const CanonicalSig *sig, V< Context > context)
void CanTransformFast(OpIndex input, CanonicalValueType type, TSBlock *slow_path)
OpIndex BuildCallAndReturn(V< Context > js_context, V< HeapObject > function_data, base::Vector< OpIndex > args, bool do_conversion, bool set_in_wasm_flag)
V< Number > BuildChangeFloat32ToNumber(V< Float32 > value)
WasmWrapperTSGraphBuilder(Zone *zone, Assembler &assembler, const CanonicalSig *sig)
V< FixedArray > BuildMultiReturnFixedArrayFromIterable(OpIndex iterable, V< Context > context)
OpIndex CallBuiltin(Builtin name, OpIndex frame_state, Operator::Properties properties, Args... args)
void SafeStore(int offset, CanonicalValueType type, OpIndex base, OpIndex value)
OpIndex LoadInstanceType(V< Map > map)
V< WordPtr > GetTargetForBuiltinCall(Builtin builtin)
V< Object > ToJS(OpIndex ret, CanonicalValueType type, V< Context > context)
V< Number > BuildChangeInt32ToNumber(V< Word32 > value)
OpIndex BuildChangeBigIntToInt64(OpIndex input, OpIndex context, compiler::turboshaft::OptionalOpIndex frame_state)
void BuildCallWasmFromWrapper(Zone *zone, const CanonicalSig *sig, V< Word32 > callee, V< HeapObject > implicit_first_arg, const base::Vector< OpIndex > args, base::Vector< OpIndex > returns)
V< Map > LoadMap(V< Object > object)
V< Float64 > HeapNumberToFloat64(V< HeapNumber > input)
V< JSArray > BuildCallAllocateJSArray(V< Number > array_length, V< Object > context)
const CanonicalSig *const sig_
V< Object > BuildSuspend(V< Object > value, V< Object > import_data, V< WordPtr > *old_sp, V< WordPtr > old_limit)
V< Smi > LoadExportedFunctionIndexAsSmi(V< Object > exported_function_data)
void BuildCapiCallWrapper()
V< Word32 > BuildSmiShiftBitsConstant32()
OpIndex FromJS(OpIndex input, OpIndex context, CanonicalValueType type, OptionalOpIndex frame_state={})
#define COMPRESS_POINTERS_BOOL
#define V8_JS_LINKAGE_INCLUDES_DISPATCH_HANDLE_BOOL
base::Vector< const DirectHandle< Object > > args
ZoneVector< RpoNumber > & result
constexpr Vector< T > VectorOf(T *start, size_t size)
FloatWithBits< 32 > Float32
WordWithBits< 32 > Word32
std::conditional_t< Is64(), Word64, Word32 > WordPtr
SnapshotTable< OpIndex, VariableData >::Key Variable
FloatWithBits< 64 > Float64
CallDescriptor * GetBuiltinCallDescriptor(Builtin name, Zone *zone, StubCallMode stub_mode, bool needs_frame_state, Operator::Properties properties)
CallDescriptor * GetWasmCallDescriptor(Zone *zone, const Signature< T > *fsig, WasmCallKind call_kind, bool need_frame_state)
bool IsTrapHandlerEnabled()
void BuildWasmWrapper(compiler::turboshaft::PipelineData *data, AccountingAllocator *allocator, compiler::turboshaft::Graph &graph, const wasm::CanonicalSig *sig, WrapperCompilationInfo)
TypeCanonicalizer * GetTypeCanonicalizer()
bool IsJSCompatibleSignature(const CanonicalSig *sig)
compiler::turboshaft::Block TSBlock
constexpr size_t kV8MaxWasmFunctionReturns
WasmEngine * GetWasmEngine()
@ kJSFunctionArityMismatch
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
kWasmInternalFunctionIndirectPointerTag kProtectedInstanceDataOffset sig
constexpr bool SmiValuesAre31Bits()
constexpr JSDispatchHandle kPlaceholderDispatchHandle(0x0)
V8_EXPORT_PRIVATE FlagValues v8_flags
constexpr int JSParameterCount(int param_count_without_receiver)
constexpr bool SmiValuesAre32Bits()
static V8_INLINE constexpr Address IntToSmi(int value)
constexpr intptr_t kDoubleAlignment
!IsContextMap !IsContextMap native_context
i::Address Load(i::Address address)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
static constexpr Kind TaggedBase()
static constexpr Kind RawAligned()
static constexpr Kind RawUnaligned()
const uint16_t input_count
static const TSCallDescriptor * Create(const CallDescriptor *descriptor, CanThrow can_throw, LazyDeoptOnThrow lazy_deopt_on_throw, Zone *graph_zone, const JSWasmCallParameters *js_wasm_call_parameters=nullptr)
wasm::ImportCallKind import_kind