v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
value-type.h
Go to the documentation of this file.
1// Copyright 2018 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
5#ifndef V8_WASM_VALUE_TYPE_H_
6#define V8_WASM_VALUE_TYPE_H_
7
8#if !V8_ENABLE_WEBASSEMBLY
9#error This header should only be included if WebAssembly is enabled.
10#endif // !V8_ENABLE_WEBASSEMBLY
11
12#include <optional>
13
14#include "src/base/bit-field.h"
20
21namespace v8 {
22namespace internal {
23
24// Type for holding simd values, defined in simd128.h.
25class Simd128;
26class Zone;
27
28namespace wasm {
29
30// Format: kind, log2Size, code, machineType, shortName, typeName
31#define FOREACH_NUMERIC_VALUE_TYPE(V) \
32 V(I32, 2, I32, Int32, 'i', "i32") \
33 V(I64, 3, I64, Int64, 'l', "i64") \
34 V(F32, 2, F32, Float32, 'f', "f32") \
35 V(F64, 3, F64, Float64, 'd', "f64") \
36 V(S128, 4, S128, Simd128, 's', "v128") \
37 V(I8, 0, I8, Int8, 'b', "i8") \
38 V(I16, 1, I16, Int16, 'h', "i16") \
39 V(F16, 1, F16, Float16, 'p', "f16")
40
41#define FOREACH_VALUE_TYPE(V) \
42 V(Void, -1, Void, None, 'v', "<void>") \
43 FOREACH_NUMERIC_VALUE_TYPE(V) \
44 V(Ref, kTaggedSizeLog2, Ref, AnyTagged, 'r', "ref") \
45 V(RefNull, kTaggedSizeLog2, RefNull, AnyTagged, 'n', "ref null") \
46 V(Top, -1, Void, None, '\\', "<top>") \
47 V(Bottom, -1, Void, None, '*', "<bot>")
48
49constexpr int kMaxValueTypeSize = 16; // bytes
50
51struct TypeIndex {
52 uint32_t index;
53
54 // We intentionally don't define comparison operators here, because
55 // different subclasses must not be compared to each other.
56
57 static constexpr uint32_t kInvalid = ~0u;
58 constexpr bool valid() const { return index != kInvalid; }
59
60 size_t hash_value() const { return index; }
61};
62
63struct ModuleTypeIndex : public TypeIndex {
64 inline static constexpr ModuleTypeIndex Invalid();
65 // Can't use "=default" because the base class doesn't have operator<=>.
66 bool operator==(ModuleTypeIndex other) const { return index == other.index; }
67 auto operator<=>(ModuleTypeIndex other) const {
68 return index <=> other.index;
69 }
70};
72
76
78 inline static constexpr CanonicalTypeIndex Invalid();
79
80 bool operator==(CanonicalTypeIndex other) const {
81 return index == other.index;
82 }
83 auto operator<=>(CanonicalTypeIndex other) const {
84 return index <=> other.index;
85 }
86};
88
92
93inline std::ostream& operator<<(std::ostream& oss, TypeIndex index) {
94 return oss << index.index;
95}
96
97enum Nullability : bool { kNonNullable = false, kNullable = true };
98
99enum Exactness : bool { kAnySubtype, kExact };
100
101static constexpr bool kNotShared = false;
102
103enum ValueKind : uint8_t {
104#define DEF_ENUM(kind, ...) k##kind,
106#undef DEF_ENUM
107};
108
110// ValueType implementation.
111//
112// We represent ValueTypes as bit fields. We store a mix of spec-level
113// information and additional caches that are useful for efficient algorithms
114// (mostly of subtyping). The key design consideration is that we need to
115// express many different variations of attributes, checks, switches; so we
116// want a ValueType representation that efficiently supports many different
117// kinds of queries and classifications.
118// The usage of the bit field is as follows:
119// bits 0-1: TypeKind: numeric, indexed ref, generic ref, or sentinel. The bits
120// are chosen such that they can also be interpreted as:
121// bit 0: is it a reference of some sort?
122// bit 1: if it's a reference: does it have an index?
123// if it isn't a reference: is it an internal sentinel?
124//
125// bit 2: if it's a reference, is it nullable? Otherwise: unused.
126// bit 3: if it's a reference, is it an exact reference? Otherwise: unused.
127//
128// For indexed (aka user defined) types, the next two fields cache information
129// that could also be looked up in the module's definition of the type:
130// bit 4: is it a shared type? Note that we consider numeric types as shared,
131// i.e. "shared" means "safe to use in a shared function".
132// bits 5-7: RefTypeKind: if it's a reference (indexed or generic), what
133// category of type (struct/array/function/continuation) is it?
134// Non-reference types store the value "kOther".
135//
136// bits 8-27: For indexed types, the index. For other types, the StandardType.
137// The "ValueType" subclass stores module-specific indices, the
138// "CanonicalValueType" stores canonicalized indices.
139// For non-indexed types, we also define their respective
140// "NumericKind" or "GenericKind", which in addition to the right
141// StandardType include the other relevant lower bits.
142//
143// With these assignments, it turns out that "HeapType" is effectively a
144// subset of "ValueType", where bits 0-1 are known to *not* be "numeric",
145// and bit 2 (which is ValueType-specific) is ignored.
146
147namespace value_type_impl {
148
151
152} // namespace value_type_impl
153
154// Shorthands for the "extra_bits" definitions below. All of these must be
155// subsets of kGenericKindMask below!
156#define FUNC value_type_impl::RefTypeKindField::encode(RefTypeKind::kFunction)
157#define STRUCT value_type_impl::RefTypeKindField::encode(RefTypeKind::kStruct)
158#define ARRAY value_type_impl::RefTypeKindField::encode(RefTypeKind::kArray)
159#define CONT value_type_impl::RefTypeKindField::encode(RefTypeKind::kCont)
160#define REF value_type_impl::IsRefField::encode(true)
161#define SENTINEL value_type_impl::HasIndexOrSentinelField::encode(true)
162#define EXACT value_type_impl::IsExactField::encode(Exactness::kExact)
163
164// Abstract ref types that can occur in wire bytes.
165// We mark them as "exact" to require less special-casing in the subtyping
166// implementation.
167// Format: kName, ValueTypeCode, extra_bits, printable_name
168#define FOREACH_NONE_TYPE(V) /* force 80 cols */ \
169 V(NoCont, NoCont, REF | CONT | EXACT, "nocont") \
170 V(NoExn, NoExn, REF | EXACT, "noexn") \
171 V(NoExtern, NoExtern, REF | EXACT, "noextern") \
172 V(NoFunc, NoFunc, REF | FUNC | EXACT, "nofunc") \
173 V(None, None, REF | EXACT, "none")
174
175#define FOREACH_ABSTRACT_TYPE(V) /* force 80 cols */ \
176 FOREACH_NONE_TYPE(V) \
177 /* Established (non-proposal) types. */ \
178 V(Func, FuncRef, REF | FUNC, "func") \
179 V(Any, AnyRef, REF, "any") \
180 V(Eq, EqRef, REF, "eq") \
181 V(I31, I31Ref, REF, "i31") \
182 V(Struct, StructRef, REF | STRUCT, "struct") \
183 V(Array, ArrayRef, REF | ARRAY, "array") \
184 V(Extern, ExternRef, REF, "extern") \
185 V(Exn, ExnRef, REF, "exn") \
186 /* WasmFX aka Core Stack Switching. */ \
187 V(Cont, ContRef, REF | CONT, "cont") \
188 /* Stringref proposal. */ \
189 V(String, StringRef, REF, "string") \
190 V(StringViewWtf8, StringViewWtf8, REF, "stringview_wtf8") \
191 V(StringViewWtf16, StringViewWtf16, REF, "stringview_wtf16") \
192 V(StringViewIter, StringViewIter, REF, "stringview_iter")
193
194// Types that don't fit into any of the other groups.
195#define FOREACH_INTERNAL_TYPE(V) /* force 80 cols */ \
196 V(Void, Void, SENTINEL, "<void>") \
197 V(Top, Void, SENTINEL, "<top>") \
198 V(Bottom, Void, SENTINEL | EXACT, "<bot>") \
199 V(ExternString, Void, REF, "<extern_string>")
200
201#define FOREACH_GENERIC_TYPE(V) /* force 80 cols */ \
202 FOREACH_INTERNAL_TYPE(V) \
203 FOREACH_ABSTRACT_TYPE(V)
204
205// 2 bits to coarsely classify ValueTypes.
206enum class TypeKind : uint8_t {
207 kNumeric = 0b00, // i32, etc. FOREACH_NUMERIC_VALUE_TYPE above.
208 kSentinel = SENTINEL, // top, bottom, void. Have "SENTINEL" above.
209 kAbstractRef = REF, // anyref, eqref, funcref, etc. Have "REF" above.
211};
212enum class RefTypeKind : uint8_t {
213 kOther = 0,
214 kFunction = 1,
215 kStruct = 2,
216 kArray = 3,
217 kCont = 4,
218
220};
221
222namespace value_type_impl {
223
225static_assert(TypeKindField::kMask ==
227// For reference types, we classify the type of reference.
228// Non-reference types don't use these bits.
231// For reference types, we cache some information about the referenced type.
232// Non-reference types don't use these bits.
236
237// Stores the index if {has_index()}, or the {StandardType} otherwise.
239
240// Reserved for future use.
242static_assert(ReservedField::kShift + ReservedField::kSize == 32);
243
244// Useful for HeapTypes, whose "shared" bit is orthogonal to their kind.
245static constexpr uint32_t kGenericKindMask =
248// Useful for numeric types which are always considered "shared".
249static constexpr uint32_t kNumericKindMask =
251static constexpr uint32_t kNumericExtraBits = IsSharedField::encode(true);
252
253#define COUNT(...) +1
254static constexpr uint32_t kNumberOfGenericKinds = 0 FOREACH_GENERIC_TYPE(COUNT);
255static constexpr uint32_t kNumberOfNumericKinds =
257#undef COUNT
258static constexpr uint32_t kNumberOfStandardTypes =
260
261} // namespace value_type_impl
262
263// We define one enum with all non-indexed types, in a compact encoding
264// space. These enum values will equal the contents of the {PayloadField} for
265// the respective ValueTypes.
266enum class StandardType : uint8_t {
267#define DEF_ENUM(kind, ...) k##kind,
269#undef DEF_ENUM
270};
271
272// We additionally define separate enums for generic and numeric types, so that
273// we can write exhaustive switch statements. These enums' values include
274// additional relevant bits in the {bit_field_}s of the respective HeapTypes/
275// ValueTypes, so that certain checks can be expressed as bit field comparisons.
276enum class GenericKind : uint32_t {
277#define DEF_ENUM(kind, code, extra_bits, ...) \
278 k##kind = value_type_impl::PayloadField::encode( \
279 static_cast<uint8_t>(StandardType::k##kind)) + \
280 (extra_bits),
282#undef DEF_ENUM
283};
284
285enum class NumericKind : uint32_t {
286#define DEF_ENUM(kind, ...) \
287 k##kind = value_type_impl::PayloadField::encode( \
288 static_cast<uint8_t>(StandardType::k##kind)) + \
289 value_type_impl::kNumericExtraBits,
291#undef DEF_ENUM
292};
293
294#undef FUNC
295#undef STRUCT
296#undef ARRAY
297#undef CONT
298#undef REF
299#undef SENTINEL
300#undef EXACT
301
302namespace value_type_impl {
303
304// Useful for dense lookup tables.
305constexpr uint32_t ToZeroBasedIndex(NumericKind kind) {
306 // Inside {StandardType}, generic types come first.
307 static_assert(static_cast<uint32_t>(StandardType::kI32) >=
309 uint32_t raw = PayloadField::decode(static_cast<uint32_t>(kind));
311 // As an additional safety net, as long as we happen to have exactly 8
312 // numeric types, we can conveniently apply a mask here. If we need to
313 // accommodate a different number of numeric kinds in the future, we should
314 // consider adding bounds checks at use sites.
315 static_assert(kNumberOfNumericKinds == 8);
316 return (raw - kNumberOfGenericKinds) & 0x7;
317}
318
319} // namespace value_type_impl
320
321constexpr bool IsNullKind(GenericKind kind) {
322 switch (kind) {
323#define NULLTYPE(name, ...) \
324 case GenericKind::k##name: \
325 return true;
327#undef NULLTYPE
328 default:
329 break;
330 }
331 return false;
332}
333
334// {ValueTypeBase} shouldn't be used directly; code should be using one of
335// the subclasses. To enforce this, the public interface is limited to
336// type index agnostic getters.
338 public:
342 static const uint32_t kIsNullableBit =
344 static const uint32_t kHasIndexBit =
347 static const uint32_t kRefKindShift =
351
352 constexpr ValueTypeBase()
353 : ValueTypeBase(GenericKind::kVoid, kNonNullable, false) {}
354
355 // This is specifically for the needs of the decoder: sometimes we need to
356 // create the ValueType instance when we still only know the type index.
357 // Once we know more about the referenced type, this function updates those
358 // bits to their correct values.
363
367 constexpr bool has_index() const {
369 }
370 constexpr bool is_sentinel() const {
371 return type_kind() == TypeKind::kSentinel;
372 }
373 constexpr bool is_numeric() const {
374 return type_kind() == TypeKind::kNumeric;
375 }
376 constexpr bool is_abstract_ref() const {
378 }
379 // Any kind of reference: abstract or indexed.
380 constexpr bool is_ref() const {
382 }
383 // Any GenericKind: abstract reference or internal sentinel.
384 constexpr bool is_generic() const {
387 }
388
393 constexpr bool is_nullable() const {
394 return is_ref() && static_cast<bool>(nullability());
395 }
396 constexpr bool is_non_nullable() const {
397 return is_ref() && !static_cast<bool>(nullability());
398 }
402 constexpr bool is_exact() const { return exactness() == Exactness::kExact; }
403 constexpr bool is_shared() const {
405 }
409
410 constexpr StandardType standard_type() const {
411 DCHECK(!has_index());
412 return static_cast<StandardType>(
414 }
415 constexpr NumericKind numeric_kind() const {
417 return static_cast<NumericKind>(bit_field_ &
419 }
420 constexpr GenericKind generic_kind() const {
422 return static_cast<GenericKind>(bit_field_ &
424 }
425
426 constexpr bool is_bottom() const {
428 return bits == static_cast<uint32_t>(GenericKind::kBottom);
429 }
430 constexpr bool is_top() const {
432 return bits == static_cast<uint32_t>(GenericKind::kTop);
433 }
434 constexpr bool is_void() const {
436 return bits == static_cast<uint32_t>(GenericKind::kVoid);
437 }
438 constexpr bool is_string_view() const {
440 return bits == static_cast<uint32_t>(GenericKind::kStringViewWtf8) ||
441 bits == static_cast<uint32_t>(GenericKind::kStringViewWtf16) ||
442 bits == static_cast<uint32_t>(GenericKind::kStringViewIter);
443 }
444 constexpr bool is_packed() const {
445 return bit_field_ == static_cast<uint32_t>(NumericKind::kI8) ||
446 bit_field_ == static_cast<uint32_t>(NumericKind::kI16) ||
447 bit_field_ == static_cast<uint32_t>(NumericKind::kF16);
448 }
449 constexpr bool is_reference_to(GenericKind type) const {
450 return is_abstract_ref() && generic_kind() == type;
451 }
452 constexpr bool is_defaultable() const {
453 return is_numeric() || is_nullable();
454 }
455 constexpr bool is_uninhabited() const {
456 if (is_bottom()) return true;
457 if (is_defaultable()) return false; // Includes all nullable refs.
458 if (has_index()) return false;
459 // Non-nullable references to null types are uninhabitable.
460 return IsNullKind(generic_kind());
461 }
462 constexpr bool use_wasm_null() const {
463 DCHECK(is_ref());
464 // TODO(jkummerow): Consider calling {wasm::IsSubtypeOf}.
465 if (has_index()) return true;
467 if (ref == GenericKind::kExtern) return false;
468 if (ref == GenericKind::kExternString) return false;
469 if (ref == GenericKind::kNoExtern) return false;
470 return true;
471 }
472
473 constexpr int value_kind_size_log2() const {
474 DCHECK(!is_sentinel()); // Caller's responsibility.
475 if (is_ref()) return kTaggedSizeLog2;
476 constexpr uint8_t kValueKindSizeLog2[] = {
477#define VALUE_KIND_SIZE_LOG2(kind, log2Size, ...) log2Size,
479#undef VALUE_KIND_SIZE_LOG2
480 };
482 return kValueKindSizeLog2[index];
483 }
484
485 constexpr int value_kind_size() const {
486 DCHECK(!is_sentinel()); // Caller's responsibility.
487 if (is_ref()) return kTaggedSize;
488 constexpr uint8_t kValueKindSize[] = {
489#define ELEM_SIZE_LOG2(kind, log2Size, ...) (1 << log2Size),
491#undef ELEM_SIZE_LOG2
492 };
494 return kValueKindSize[index];
495 }
496
497 constexpr int value_kind_full_size() const {
498 if (is_ref()) {
499 // Uncompressed pointer size.
500 return kSystemPointerSize;
501 }
502 return value_kind_size();
503 }
504
505 /*************************** Machine-type related ***************************/
506 constexpr MachineType machine_type() const {
507 // TODO(jkummerow): Do any callers ever pass a sentinel here?
508 if (is_sentinel()) return MachineType::None();
509 if (is_ref()) return MachineType::AnyTagged();
510 constexpr MachineType kMachineType[] = {
511#define MACH_TYPE(kind, log2Size, code, machineType, ...) \
512 MachineType::machineType(),
514#undef MACH_TYPE
515 };
517 return kMachineType[index];
518 }
519
523
524 /********************************* Encoding *********************************/
525 // Returns the first byte of this type's representation in the wasm binary
526 // format. Prioritizes shorthand encodings, e.g. kFuncRefCode.
528 if (is_numeric()) return value_type_code_numeric();
529 if (is_ref() && encoding_needs_heap_type()) {
530 return is_nullable() ? kRefNullCode : kRefCode;
531 }
532 DCHECK(!has_index()); // Handled by {encoding_needs_heap_type()}.
534 }
535
536 // Returns true iff the heap type is needed to encode this type in the wasm
537 // binary format, taking into account available type shorthands.
538 constexpr bool encoding_needs_heap_type() const {
539 if (has_index()) return true;
540 if (!is_abstract_ref()) return false;
541 return !is_nullable() || is_shared();
542 }
543
544 constexpr bool encoding_needs_shared() const {
545 return is_abstract_ref() && is_shared();
546 }
547
548 constexpr bool encoding_needs_exact() const {
549 return has_index() && is_exact();
550 }
551
554
555 /****************************** Pretty-printing *****************************/
556 constexpr char short_name() const {
557 DCHECK(!is_sentinel()); // Caller's responsibility.
558 if (is_ref()) {
559 return is_nullable() ? 'n' : 'r';
560 }
561 constexpr const char kNumericShortName[] = {
562#define SHORT_NAME(kind, log2, code, mtype, shortName, ...) shortName,
564#undef SHORT_NAME
565 };
567 return kNumericShortName[index];
568 }
569
570 V8_EXPORT_PRIVATE std::string generic_heaptype_name() const;
571 V8_EXPORT_PRIVATE std::string name() const;
572
573 constexpr bool is_valid() const {
574 static_assert(static_cast<int>(StandardType::kI32) >
575 static_cast<int>(StandardType::kAny));
577 if (is_numeric()) {
578 // For numeric types, everything outside the payload is fixed.
581 return false;
582 }
583 return payload >= value_type_impl::kNumberOfGenericKinds &&
585 }
586 if (!has_index()) {
587 // Generic types must be part of the predefined set.
588 if (payload >= value_type_impl::kNumberOfGenericKinds) return false;
589 }
590 // Both generic and indexed ref types must leave the reserved bits free.
592 }
593
594 constexpr uint32_t raw_bit_field() const { return bit_field_; }
595
596 size_t hash_value() const { return bit_field_; }
597
598 /************************* Incremental transition ***************************/
599 // The following methods are deprecated. Their usage should be replaced.
600 constexpr bool is_reference() const { return is_ref(); }
601 constexpr bool is_object_reference() const { return is_ref(); }
602
604 switch (kind) {
605 case kI32:
606 return ValueTypeBase(NumericKind::kI32);
607 case kI64:
608 return ValueTypeBase(NumericKind::kI64);
609 case kF32:
610 return ValueTypeBase(NumericKind::kF32);
611 case kF64:
612 return ValueTypeBase(NumericKind::kF64);
613 case kS128:
614 return ValueTypeBase(NumericKind::kS128);
615 case kI8:
616 return ValueTypeBase(NumericKind::kI8);
617 case kI16:
618 return ValueTypeBase(NumericKind::kI16);
619 case kF16:
620 return ValueTypeBase(NumericKind::kF16);
621 case kVoid:
622 return ValueTypeBase(GenericKind::kVoid, kNonNullable, false);
623 case kRef:
624 case kRefNull:
625 case kTop:
626 case kBottom:
627 UNREACHABLE();
628 }
629 }
630
631 constexpr ValueKind kind() const {
632 if (is_numeric()) {
633 switch (numeric_kind()) {
634 case NumericKind::kI32:
635 return kI32;
636 case NumericKind::kI64:
637 return kI64;
638 case NumericKind::kF32:
639 return kF32;
640 case NumericKind::kF64:
641 return kF64;
642 case NumericKind::kS128:
643 return kS128;
644 case NumericKind::kI8:
645 return kI8;
646 case NumericKind::kI16:
647 return kI16;
648 case NumericKind::kF16:
649 return kF16;
650 }
651 UNREACHABLE();
652 }
653 if (is_top()) return kTop;
654 if (is_bottom()) return kBottom;
655 if (is_void()) return kVoid;
656 return is_nullable() ? kRefNull : kRef;
657 }
658
659 constexpr uint32_t raw_heap_representation(bool distinguish_shared) const;
660
661 protected:
662 friend class CanonicalValueType;
663 friend class HeapType;
665 friend class ValueType;
666
667 explicit constexpr ValueTypeBase(uint32_t bit_field) : bit_field_(bit_field) {
668 DCHECK(is_valid());
669 }
670
671 explicit constexpr ValueTypeBase(NumericKind kind)
672 : bit_field_(static_cast<uint32_t>(kind)) {
674 }
675
676 explicit constexpr ValueTypeBase(GenericKind kind, Nullability nullable,
677 bool is_shared)
678 : bit_field_(static_cast<uint32_t>(kind) |
679 value_type_impl::IsNullableField::encode(nullable) |
680 value_type_impl::IsSharedField::encode(is_shared)) {
682 }
683
684 explicit constexpr ValueTypeBase(TypeIndex index, Nullability nullable,
685 Exactness exact, bool shared,
687 : bit_field_(
688 value_type_impl::TypeKindField::encode(TypeKind::kIndexedRef) |
689 value_type_impl::IsNullableField::encode(nullable) |
690 value_type_impl::IsExactField::encode(exact) |
691 value_type_impl::IsSharedField::encode(shared) |
692 value_type_impl::RefTypeKindField::encode(ref_type_kind) |
693 value_type_impl::PayloadField::encode(index.index)) {
694 // We shouldn't need this, but experience has shown that having an extra
695 // "safety net" here is valuable every now and then.
697 }
698
703
704 uint32_t bit_field_;
705};
707
708// A HeapType is like a ValueType where {is_numeric()} is known to be false
709// and the value of {is_nullable()} is ignored.
710// Uses module-specific type indices.
711class HeapType : public ValueTypeBase {
712 public:
713 static constexpr HeapType Generic(GenericKind kind, bool shared) {
714 return HeapType{ValueTypeBase(kind, kNullable, shared)};
715 }
716 static constexpr HeapType Index(ModuleTypeIndex index, bool shared,
719 return HeapType{ValueTypeBase(index, kNullable, exact, shared, kind)};
720 }
721 static constexpr HeapType FromBits(uint32_t bits) {
722 HeapType type{ValueTypeBase(bits)};
723 DCHECK(!type.is_numeric());
724 return type;
725 }
726
727 static constexpr HeapType from_code(uint8_t code, bool is_shared) {
728 constexpr uint8_t kFirst = ValueTypeCode::kFirstHeapTypeCode;
729 constexpr uint8_t kLast = ValueTypeCode::kLastHeapTypeCode;
731 return Generic(GenericKind::kBottom, false);
732 }
733 constexpr size_t kNumCases = kLast - kFirst + 1;
734 constexpr std::array<GenericKind, kNumCases> kLookupTable =
735 base::make_array<kNumCases>([](size_t i) {
736 switch (i) {
737#define CASE(name, code, ...) \
738 case (k##code##Code - kFirst): \
739 static_assert(k##code##Code >= kFirst && k##code##Code <= kLast); \
740 return GenericKind::k##name;
742#undef CASE
743 default:
744 return GenericKind::kBottom;
745 }
746 });
747 return Generic(kLookupTable[code - kFirst], is_shared);
748 }
749
754
755 int32_t code() const {
756 if (has_index()) return static_cast<int32_t>(ref_index().index);
757 // Value type codes represent the first byte of the LEB128 encoding. To get
758 // the int32 represented by a code, we sign-extend it from 7 to 32 bits.
759 return 0xFFFF'FF80 | value_type_code_generic();
760 }
761
762 constexpr ModuleTypeIndex ref_index() const {
763 return ModuleTypeIndex{raw_index()};
764 }
765
766 constexpr bool operator==(HeapType other) const {
767 constexpr uint32_t kMask = ~value_type_impl::IsRefField::kMask &
768 ~value_type_impl::IsNullableField::kMask;
769 return (bit_field_ & kMask) == (other.bit_field_ & kMask);
770 }
771
772 /****************************** Pretty-printing *****************************/
773 std::string name() const {
774 if (has_index()) {
775 if (is_exact()) return "exact " + std::to_string(raw_index().index);
776 return std::to_string(raw_index().index);
777 }
778 return generic_heaptype_name();
779 }
780
781 /************************* Incremental transition ***************************/
782 // The following methods are deprecated. Their usage should be replaced.
783 enum Representation : uint32_t {
784 kFunc = kV8MaxWasmTypes, // shorthand: c
785 kEq, // shorthand: q
786 kI31, // shorthand: j
787 kStruct, // shorthand: o
788 kArray, // shorthand: g
790 kExtern, // shorthand: a.
791 kExternString, // Internal type for optimization purposes.
792 // Subtype of extern.
793 // Used by the js-builtin-strings proposal.
795 kString, // shorthand: w.
796 kStringViewWtf8, // shorthand: x.
797 kStringViewWtf16, // shorthand: y.
798 kStringViewIter, // shorthand: z.
803 kCont, // shorthand: k.
805 kNoCont, // bottom continuation type
824 // This value is an internal type (not part of the Wasm spec) that
825 // is the common supertype across all type hierarchies. It should never
826 // appear in validated Wasm programs, but is used to signify that we don't
827 // have any information about a particular value and to prevent bugs in our
828 // typed optimizations, see crbug.com/361652141. Note: kTop is the neutral
829 // element wrt. to intersection (whereas kBottom is for union), and kBottom
830 // is indicating unreachable code, which might be used for subsequent
831 // optimizations, e.g., DCE.
833 // This value is used to represent failures in the parsing of heap types and
834 // does not correspond to a Wasm heap type. It has to be last in this list.
835 kBottom
836 };
837 constexpr Representation representation() const {
838 return static_cast<Representation>(raw_heap_representation(true));
839 }
840 constexpr bool is_index() const { return has_index(); }
841
842 private:
843 // Hide inherited methods that don't make sense for HeapTypes.
844 constexpr bool is_nullable() const;
845 constexpr bool is_non_nullable() const;
846 constexpr Nullability nullability() const;
847};
848
849// Deprecated.
851 bool distinguish_shared) const {
852 DCHECK(!is_numeric());
853 if (has_index()) return raw_index().index;
854 switch (generic_kind()) {
855 case GenericKind::kTop:
856 return HeapType::kTop;
857 case GenericKind::kBottom:
858 return HeapType::kBottom;
859
860#define CASE(name, ...) \
861 case GenericKind::k##name: \
862 return distinguish_shared && is_shared() ? HeapType::k##name##Shared \
863 : HeapType::k##name;
865#undef CASE
866
867 case GenericKind::kExternString:
868 return distinguish_shared && is_shared() ? HeapType::kExternStringShared
870 case GenericKind::kVoid:
871 UNREACHABLE();
872 }
873}
874
876
877// Uses module-specific type indices.
878class ValueType : public ValueTypeBase {
879 public:
882 }
883 static constexpr ValueType Generic(GenericKind kind, Nullability nullable,
884 bool shared) {
885 return ValueType{ValueTypeBase(kind, nullable, shared)};
886 }
887 static constexpr ValueType Ref(ModuleTypeIndex index, bool shared,
890 shared, kind)};
891 }
892 static constexpr ValueType Ref(HeapType type) {
893 return ValueType{type}.AsNonNull();
894 }
895 static constexpr ValueType RefNull(ModuleTypeIndex index, bool shared,
897 return ValueType{
899 }
900 static constexpr ValueType RefNull(HeapType type) {
901 return ValueType{type}.AsNullable(kNullable);
902 }
903 static constexpr ValueType RefMaybeNull(ModuleTypeIndex index,
904 Nullability nullable, bool shared,
906 return ValueType{
907 ValueTypeBase(index, nullable, Exactness::kAnySubtype, shared, kind)};
908 }
909 static constexpr ValueType RefMaybeNull(HeapType type, Nullability nullable) {
910 return ValueType{type}.AsNullable(nullable);
911 }
912
913 static constexpr ValueType FromRawBitField(uint32_t bits) {
914 return ValueType{ValueTypeBase(bits)};
915 }
916
917 constexpr ValueType AsNonNull() const { return AsNullable(kNonNullable); }
923
929
930 // This will be replaced by direct calls to {AsExact} once the proposal
931 // has shipped by default and the flag is removed.
933 Exactness exact = Exactness::kExact) const {
934 if V8_LIKELY (!v8_flags.experimental_wasm_custom_descriptors) return *this;
935 return AsExact(exact);
936 }
937
938 constexpr ValueType AsNonShared() const {
939 if (!is_ref()) return *this;
942 }
943
944 constexpr ValueType Unpacked() const {
945 if (bit_field_ == static_cast<uint32_t>(NumericKind::kI8) ||
946 bit_field_ == static_cast<uint32_t>(NumericKind::kI16)) {
947 return Primitive(NumericKind::kI32);
948 }
949 if (bit_field_ == static_cast<uint32_t>(NumericKind::kF16)) {
950 return Primitive(NumericKind::kF32);
951 }
952 return *this;
953 }
954
956
957 // For incremental transition:
958 static constexpr ValueType Primitive(ValueKind kind) {
960 }
961
962 // For incremental transition:
964 return static_cast<HeapType::Representation>(raw_heap_representation(true));
965 }
966
967 // For incremental transition:
968 constexpr bool is_reference_to(HeapType::Representation repr) const {
969 return is_ref() && heap_representation() == repr;
970 }
971 // Un-hide the superclass method (which is here to stay):
972 constexpr bool is_reference_to(GenericKind kind) const {
974 }
975
976 static ValueType For(MachineType type) {
977 switch (type.representation()) {
981 return Primitive(NumericKind::kI32);
983 return Primitive(NumericKind::kI64);
985 return Primitive(NumericKind::kF32);
987 return Primitive(NumericKind::kF64);
989 return Generic(GenericKind::kAny, kNullable, kNotShared);
991 return Primitive(NumericKind::kS128);
992 default:
993 UNREACHABLE();
994 }
995 }
996
997 constexpr bool operator==(ValueType other) const {
998 return bit_field_ == other.bit_field_;
999 }
1000
1001 constexpr HeapType heap_type() const {
1002 DCHECK(!is_numeric());
1003 return HeapType{*this};
1004 }
1005
1006 constexpr ModuleTypeIndex ref_index() const {
1007 return ModuleTypeIndex{raw_index()};
1008 }
1009};
1011
1012// Uses canonicalized type indices.
1014 public:
1018 static constexpr CanonicalValueType Ref(CanonicalTypeIndex index, bool shared,
1019 RefTypeKind kind) {
1021 index, kNonNullable, Exactness::kAnySubtype, shared, kind)};
1022 }
1024 bool shared, RefTypeKind kind) {
1025 return CanonicalValueType{
1027 }
1028 // Technically this should take a "CanonicalHeapType", but we don't have
1029 // that class because there's not enough use case for it.
1031 Nullability nullable) {
1032 return CanonicalValueType{
1034 type.raw_bit_field(), nullable))};
1035 }
1036
1037 static constexpr CanonicalValueType FromRawBitField(uint32_t bits) {
1038 return CanonicalValueType{ValueTypeBase(bits)};
1039 }
1040
1047
1048 // This will be replaced by direct calls to {AsExact} once the proposal
1049 // has shipped by default and the flag is removed.
1051 Exactness exact = Exactness::kExact) const {
1052 if V8_LIKELY (!v8_flags.experimental_wasm_custom_descriptors) return *this;
1053 return AsExact(exact);
1054 }
1055
1056 constexpr CanonicalTypeIndex ref_index() const {
1057 return CanonicalTypeIndex{raw_index()};
1058 }
1059
1060 constexpr bool operator==(CanonicalValueType other) const {
1061 return bit_field_ == other.bit_field_;
1062 }
1063
1064 constexpr bool IsFunctionType() const {
1066 }
1067
1068 // For incremental transition.
1070 return static_cast<HeapType::Representation>(raw_heap_representation(true));
1071 }
1072
1073 // For incremental transition.
1075 return static_cast<HeapType::Representation>(
1077 }
1078
1079 // For incremental transition:
1080 constexpr bool is_reference_to(HeapType::Representation repr) const {
1081 return is_ref() && heap_representation() == repr;
1082 }
1083};
1085
1092
1093// Non-indexed types. We use them for global constants; they have the
1094// specific characteristic that they can be compared and implicitly converted
1095// to both HeapTypes/ValueTypes and CanonicalValueTypes.
1097 public:
1100
1101 constexpr operator ValueType() const { return ValueType{*this}; }
1102 constexpr operator CanonicalValueType() const {
1103 return CanonicalValueType{*this};
1104 }
1105
1106 // Implicit conversions aren't enough when the IndependentValueType is the
1107 // left-hand side.
1108 constexpr bool operator==(ValueType b) const {
1109 return raw_bit_field() == b.raw_bit_field();
1110 }
1111 constexpr bool operator==(CanonicalValueType b) const {
1112 return raw_bit_field() == b.raw_bit_field();
1113 }
1114
1115 protected:
1117 Nullability nullable, bool shared)
1118 : ValueTypeBase(kind, nullable, shared) {}
1119};
1121 public:
1123 Nullability nullable = kNullable,
1124 bool shared = false)
1125 : IndependentValueType(kind, nullable, shared) {}
1126
1130
1131 constexpr HeapType heap_type() const { return HeapType{*this}; }
1132 constexpr operator HeapType() const { return HeapType{*this}; }
1133};
1134
1135// TODO(jkummerow): See how many of these ValueKind-based helpers we can
1136// replace with ValueType methods.
1137
1138constexpr bool is_reference(ValueKind kind) {
1139 return kind == kRef || kind == kRefNull;
1140}
1141
1143 return kind == kRef || kind == kRefNull;
1144}
1145
1147 constexpr int8_t kValueKindSizeLog2[] = {
1148#define VALUE_KIND_SIZE_LOG2(kind, log2Size, ...) log2Size,
1150#undef VALUE_KIND_SIZE_LOG2
1151 };
1152
1153 int size_log_2 = kValueKindSizeLog2[kind];
1154 DCHECK_LE(0, size_log_2);
1155 return size_log_2;
1156}
1157
1159 constexpr int8_t kElementSize[] = {
1160#define ELEM_SIZE_LOG2(kind, log2Size, ...) \
1161 log2Size == -1 ? -1 : (1 << std::max(0, log2Size)),
1163#undef ELEM_SIZE_LOG2
1164 };
1165
1166 int size = kElementSize[kind];
1167 DCHECK_LT(0, size);
1168 return size;
1169}
1170
1172 if (is_reference(kind)) {
1173 // Uncompressed pointer size.
1174 return kSystemPointerSize;
1175 }
1176 return value_kind_size(kind);
1177}
1178
1179constexpr const char* name(ValueKind kind) {
1180 constexpr const char* kKindName[] = {
1181#define KIND_NAME(kind, log2Size, code, machineType, shortName, kindName, ...) \
1182 kindName,
1184#undef TYPE_NAME
1185 };
1186
1187 return kKindName[kind];
1188}
1189
1190// Output operator, useful for DCHECKS and others.
1191inline std::ostream& operator<<(std::ostream& oss, ValueKind kind) {
1192 return oss << name(kind);
1193}
1194
1196 DCHECK_NE(kBottom, kind);
1197
1198 constexpr MachineType kMachineType[] = {
1199#define MACH_TYPE(kind, log2Size, code, machineType, ...) \
1200 MachineType::machineType(),
1202#undef MACH_TYPE
1203 };
1204
1205 return kMachineType[kind];
1206}
1207
1208constexpr bool is_packed(ValueKind kind) {
1209 return kind == kI8 || kind == kI16 || kind == kF16;
1210}
1212 return is_packed(kind) ? (kind == kF16 ? kF32 : kI32) : kind;
1213}
1214
1215static_assert(sizeof(ValueTypeBase) <= kUInt32Size,
1216 "ValueType is small and can be passed by value");
1218 "ValueType has space to be encoded in a Smi");
1219
1220// Output operator, useful for DCHECKS and others.
1221inline std::ostream& operator<<(std::ostream& oss, ValueType type) {
1222 return oss << type.name() << " (raw=0x" << std::hex << type.raw_bit_field()
1223 << ")" << std::dec;
1224}
1225
1226// Precomputed primitive types.
1227constexpr IndependentValueType kWasmI32{NumericKind::kI32};
1228constexpr IndependentValueType kWasmI64{NumericKind::kI64};
1229constexpr IndependentValueType kWasmF32{NumericKind::kF32};
1230constexpr IndependentValueType kWasmF64{NumericKind::kF64};
1231constexpr IndependentValueType kWasmS128{NumericKind::kS128};
1232constexpr IndependentValueType kWasmI8{NumericKind::kI8};
1233constexpr IndependentValueType kWasmI16{NumericKind::kI16};
1234constexpr IndependentValueType kWasmF16{NumericKind::kF16};
1235constexpr IndependentHeapType kWasmVoid{GenericKind::kVoid, kNonNullable};
1236// The abstract top type (super type of all other types).
1237constexpr IndependentHeapType kWasmTop{GenericKind::kTop};
1238constexpr IndependentHeapType kWasmBottom{GenericKind::kBottom, kNonNullable};
1239// Established reference-type and wasm-gc proposal shorthands.
1240constexpr IndependentHeapType kWasmFuncRef{GenericKind::kFunc};
1241constexpr IndependentHeapType kWasmAnyRef{GenericKind::kAny};
1242constexpr IndependentHeapType kWasmExternRef{GenericKind::kExtern};
1243constexpr IndependentHeapType kWasmRefExtern{GenericKind::kExtern,
1244 kNonNullable};
1245constexpr IndependentHeapType kWasmExnRef{GenericKind::kExn};
1246constexpr IndependentHeapType kWasmEqRef{GenericKind::kEq};
1247constexpr IndependentHeapType kWasmI31Ref{GenericKind::kI31};
1248constexpr IndependentHeapType kWasmRefI31{GenericKind::kI31, kNonNullable};
1249constexpr IndependentHeapType kWasmStructRef{GenericKind::kStruct};
1250constexpr IndependentHeapType kWasmArrayRef{GenericKind::kArray};
1251constexpr IndependentHeapType kWasmStringRef{GenericKind::kString};
1252constexpr IndependentHeapType kWasmRefString{GenericKind::kString,
1253 kNonNullable};
1255 GenericKind::kExternString};
1256constexpr IndependentHeapType kWasmRefExternString{GenericKind::kExternString,
1257 kNonNullable};
1258constexpr IndependentHeapType kWasmStringViewWtf8{GenericKind::kStringViewWtf8,
1259 kNonNullable};
1261 GenericKind::kStringViewWtf16, kNonNullable};
1262constexpr IndependentHeapType kWasmStringViewIter{GenericKind::kStringViewIter,
1263 kNonNullable};
1264constexpr IndependentHeapType kWasmNullRef{GenericKind::kNone};
1265constexpr IndependentHeapType kWasmNullExternRef{GenericKind::kNoExtern};
1266constexpr IndependentHeapType kWasmNullExnRef{GenericKind::kNoExn};
1267constexpr IndependentHeapType kWasmNullFuncRef{GenericKind::kNoFunc};
1268constexpr IndependentHeapType kWasmContRef{GenericKind::kCont};
1269constexpr IndependentHeapType kWasmNullContRef{GenericKind::kNoCont};
1270
1271#define FOREACH_WASMVALUE_CTYPES(V) \
1272 V(kI32, int32_t) \
1273 V(kI64, int64_t) \
1274 V(kF32, float) \
1275 V(kF64, double) \
1276 V(kS128, Simd128)
1277
1279
1280class CanonicalSig : public Signature<CanonicalValueType> {
1281 public:
1285
1286 class Builder : public SignatureBuilder<CanonicalSig, CanonicalValueType> {
1287 public:
1291 CanonicalSig* Get() const;
1292 };
1293
1294 uint64_t signature_hash() const { return signature_hash_; }
1295
1296 private:
1298};
1299
1300// This is the special case where comparing module-specific to canonical
1301// signatures is safe: when they only contain numerical types.
1303 const FunctionSig* b);
1304
1305#define FOREACH_LOAD_TYPE(V) \
1306 V(I32, , Int32) \
1307 V(I32, 8S, Int8) \
1308 V(I32, 8U, Uint8) \
1309 V(I32, 16S, Int16) \
1310 V(I32, 16U, Uint16) \
1311 V(I64, , Int64) \
1312 V(I64, 8S, Int8) \
1313 V(I64, 8U, Uint8) \
1314 V(I64, 16S, Int16) \
1315 V(I64, 16U, Uint16) \
1316 V(I64, 32S, Int32) \
1317 V(I64, 32U, Uint32) \
1318 V(F32, F16, Float16) \
1319 V(F32, , Float32) \
1320 V(F64, , Float64) \
1321 V(S128, , Simd128)
1322
1324 public:
1325 enum LoadTypeValue : uint8_t {
1326#define DEF_ENUM(type, suffix, ...) k##type##Load##suffix,
1328#undef DEF_ENUM
1329 };
1330
1331 // Allow implicit conversion of the enum value to this wrapper.
1332 // NOLINTNEXTLINE(runtime/explicit)
1333 constexpr LoadType(LoadTypeValue val) : val_(val) {}
1334
1335 constexpr LoadTypeValue value() const { return val_; }
1336 constexpr uint8_t size_log_2() const { return kLoadSizeLog2[val_]; }
1337 constexpr uint8_t size() const { return kLoadSize[val_]; }
1338 constexpr ValueType value_type() const { return kValueType[val_]; }
1339 constexpr MachineType mem_type() const { return kMemType[val_]; }
1340
1342 switch (kind) {
1343 case kI32:
1344 return kI32Load;
1345 case kI64:
1346 return kI64Load;
1347 case kF32:
1348 return kF32Load;
1349 case kF64:
1350 return kF64Load;
1351 case kS128:
1352 return kS128Load;
1353 case kI8:
1354 return is_signed ? kI32Load8S : kI32Load8U;
1355 case kI16:
1356 return is_signed ? kI32Load16S : kI32Load16U;
1357 case kF16:
1358 return kF32LoadF16;
1359 default:
1360 UNREACHABLE();
1361 }
1362 }
1363
1364 private:
1366
1367 static constexpr uint8_t kLoadSize[] = {
1368 // MSVC wants a static_cast here.
1369#define LOAD_SIZE(_, __, memtype) \
1370 static_cast<uint8_t>( \
1371 ElementSizeInBytes(MachineType::memtype().representation())),
1373#undef LOAD_SIZE
1374 };
1375
1376 static constexpr uint8_t kLoadSizeLog2[] = {
1377 // MSVC wants a static_cast here.
1378#define LOAD_SIZE(_, __, memtype) \
1379 static_cast<uint8_t>( \
1380 ElementSizeLog2Of(MachineType::memtype().representation())),
1382#undef LOAD_SIZE
1383 };
1384
1385 static constexpr ValueType kValueType[] = {
1386#define VALUE_TYPE(type, ...) ValueType::Primitive(k##type),
1388#undef VALUE_TYPE
1389 };
1390
1391 static constexpr MachineType kMemType[] = {
1392#define MEMTYPE(_, __, memtype) MachineType::memtype(),
1394#undef MEMTYPE
1395 };
1396};
1397
1398#define FOREACH_STORE_TYPE(V) \
1399 V(I32, , Word32) \
1400 V(I32, 8, Word8) \
1401 V(I32, 16, Word16) \
1402 V(I64, , Word64) \
1403 V(I64, 8, Word8) \
1404 V(I64, 16, Word16) \
1405 V(I64, 32, Word32) \
1406 V(F32, F16, Float16) \
1407 V(F32, , Float32) \
1408 V(F64, , Float64) \
1409 V(S128, , Simd128)
1410
1412 public:
1413 enum StoreTypeValue : uint8_t {
1414#define DEF_ENUM(type, suffix, ...) k##type##Store##suffix,
1416#undef DEF_ENUM
1417 };
1418
1419 // Allow implicit conversion of the enum value to this wrapper.
1420 // NOLINTNEXTLINE(runtime/explicit)
1421 constexpr StoreType(StoreTypeValue val) : val_(val) {}
1422
1423 constexpr StoreTypeValue value() const { return val_; }
1424 constexpr unsigned size_log_2() const { return kStoreSizeLog2[val_]; }
1425 constexpr unsigned size() const { return 1 << size_log_2(); }
1426 constexpr ValueType value_type() const { return kValueType[val_]; }
1427 constexpr MachineRepresentation mem_rep() const { return kMemRep[val_]; }
1428
1430 switch (kind) {
1431 case kI32:
1432 return kI32Store;
1433 case kI64:
1434 return kI64Store;
1435 case kF32:
1436 return kF32Store;
1437 case kF64:
1438 return kF64Store;
1439 case kS128:
1440 return kS128Store;
1441 case kI8:
1442 return kI32Store8;
1443 case kI16:
1444 return kI32Store16;
1445 case kF16:
1446 return kF32StoreF16;
1447 default:
1448 UNREACHABLE();
1449 }
1450 }
1451
1452 private:
1454
1455 static constexpr uint8_t kStoreSizeLog2[] = {
1456 // MSVC wants a static_cast here.
1457#define STORE_SIZE(_, __, memrep) \
1458 static_cast<uint8_t>(ElementSizeLog2Of(MachineRepresentation::k##memrep)),
1460#undef STORE_SIZE
1461 };
1462
1463 static constexpr ValueType kValueType[] = {
1464#define VALUE_TYPE(type, ...) ValueType::Primitive(k##type),
1466#undef VALUE_TYPE
1467 };
1468
1469 static constexpr MachineRepresentation kMemRep[] = {
1470#define MEMREP(_, __, memrep) MachineRepresentation::k##memrep,
1472#undef MEMREP
1473 };
1474};
1475
1476std::optional<wasm::ValueKind> WasmReturnTypeFromSignature(
1477 const CanonicalSig* wasm_signature);
1478
1479// Lowers a signature for 32 bit platforms by replacing i64 parameters and
1480// returns with two i32s each.
1482 Zone* zone, const wasm::FunctionSig* sig);
1483
1484} // namespace wasm
1485} // namespace internal
1486} // namespace v8
1487
1488#endif // V8_WASM_VALUE_TYPE_H_
friend Zone
Definition asm-types.cc:195
Builtins::Kind kind
Definition builtins.cc:40
static constexpr int kLastUsedBit
Definition bit-field.h:42
static constexpr T decode(U value)
Definition bit-field.h:66
static constexpr bool is_valid(T value)
Definition bit-field.h:50
static constexpr U encode(T value)
Definition bit-field.h:55
static V8_NODISCARD constexpr U update(U previous, T value)
Definition bit-field.h:61
static constexpr int kSize
Definition bit-field.h:40
static constexpr U kMask
Definition bit-field.h:41
static constexpr int kShift
Definition bit-field.h:39
constexpr MachineRepresentation representation() const
static constexpr MachineType AnyTagged()
static constexpr MachineType None()
Builder(Zone *zone, size_t return_count, size_t parameter_count)
CanonicalSig(size_t return_count, size_t parameter_count, const CanonicalValueType *reps)
CanonicalValueType AsExactIfProposalEnabled(Exactness exact=Exactness::kExact) const
constexpr CanonicalValueType AsExact(Exactness exact=Exactness::kExact) const
static constexpr CanonicalValueType RefNull(CanonicalTypeIndex index, bool shared, RefTypeKind kind)
constexpr HeapType::Representation heap_representation() const
static constexpr CanonicalValueType FromRawBitField(uint32_t bits)
static constexpr CanonicalValueType Ref(CanonicalTypeIndex index, bool shared, RefTypeKind kind)
constexpr HeapType::Representation heap_representation_non_shared() const
constexpr CanonicalTypeIndex ref_index() const
constexpr bool is_reference_to(HeapType::Representation repr) const
static constexpr CanonicalValueType Primitive(NumericKind kind)
constexpr bool IsFunctionType() const
static constexpr CanonicalValueType RefMaybeNull(CanonicalValueType type, Nullability nullable)
constexpr bool operator==(CanonicalValueType other) const
static constexpr HeapType Generic(GenericKind kind, bool shared)
Definition value-type.h:713
static constexpr HeapType from_code(uint8_t code, bool is_shared)
Definition value-type.h:727
constexpr bool operator==(HeapType other) const
Definition value-type.h:766
constexpr HeapType AsExact(Exactness exact=Exactness::kExact) const
Definition value-type.h:750
static constexpr HeapType Index(ModuleTypeIndex index, bool shared, RefTypeKind kind, Exactness exact=Exactness::kAnySubtype)
Definition value-type.h:716
constexpr Representation representation() const
Definition value-type.h:837
constexpr bool is_non_nullable() const
constexpr bool is_index() const
Definition value-type.h:840
constexpr bool is_nullable() const
std::string name() const
Definition value-type.h:773
constexpr ModuleTypeIndex ref_index() const
Definition value-type.h:762
static constexpr HeapType FromBits(uint32_t bits)
Definition value-type.h:721
constexpr Nullability nullability() const
constexpr HeapType heap_type() const
constexpr IndependentHeapType AsNonNull() const
constexpr IndependentHeapType(GenericKind kind, Nullability nullable=kNullable, bool shared=false)
constexpr bool operator==(CanonicalValueType b) const
constexpr IndependentValueType(NumericKind kind)
constexpr bool operator==(ValueType b) const
constexpr IndependentValueType(GenericKind kind, Nullability nullable, bool shared)
constexpr ValueType value_type() const
constexpr LoadType(LoadTypeValue val)
constexpr uint8_t size() const
static LoadType ForValueKind(ValueKind kind, bool is_signed=false)
constexpr uint8_t size_log_2() const
static constexpr ValueType kValueType[]
constexpr MachineType mem_type() const
static constexpr MachineType kMemType[]
static constexpr uint8_t kLoadSize[]
static constexpr uint8_t kLoadSizeLog2[]
constexpr LoadTypeValue value() const
static constexpr ValueType kValueType[]
static StoreType ForValueKind(ValueKind kind)
constexpr MachineRepresentation mem_rep() const
static constexpr uint8_t kStoreSizeLog2[]
constexpr StoreTypeValue value() const
static constexpr MachineRepresentation kMemRep[]
constexpr unsigned size_log_2() const
constexpr ValueType value_type() const
constexpr StoreType(StoreTypeValue val)
constexpr unsigned size() const
V8_EXPORT_PRIVATE ValueTypeCode value_type_code_numeric() const
Definition value-type.cc:44
constexpr bool is_ref() const
Definition value-type.h:380
V8_EXPORT_PRIVATE std::string generic_heaptype_name() const
Definition value-type.cc:76
static const uint32_t kIndexShift
Definition value-type.h:350
constexpr int value_kind_size() const
Definition value-type.h:485
constexpr int value_kind_size_log2() const
Definition value-type.h:473
V8_EXPORT_PRIVATE ValueTypeCode value_type_code_generic() const
Definition value-type.cc:55
constexpr char short_name() const
Definition value-type.h:556
constexpr bool is_non_nullable() const
Definition value-type.h:396
constexpr TypeIndex raw_index() const
Definition value-type.h:699
constexpr bool is_sentinel() const
Definition value-type.h:370
constexpr NumericKind numeric_kind() const
Definition value-type.h:415
static const uint32_t kIsNullableBit
Definition value-type.h:342
static const uint32_t kRefKindShift
Definition value-type.h:347
constexpr bool is_valid() const
Definition value-type.h:573
constexpr StandardType standard_type() const
Definition value-type.h:410
void Populate(bool shared, RefTypeKind kind)
Definition value-type.h:359
constexpr bool encoding_needs_shared() const
Definition value-type.h:544
constexpr MachineType machine_type() const
Definition value-type.h:506
constexpr bool is_bottom() const
Definition value-type.h:426
constexpr bool is_packed() const
Definition value-type.h:444
constexpr bool is_reference_to(GenericKind type) const
Definition value-type.h:449
constexpr ValueTypeBase(GenericKind kind, Nullability nullable, bool is_shared)
Definition value-type.h:676
constexpr uint32_t raw_heap_representation(bool distinguish_shared) const
Definition value-type.h:850
constexpr ValueTypeBase(NumericKind kind)
Definition value-type.h:671
constexpr ValueKind kind() const
Definition value-type.h:631
constexpr bool is_reference() const
Definition value-type.h:600
static const uint32_t kHasIndexBit
Definition value-type.h:344
constexpr bool is_shared() const
Definition value-type.h:403
constexpr MachineRepresentation machine_representation() const
Definition value-type.h:520
constexpr bool is_string_view() const
Definition value-type.h:438
static const uint32_t kRefKindBits
Definition value-type.h:346
constexpr bool encoding_needs_exact() const
Definition value-type.h:548
constexpr bool has_index() const
Definition value-type.h:367
constexpr Nullability nullability() const
Definition value-type.h:389
constexpr Exactness exactness() const
Definition value-type.h:399
constexpr bool is_generic() const
Definition value-type.h:384
constexpr bool is_object_reference() const
Definition value-type.h:601
constexpr bool is_numeric() const
Definition value-type.h:373
constexpr bool is_void() const
Definition value-type.h:434
constexpr bool is_nullable() const
Definition value-type.h:393
constexpr bool is_uninhabited() const
Definition value-type.h:455
constexpr ValueTypeBase(TypeIndex index, Nullability nullable, Exactness exact, bool shared, RefTypeKind ref_type_kind)
Definition value-type.h:684
static const uint32_t kIsRefBit
Definition value-type.h:341
constexpr bool encoding_needs_heap_type() const
Definition value-type.h:538
constexpr bool is_exact() const
Definition value-type.h:402
constexpr bool is_abstract_ref() const
Definition value-type.h:376
constexpr bool is_defaultable() const
Definition value-type.h:452
V8_EXPORT_PRIVATE std::string name() const
constexpr uint32_t raw_bit_field() const
Definition value-type.h:594
constexpr TypeKind type_kind() const
Definition value-type.h:364
constexpr bool is_top() const
Definition value-type.h:430
constexpr bool use_wasm_null() const
Definition value-type.h:462
constexpr RefTypeKind ref_type_kind() const
Definition value-type.h:406
constexpr ValueTypeBase(uint32_t bit_field)
Definition value-type.h:667
constexpr int value_kind_full_size() const
Definition value-type.h:497
static const uint32_t kIndexBits
Definition value-type.h:349
constexpr GenericKind generic_kind() const
Definition value-type.h:420
ValueTypeCode value_type_code() const
Definition value-type.h:527
static constexpr ValueTypeBase Primitive(ValueKind kind)
Definition value-type.h:603
constexpr ValueType AsNonShared() const
Definition value-type.h:938
static constexpr ValueType FromRawBitField(uint32_t bits)
Definition value-type.h:913
static constexpr ValueType Primitive(ValueKind kind)
Definition value-type.h:958
static constexpr ValueType Generic(GenericKind kind, Nullability nullable, bool shared)
Definition value-type.h:883
constexpr ValueType AsExact(Exactness exact=Exactness::kExact) const
Definition value-type.h:924
constexpr HeapType heap_type() const
constexpr bool operator==(ValueType other) const
Definition value-type.h:997
static constexpr ValueType RefNull(ModuleTypeIndex index, bool shared, RefTypeKind kind)
Definition value-type.h:895
constexpr bool is_reference_to(HeapType::Representation repr) const
Definition value-type.h:968
static ValueType For(MachineType type)
Definition value-type.h:976
ValueType AsExactIfProposalEnabled(Exactness exact=Exactness::kExact) const
Definition value-type.h:932
constexpr HeapType::Representation heap_representation() const
Definition value-type.h:963
static constexpr ValueType Ref(HeapType type)
Definition value-type.h:892
constexpr bool is_reference_to(GenericKind kind) const
Definition value-type.h:972
static constexpr ValueType RefMaybeNull(HeapType type, Nullability nullable)
Definition value-type.h:909
constexpr CanonicalValueType Canonicalize(CanonicalTypeIndex index) const
constexpr ValueType Unpacked() const
Definition value-type.h:944
static constexpr ValueType Ref(ModuleTypeIndex index, bool shared, RefTypeKind kind)
Definition value-type.h:887
constexpr ModuleTypeIndex ref_index() const
static constexpr ValueType RefNull(HeapType type)
Definition value-type.h:900
static constexpr ValueType RefMaybeNull(ModuleTypeIndex index, Nullability nullable, bool shared, RefTypeKind kind)
Definition value-type.h:903
static constexpr ValueType Primitive(NumericKind kind)
Definition value-type.h:880
constexpr ValueType AsNonNull() const
Definition value-type.h:917
constexpr ValueType AsNullable(Nullability nullable=kNullable) const
Definition value-type.h:918
constexpr auto make_array(Function f)
UnionOf< BigInt, NonBigIntPrimitive > Primitive
Definition index.h:546
WordWithBits< 128 > Simd128
Definition index.h:236
static constexpr uint32_t kNumericExtraBits
Definition value-type.h:251
static constexpr uint32_t kNumberOfNumericKinds
Definition value-type.h:255
static constexpr uint32_t kGenericKindMask
Definition value-type.h:245
static constexpr uint32_t kNumericKindMask
Definition value-type.h:249
constexpr uint32_t ToZeroBasedIndex(NumericKind kind)
Definition value-type.h:305
static constexpr uint32_t kNumberOfStandardTypes
Definition value-type.h:258
static constexpr uint32_t kNumberOfGenericKinds
Definition value-type.h:254
constexpr bool IsNullKind(GenericKind kind)
Definition value-type.h:321
constexpr MachineType machine_type(ValueKind kind)
bool EquivalentNumericSig(const CanonicalSig *a, const FunctionSig *b)
constexpr IndependentHeapType kWasmNullExternRef
constexpr IndependentHeapType kWasmNullRef
constexpr IndependentHeapType kWasmRefExtern
constexpr IndependentHeapType kWasmRefNullExternString
constexpr IndependentHeapType kWasmStringRef
std::optional< wasm::ValueKind > WasmReturnTypeFromSignature(const CanonicalSig *wasm_signature)
constexpr IndependentValueType kWasmI8
constexpr IndependentValueType kWasmF32
constexpr IndependentHeapType kWasmAnyRef
constexpr IndependentHeapType kWasmStringViewWtf8
constexpr IndependentHeapType kWasmEqRef
constexpr IndependentHeapType kWasmExternRef
constexpr int value_kind_full_size(ValueKind kind)
constexpr IndependentHeapType kWasmNullFuncRef
constexpr IndependentValueType kWasmI32
constexpr bool is_packed(ValueKind kind)
constexpr IndependentHeapType kWasmStringViewIter
constexpr IndependentHeapType kWasmContRef
constexpr IndependentHeapType kWasmI31Ref
constexpr IndependentValueType kWasmF16
constexpr IndependentHeapType kWasmFuncRef
constexpr int value_kind_size_log2(ValueKind kind)
const wasm::FunctionSig * GetI32Sig(Zone *zone, const wasm::FunctionSig *sig)
constexpr size_t kV8MaxWasmTypes
Definition wasm-limits.h:30
constexpr IndependentHeapType kWasmTop
constexpr bool is_object_reference(ValueKind kind)
constexpr IndependentHeapType kWasmRefI31
constexpr ValueKind unpacked(ValueKind kind)
constexpr IndependentHeapType kWasmExnRef
constexpr IndependentHeapType kWasmRefExternString
static constexpr bool kNotShared
Definition value-type.h:101
constexpr IndependentHeapType kWasmStringViewWtf16
constexpr IndependentHeapType kWasmVoid
constexpr IndependentHeapType kWasmStructRef
constexpr IndependentHeapType kWasmNullContRef
constexpr int value_kind_size(ValueKind kind)
constexpr IndependentHeapType kWasmBottom
std::ostream & operator<<(std::ostream &os, LiftoffVarState slot)
constexpr IndependentValueType kWasmS128
constexpr int kMaxValueTypeSize
Definition value-type.h:49
constexpr IndependentValueType kWasmF64
constexpr bool is_reference(ValueKind kind)
constexpr IndependentValueType kWasmI64
constexpr IndependentValueType kWasmI16
constexpr IndependentHeapType kWasmRefString
constexpr IndependentHeapType kWasmArrayRef
constexpr IndependentHeapType kWasmNullExnRef
constexpr int kTaggedSize
Definition globals.h:542
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
kWasmInternalFunctionIndirectPointerTag kProtectedInstanceDataOffset sig
constexpr int kSystemPointerSize
Definition globals.h:410
constexpr int kTaggedSizeLog2
Definition globals.h:543
const int kSmiValueSize
V8_EXPORT_PRIVATE FlagValues v8_flags
constexpr int kUInt32Size
Definition globals.h:403
bool is_signed(Condition cond)
Definition c-api.cc:87
#define COUNT(...)
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define ASSERT_TRIVIALLY_COPYABLE(T)
Definition macros.h:267
#define V8_EXPORT_PRIVATE
Definition macros.h:460
auto operator<=>(CanonicalTypeIndex other) const
Definition value-type.h:83
bool operator==(CanonicalTypeIndex other) const
Definition value-type.h:80
static constexpr CanonicalTypeIndex Invalid()
Definition value-type.h:89
static constexpr ModuleTypeIndex Invalid()
Definition value-type.h:73
auto operator<=>(ModuleTypeIndex other) const
Definition value-type.h:67
bool operator==(ModuleTypeIndex other) const
Definition value-type.h:66
static constexpr uint32_t kInvalid
Definition value-type.h:57
constexpr bool valid() const
Definition value-type.h:58
#define V8_LIKELY(condition)
Definition v8config.h:661
#define FOREACH_STORE_TYPE(V)
#define NULLTYPE(name,...)
#define LOAD_SIZE(_, __, memtype)
#define ELEM_SIZE_LOG2(kind, log2Size,...)
#define MEMTYPE(_, __, memtype)
#define FOREACH_NUMERIC_VALUE_TYPE(V)
Definition value-type.h:31
#define FOREACH_ABSTRACT_TYPE(V)
Definition value-type.h:175
#define MEMREP(_, __, memrep)
#define VALUE_KIND_SIZE_LOG2(kind, log2Size,...)
#define SHORT_NAME(kind, log2, code, mtype, shortName,...)
#define KIND_NAME(kind, log2Size, code, machineType, shortName, kindName,...)
#define VALUE_TYPE(type,...)
#define FOREACH_NONE_TYPE(V)
Definition value-type.h:168
#define REF
Definition value-type.h:160
#define FOREACH_LOAD_TYPE(V)
#define MACH_TYPE(kind, log2Size, code, machineType,...)
#define FOREACH_VALUE_TYPE(V)
Definition value-type.h:41
#define STORE_SIZE(_, __, memrep)
#define SENTINEL
Definition value-type.h:161
wasm::ValueType type