5#ifndef V8_COMPILER_TURBOSHAFT_WASM_LOWERING_REDUCER_H_
6#define V8_COMPILER_TURBOSHAFT_WASM_LOWERING_REDUCER_H_
9#if !V8_ENABLE_WEBASSEMBLY
10#error This header should only be included if WebAssembly is enabled.
34 const
wasm::WasmGlobal* global) {
49#if V8_TARGET_BIG_ENDIAN
52 return __ BitcastWordPtrToTagged(
__ Load(
64#if V8_STATIC_ROOTS_BOOL
67 StaticReadOnlyRootsPointerTable[
static_cast<size_t>(index)]));
68 return __ TaggedEqual(
object, root);
76 type.use_wasm_null() ? RootIndex::kWasmNull : RootIndex::kNullValue;
77 return ReduceRootConstant(index);
82 type.use_wasm_null() ? RootIndex::kWasmNull : RootIndex::kNullValue;
83 return ReduceIsRootConstant(
object, index);
88 if (trap_id == TrapId::kTrapNullDereference) {
90 if (!
v8_flags.experimental_wasm_skip_null_checks) {
97 !type.use_wasm_null()) {
101 static_assert(WasmStruct::kHeaderSize >
kTaggedSize);
102 static_assert(WasmArray::kHeaderSize >
kTaggedSize);
103 static_assert(WasmInternalFunction::kHeaderSize >
kTaggedSize);
124 if (rtt.has_value()) {
133 if (rtt.has_value()) {
144 Label<> int_to_smi_label(&Asm());
145 Label<> heap_number_label(&Asm());
147 constexpr int32_t kInt31MaxValue = 0x3fffffff;
148 constexpr int32_t kInt31MinValue = -kInt31MaxValue - 1;
152 GOTO_IF(
__ HasInstanceType(
object, HEAP_NUMBER_TYPE), heap_number_label);
154 GOTO(end_label,
object);
162 GOTO(end_label,
object);
164 Label<> convert_to_heap_number_label(&Asm());
168 GOTO_IF(
__ Int32LessThan(
__ Word32Constant(kInt31MaxValue), int_value),
169 convert_to_heap_number_label);
170 GOTO_IF(
__ Int32LessThan(int_value,
__ Word32Constant(kInt31MinValue)),
171 convert_to_heap_number_label);
172 GOTO(end_label,
object);
174 BIND(convert_to_heap_number_label);
175 V<Object> heap_number =
__ template WasmCallBuiltinThroughJumptable<
176 BuiltinCallDescriptor::WasmInt32ToHeapNumber>({int_value});
177 GOTO(end_label, heap_number);
181 BIND(heap_number_label);
185 GOTO_IF(
__ Float64LessThan(float_value,
__ Float64Constant(kInt31MinValue)),
187 GOTO_IF(
__ Float64LessThan(
__ Float64Constant(kInt31MaxValue), float_value),
191 if constexpr (
Is64()) {
193 V<Word64> float_bits =
__ BitcastFloat64ToWord64(float_value);
194 is_minus_zero =
__ Word64Equal(float_bits, minus_zero);
198 V<Word32> value_lo =
__ Float64ExtractLowWord32(float_value);
200 done,
__ Word32Constant(0));
201 V<Word32> value_hi =
__ Float64ExtractHighWord32(float_value);
203 BIND(done, phi_is_minus_zero);
204 is_minus_zero = phi_is_minus_zero;
206 GOTO_IF(is_minus_zero, end_label,
object);
209 __ TruncateFloat64ToInt32OverflowUndefined(float_value);
210 GOTO_IF(
__ Float64Equal(float_value,
__ ChangeInt32ToFloat64(int_value)),
212 GOTO(end_label,
object);
214 BIND(int_to_smi_label);
215 GOTO(end_label,
__ TagSmi(int_value));
238 auto [explicit_null_check, implicit_null_check] =
241 if (explicit_null_check) {
243 TrapId::kTrapNullDereference);
248 if (!type->mutability(field_index)) {
261 auto [explicit_null_check, implicit_null_check] =
264 if (explicit_null_check) {
266 TrapId::kTrapNullDereference);
275 __ Store(
object, value, store_kind, repr,
285 bool is_mutable = array_type->mutability();
289 return __ Load(array,
__ ChangeInt32ToIntPtr(index), load_kind,
291 WasmArray::kHeaderSize,
292 array_type->element_type().value_kind_size_log2());
297 __ Store(array,
__ ChangeInt32ToIntPtr(index), value,
300 WasmArray::kHeaderSize, element_type.value_kind_size_log2());
306 bool explicit_null_check =
309 bool implicit_null_check =
313 if (explicit_null_check) {
315 TrapId::kTrapNullDereference);
323 WasmArray::kLengthOffset);
329 __ Uint32LessThanOrEqual(
331 TrapId::kTrapArrayTooLarge);
338 __ Word32Add(
__ Word32Mul(length,
__ Word32Constant(
343 __ ChangeUint32ToUintPtr(
__ Word32Add(
344 padded_length,
__ Word32Constant(WasmArray::kHeaderSize))),
353 __ InitializeField(a, AccessBuilder::ForWasmArrayLength(), length);
377 uint32_t function_index) {
381 __ LoadFixedArrayElement(
func_refs, function_index);
385 bool extract_shared_data =
389 BuiltinCallDescriptor::WasmRefFunc>(
390 {
__ Word32Constant(function_index),
391 __ Word32Constant(extract_shared_data ? 1 : 0)});
393 GOTO(done, from_builtin);
398 BIND(done, result_value);
404 V<Word32> instance_type =
__ LoadInstanceTypeField(
__ LoadMapField(
string));
405 V<Word32> string_representation =
__ Word32BitwiseAnd(
409 GOTO(done,
__ template WasmCallBuiltinThroughJumptable<
410 BuiltinCallDescriptor::WasmStringAsWtf16>({
string}));
419 direct_string(&Asm());
435 __ LoadInstanceTypeField(
__ LoadMapField(original_string));
436 GOTO(dispatch, original_string, original_type,
__ Word32Constant(0));
443 static constexpr int kIsDirectStringTag = 0;
447 direct_string,
string, instance_type,
offset);
459 offset,
__ UntagSmi(
__ template LoadField<Smi>(
463 V<Word32> parent_type =
__ LoadInstanceTypeField(
__ LoadMapField(parent));
464 GOTO(dispatch, parent, parent_type, new_offset);
470 V<Word32> actual_type =
__ LoadInstanceTypeField(
__ LoadMapField(actual));
472 GOTO(direct_string, actual, actual_type,
offset);
479 V<Word32> first_type =
__ LoadInstanceTypeField(
__ LoadMapField(first));
483 BIND(direct_string,
string, instance_type,
offset);
490 __ Word32Sub(1,
__ Word32ShiftRightLogical(is_onebyte, 3));
501 const int chars_start_offset =
505 __ Word32ShiftLeft(
offset, charwidth_shift));
506 GOTO(done,
string,
__ ChangeInt32ToIntPtr(final_offset), charwidth_shift);
517 __ WordPtrAdd(resource,
__ ChangeInt32ToIntPtr(shifted_offset));
522 BIND(done,
base, final_offset, charwidth_shift);
523 return __ Tuple({
base, final_offset, charwidth_shift});
535 switch (type.kind()) {
570 const bool object_can_be_i31 =
592 const int kResult = 1;
594 __ Word32Constant(kResult));
604 if (object_can_be_i31) {
611 if (object_can_be_i31) {
615 result =
__ HasInstanceType(
object, WASM_ARRAY_TYPE);
619 result =
__ HasInstanceType(
object, WASM_STRUCT_TYPE);
625 __ LoadInstanceTypeField(
__ LoadMapField(
object));
626 result =
__ Uint32LessThan(instance_type,
635 BIND(end_label, final_result);
643 const bool object_can_be_i31 =
658 __ TrapIfNot(
__ IsNull(
object, config.
from), TrapId::kTrapIllegalCast);
665 !
v8_flags.experimental_wasm_skip_null_checks) {
672 object_can_be_i31 ?
__ IsSmi(
object) :
__ Word32Constant(0);
673 __ TrapIfNot(success, TrapId::kTrapIllegalCast);
677 if (object_can_be_i31) {
681 TrapId::kTrapIllegalCast);
685 if (object_can_be_i31) {
686 __ TrapIf(
__ IsSmi(
object), TrapId::kTrapIllegalCast);
689 __ TrapIfNot(
__ HasInstanceType(
object, WASM_ARRAY_TYPE),
690 TrapId::kTrapIllegalCast);
694 __ TrapIfNot(
__ HasInstanceType(
object, WASM_STRUCT_TYPE),
695 TrapId::kTrapIllegalCast);
701 __ LoadInstanceTypeField(
__ LoadMapField(
object));
702 __ TrapIfNot(
__ Uint32LessThan(instance_type,
704 TrapId::kTrapIllegalCast);
720 bool object_can_be_i31 =
729 if (object_can_be_null && (!is_cast_from_any || config.
to.is_nullable())) {
731 if (config.
to.is_nullable()) {
733 }
else if (!
v8_flags.experimental_wasm_skip_null_checks) {
734 __ TrapIf(is_null, TrapId::kTrapIllegalCast);
738 if (object_can_be_i31) {
739 __ TrapIf(
__ IsSmi(
object), TrapId::kTrapIllegalCast);
742 V<Map> map =
__ LoadMapField(
object);
748 __ TrapIfNot(
__ TaggedEqual(map, rtt.
value()), TrapId::kTrapIllegalCast);
756 if (is_cast_from_any) {
758 __ TrapIfNot(is_wasm_obj, TrapId::kTrapIllegalCast);
766 if (
static_cast<uint32_t
>(rtt_depth) >=
771 WasmTypeInfo::kSupertypesLengthOffset));
772 __ TrapIfNot(
__ Uint32LessThan(rtt_depth, supertypes_length),
773 TrapId::kTrapIllegalCast);
779 WasmTypeInfo::kSupertypesOffset +
kTaggedSize * rtt_depth);
781 __ TrapIfNot(
__ TaggedEqual(maybe_match, rtt.
value()),
782 TrapId::kTrapIllegalCast);
795 bool object_can_be_i31 =
804 if (object_can_be_null && (!is_cast_from_any || config.
to.is_nullable())) {
805 const int kResult = config.
to.is_nullable() ? 1 : 0;
807 __ Word32Constant(kResult));
810 if (object_can_be_i31) {
814 V<Map> map =
__ LoadMapField(
object);
825 __ Word32Constant(1));
828 if (is_cast_from_any) {
838 if (
static_cast<uint32_t
>(rtt_depth) >=
843 WasmTypeInfo::kSupertypesLengthOffset));
845 end_label,
__ Word32Constant(0));
851 WasmTypeInfo::kSupertypesOffset +
kTaggedSize * rtt_depth);
853 GOTO(end_label,
__ TaggedEqual(maybe_match, rtt.
value()));
864 if (is_mutable && global->
imported) {
871 instance, ImportedMutableGlobalsBuffers,
943 V<Word32> instance_type =
__ LoadInstanceTypeField(map);
947 __ Word32Sub(instance_type, FIRST_WASM_OBJECT_TYPE);
948 return __ Uint32LessThanOrEqual(
949 comparison_value, LAST_WASM_OBJECT_TYPE - FIRST_WASM_OBJECT_TYPE);
953 int offset = Map::kConstructorOrBackPointerOrNativeContextOffset;
960 bool explicit_null_check =
964 bool implicit_null_check =
966 return {explicit_null_check, implicit_null_check};
970 return WasmStruct::kHeaderSize + type->field_offset(field_index);
#define REDUCE(operation)
#define BIND_LOOP(loop_label,...)
#define GOTO_IF_NOT(cond, label,...)
#define GOTO_IF(cond, label,...)
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
static constexpr int OffsetOfElementAt(int index)
static constexpr int root_slot_offset(RootIndex root_index)
static constexpr bool IsReadOnly(RootIndex root_index)
static constexpr Tagged< Smi > FromInt(int value)
static constexpr int OffsetOfElementAt(int index)
static constexpr int MaxLength(uint32_t element_size_bytes)
static int Size(const wasm::StructType *type)
static ElementAccess ForSeqTwoByteStringCharacter()
static FieldAccess ForMap(WriteBarrierKind write_barrier=kMapWriteBarrier)
static ElementAccess ForSeqOneByteStringCharacter()
static FieldAccess ForThinStringActual()
static FieldAccess ForExternalStringResourceData()
static FieldAccess ForSlicedStringParent()
static FieldAccess ForSlicedStringOffset()
static FieldAccess ForJSObjectPropertiesOrHash()
static FieldAccess ForConsStringFirst()
static constexpr MemoryRepresentation AnyTagged()
static constexpr MemoryRepresentation Int8()
static constexpr MemoryRepresentation Float16()
static constexpr MemoryRepresentation Uint32()
static constexpr MemoryRepresentation TaggedSigned()
static constexpr MemoryRepresentation Int32()
static constexpr MemoryRepresentation Int64()
static constexpr MemoryRepresentation Simd128()
static constexpr MemoryRepresentation SandboxedPointer()
static constexpr MemoryRepresentation Uint16()
static constexpr MemoryRepresentation TaggedPointer()
static constexpr MemoryRepresentation UintPtr()
static constexpr MemoryRepresentation Uint8()
static constexpr MemoryRepresentation Int16()
static constexpr MemoryRepresentation Uint64()
static constexpr MemoryRepresentation Float32()
static constexpr MemoryRepresentation Float64()
static constexpr OpIndex Invalid()
constexpr bool has_value() const
constexpr V< T > value() const
static V< T > Cast(V< U > index)
static constexpr MemoryRepresentation kMaybeSandboxedPointer
V< Object > LoadWasmTypeInfo(V< Map > map)
std::pair< bool, bool > null_checks_for_struct_op(CheckForNull null_check, int field_index)
OpIndex REDUCE RootConstant(RootIndex index)
V< Any > REDUCE ArrayGet(V< WasmArrayNullable > array, V< Word32 > index, const wasm::ArrayType *array_type, bool is_signed)
V< None > REDUCE StructSet(V< WasmStructNullable > object, V< Any > value, const wasm::StructType *type, wasm::ModuleTypeIndex type_index, int field_index, CheckForNull null_check)
V< Object > REDUCE ExternConvertAny(V< Object > object)
int field_offset(const wasm::StructType *type, int field_index)
OpIndex REDUCE StringPrepareForGetCodeUnit(V< Object > original_string)
V< Word32 > REDUCE WasmTypeCheck(V< Object > object, OptionalV< Map > rtt, WasmTypeCheckConfig config)
V< Word32 > REDUCE IsRootConstant(OpIndex object, RootIndex index)
V< Word32 > REDUCE ArrayLength(V< WasmArrayNullable > array, CheckForNull null_check)
V< Object > REDUCE WasmTypeCast(V< Object > object, OptionalV< Map > rtt, WasmTypeCheckConfig config)
V< Map > REDUCE RttCanon(V< FixedArray > rtts, wasm::ModuleTypeIndex type_index)
OpIndex REDUCE GlobalSet(V< WasmTrustedInstanceData > instance, V< Any > value, const wasm::WasmGlobal *global)
V< Object > ReduceWasmTypeCastRtt(V< Object > object, OptionalV< Map > rtt, WasmTypeCheckConfig config)
V< Object > ReduceWasmTypeCastAbstract(V< Object > object, WasmTypeCheckConfig config)
V< Word32 > REDUCE IsNull(OpIndex object, wasm::ValueType type)
V< Word32 > ReduceWasmTypeCheckAbstract(V< Object > object, WasmTypeCheckConfig config)
V< Object > REDUCE WasmTypeAnnotation(V< Object > value, wasm::ValueType type)
V< Object > REDUCE AnyConvertExtern(V< Object > object)
const NullCheckStrategy null_check_strategy_
V< Any > REDUCE StructGet(V< WasmStructNullable > object, const wasm::StructType *type, wasm::ModuleTypeIndex type_index, int field_index, bool is_signed, CheckForNull null_check)
V< None > REDUCE ArraySet(V< WasmArrayNullable > array, V< Word32 > index, V< Any > value, wasm::ValueType element_type)
const wasm::WasmModule * module_
V< Word32 > ReduceWasmTypeCheckRtt(V< Object > object, OptionalV< Map > rtt, WasmTypeCheckConfig config)
V< WasmArray > REDUCE WasmAllocateArray(V< Map > rtt, V< Word32 > length, const wasm::ArrayType *array_type)
V< Word32 > IsDataRefMap(V< Map > map)
V< WasmFuncRef > REDUCE WasmRefFunc(V< WasmTrustedInstanceData > wasm_instance, uint32_t function_index)
OpIndex LowerGlobalSetOrGet(V< WasmTrustedInstanceData > instance, V< Any > value, const wasm::WasmGlobal *global, GlobalMode mode)
MemoryRepresentation RepresentationFor(wasm::ValueType type, bool is_signed)
V< String > REDUCE StringAsWtf16(V< String > string)
V< Any > REDUCE GlobalGet(V< WasmTrustedInstanceData > instance, const wasm::WasmGlobal *global)
V< Object > REDUCE AssertNotNull(V< Object > object, wasm::ValueType type, TrapId trap_id)
V< WasmStruct > REDUCE WasmAllocateStruct(V< Map > rtt, const wasm::StructType *struct_type)
constexpr int value_kind_size() const
constexpr bool is_reference() const
constexpr bool is_nullable() const
constexpr bool is_reference_to(HeapType::Representation repr) const
constexpr HeapType::Representation heap_representation() const
#define V8_ENABLE_SANDBOX_BOOL
constexpr int32_t kMinusZeroLoBits
constexpr int64_t kMinusZeroBits
constexpr int32_t kMinusZeroHiBits
#define TURBOSHAFT_REDUCER_BOILERPLATE(Name)
ZoneVector< RpoNumber > & result
std::conditional_t< Is64(), Word64, Word32 > WordPtr
static constexpr int kCharWidthBailoutSentinel
bool IsTrapHandlerEnabled()
int GetSubtypingDepth(const WasmModule *module, ModuleTypeIndex type_index)
constexpr uint32_t kMinimumSupertypeArraySize
constexpr IndependentHeapType kWasmAnyRef
constexpr IndependentHeapType kWasmExternRef
constexpr IndependentValueType kWasmI32
constexpr IndependentHeapType kWasmI31Ref
constexpr int kMaxStructFieldIndexForImplicitNullCheck
V8_INLINE bool IsSubtypeOf(ValueType subtype, ValueType supertype, const WasmModule *sub_module, const WasmModule *super_module)
const uint32_t kStringEncodingMask
constexpr int kTaggedSize
constexpr intptr_t kObjectAlignment
const uint32_t kUncachedExternalStringMask
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
constexpr int kTaggedSizeLog2
constexpr bool SmiValuesAre31Bits()
const uint32_t kStringRepresentationMask
kMemory0SizeOffset Address kNewAllocationLimitAddressOffset Address kOldAllocationLimitAddressOffset uint8_t kGlobalsStartOffset kJumpTableStartOffset std::atomic< uint32_t > kTieringBudgetArrayOffset kDataSegmentStartsOffset kElementSegmentsOffset kInstanceObjectOffset kMemoryObjectsOffset kTaggedGlobalsBufferOffset kTablesOffset kProtectedDispatchTable0Offset kProtectedDispatchTableForImportsOffset func_refs
const uint32_t kIsIndirectStringTag
V8_EXPORT_PRIVATE FlagValues v8_flags
const uint32_t kIsIndirectStringMask
bool is_signed(Condition cond)
template const char * string
i::Address Load(i::Address address)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
ExternalPointerTag external_pointer_tag
static constexpr Kind TaggedBase()
static constexpr Kind RawAligned()
constexpr Kind Immutable() const
static constexpr Kind TrapOnNull()
#define OFFSET_OF_DATA_START(Type)
#define V8_STATIC_ROOTS_BOOL
#define LOAD_IMMUTABLE_INSTANCE_FIELD(instance, name, representation)