// Copyright 2014 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_COMPILER_TYPES_H_ #define V8_COMPILER_TYPES_H_ #include "src/base/compiler-specific.h" #include "src/common/globals.h" #include "src/compiler/heap-refs.h" #include "src/handles/handles.h" #include "src/numbers/conversions.h" #include "src/objects/objects.h" #include "src/utils/ostreams.h" #ifdef V8_ENABLE_WEBASSEMBLY #include "src/wasm/value-type.h" #endif namespace v8 { namespace internal { namespace wasm { struct TypeInModule; } namespace compiler { // SUMMARY // // A simple type system for compiler-internal use. It is based entirely on // union types, and all subtyping hence amounts to set inclusion. Besides the // obvious primitive types and some predefined unions, the type language also // can express class types (a.k.a. specific maps) and singleton types (i.e., // concrete constants). // // The following equations and inequations hold: // // None <= T // T <= Any // // Number = Signed32 \/ Unsigned32 \/ Double // Smi <= Signed32 // Name = String \/ Symbol // UniqueName = InternalizedString \/ Symbol // InternalizedString < String // // Receiver = Object \/ Proxy // OtherUndetectable < Object // DetectableReceiver = Receiver - OtherUndetectable // // Constant(x) < T iff instance_type(map(x)) < T // // None <= Machine <= Any // // RANGE TYPES // // A range type represents a continuous integer interval by its minimum and // maximum value. Either value may be an infinity, in which case that infinity // itself is also included in the range. A range never contains NaN or -0. // // If a value v happens to be an integer n, then Constant(v) is considered a // subtype of Range(n, n) (and therefore also a subtype of any larger range). // In order to avoid large unions, however, it is usually a good idea to use // Range rather than Constant. // // // PREDICATES // // There are two main functions for testing types: // // T1.Is(T2) -- tests whether T1 is included in T2 (i.e., T1 <= T2) // T1.Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0) // // Typically, the former is to be used to select representations (e.g., via // T.Is(SignedSmall())), and the latter to check whether a specific case needs // handling (e.g., via T.Maybe(Number())). // // There is no functionality to discover whether a type is a leaf in the // lattice. That is intentional. It should always be possible to refine the // lattice (e.g., splitting up number types further) without invalidating any // existing assumptions or tests. // Consequently, do not normally use Equals for type tests, always use Is! // // // PROPERTIES // // Various formal properties hold for constructors, operators, and predicates // over types. For example, constructors are injective and subtyping is a // complete partial order. // // See test/cctest/test-types.cc for a comprehensive executable specification, // especially with respect to the properties of the more exotic 'temporal' // constructors and predicates (those prefixed 'Now'). // // // IMPLEMENTATION // // Internally, all 'primitive' types, and their unions, are represented as // bitsets. Bit 0 is reserved for tagging. Only structured types require // allocation. // ----------------------------------------------------------------------------- // Values for bitset types // clang-format off #define INTERNAL_BITSET_TYPE_LIST(V) … \ #define PROPER_ATOMIC_BITSET_TYPE_LOW_LIST(V) … // We split the macro list into two parts because the Torque equivalent in // turbofan-types.tq uses two 32bit bitfield structs. #define PROPER_ATOMIC_BITSET_TYPE_HIGH_LIST(V) … #define PROPER_BITSET_TYPE_LIST(V) … // clang-format on /* * The following diagrams show how integers (in the mathematical sense) are * divided among the different atomic numerical types. * * ON OS32 N31 U30 OU31 OU32 ON * ______[_______[_______[_______[_______[_______[_______ * -2^31 -2^30 0 2^30 2^31 2^32 * * E.g., OtherUnsigned32 (OU32) covers all integers from 2^31 to 2^32-1. * * Some of the atomic numerical bitsets are internal only (see * INTERNAL_BITSET_TYPE_LIST). To a types user, they should only occur in * union with certain other bitsets. For instance, OtherNumber should only * occur as part of PlainNumber. */ #define BITSET_TYPE_LIST(V) … class JSHeapBroker; class HeapConstantType; class OtherNumberConstantType; class TupleType; class Type; class UnionType; // ----------------------------------------------------------------------------- // Bitset types (internal). class V8_EXPORT_PRIVATE BitsetType { … }; // ----------------------------------------------------------------------------- // Superclass for non-bitset types (internal). class TypeBase { … }; // ----------------------------------------------------------------------------- // Range types. class RangeType : public TypeBase { … }; #ifdef V8_ENABLE_WEBASSEMBLY class WasmType : public TypeBase { … }; #endif // V8_ENABLE_WEBASSEMBLY // ----------------------------------------------------------------------------- // The actual type. class V8_EXPORT_PRIVATE Type { … }; inline size_t hash_value(Type type) { … } V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, Type type); // ----------------------------------------------------------------------------- // Constant types. class OtherNumberConstantType : public TypeBase { … }; class V8_EXPORT_PRIVATE HeapConstantType : public NON_EXPORTED_BASE(TypeBase) { … }; // ----------------------------------------------------------------------------- // Superclass for types with variable number of type fields. class StructuralType : public TypeBase { … }; // ----------------------------------------------------------------------------- // Tuple types. class TupleType : public StructuralType { … }; // ----------------------------------------------------------------------------- // Union types (internal). // A union is a structured type with the following invariants: // - its length is at least 2 // - at most one field is a bitset, and it must go into index 0 // - no field is a union // - no field is a subtype of any other field class UnionType : public StructuralType { … }; } // namespace compiler } // namespace internal } // namespace v8 #endif // V8_COMPILER_TYPES_H_