1 // Copyright 2014 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_TYPE_CACHE_H_
6 #define V8_TYPE_CACHE_H_
7 
8 #include "src/types.h"
9 
10 namespace v8 {
11 namespace internal {
12 
13 class TypeCache final {
14  private:
15   // This has to be first for the initialization magic to work.
16   Zone zone_;
17 
18  public:
19   static TypeCache const& Get();
20 
21   TypeCache() = default;
22 
23   Type* const kInt8 =
24       CreateNative(CreateRange<int8_t>(), Type::UntaggedIntegral8());
25   Type* const kUint8 =
26       CreateNative(CreateRange<uint8_t>(), Type::UntaggedIntegral8());
27   Type* const kUint8Clamped = kUint8;
28   Type* const kInt16 =
29       CreateNative(CreateRange<int16_t>(), Type::UntaggedIntegral16());
30   Type* const kUint16 =
31       CreateNative(CreateRange<uint16_t>(), Type::UntaggedIntegral16());
32   Type* const kInt32 =
33       CreateNative(Type::Signed32(), Type::UntaggedIntegral32());
34   Type* const kUint32 =
35       CreateNative(Type::Unsigned32(), Type::UntaggedIntegral32());
36   Type* const kFloat32 = CreateNative(Type::Number(), Type::UntaggedFloat32());
37   Type* const kFloat64 = CreateNative(Type::Number(), Type::UntaggedFloat64());
38 
39   Type* const kSmi = CreateNative(Type::SignedSmall(), Type::TaggedSigned());
40   Type* const kHeapNumber = CreateNative(Type::Number(), Type::TaggedPointer());
41 
42   Type* const kSingletonZero = CreateRange(0.0, 0.0);
43   Type* const kSingletonOne = CreateRange(1.0, 1.0);
44   Type* const kZeroOrOne = CreateRange(0.0, 1.0);
45   Type* const kZeroToThirtyOne = CreateRange(0.0, 31.0);
46   Type* const kZeroToThirtyTwo = CreateRange(0.0, 32.0);
47   Type* const kZeroish =
48       Type::Union(kSingletonZero, Type::MinusZeroOrNaN(), zone());
49   Type* const kInteger = CreateRange(-V8_INFINITY, V8_INFINITY);
50   Type* const kPositiveInteger = CreateRange(0.0, V8_INFINITY);
51   Type* const kIntegerOrMinusZero =
52       Type::Union(kInteger, Type::MinusZero(), zone());
53   Type* const kIntegerOrMinusZeroOrNaN =
54       Type::Union(kIntegerOrMinusZero, Type::NaN(), zone());
55 
56   Type* const kAdditiveSafeInteger =
57       CreateRange(-4503599627370496.0, 4503599627370496.0);
58   Type* const kSafeInteger = CreateRange(-kMaxSafeInteger, kMaxSafeInteger);
59   Type* const kPositiveSafeInteger = CreateRange(0.0, kMaxSafeInteger);
60 
61   Type* const kUntaggedUndefined =
62       Type::Intersect(Type::Undefined(), Type::Untagged(), zone());
63 
64   // Asm.js related types.
65   Type* const kAsmSigned = kInt32;
66   Type* const kAsmUnsigned = kUint32;
67   Type* const kAsmInt = Type::Union(kAsmSigned, kAsmUnsigned, zone());
68   Type* const kAsmFixnum = Type::Intersect(kAsmSigned, kAsmUnsigned, zone());
69   Type* const kAsmFloat = kFloat32;
70   Type* const kAsmDouble = kFloat64;
71   Type* const kAsmFloatQ = Type::Union(kAsmFloat, kUntaggedUndefined, zone());
72   Type* const kAsmDoubleQ = Type::Union(kAsmDouble, kUntaggedUndefined, zone());
73   // Not part of the Asm.js type hierarchy, but represents a part of what
74   // intish encompasses.
75   Type* const kAsmIntQ = Type::Union(kAsmInt, kUntaggedUndefined, zone());
76   Type* const kAsmFloatDoubleQ = Type::Union(kAsmFloatQ, kAsmDoubleQ, zone());
77   // Asm.js size unions.
78   Type* const kAsmSize8 = Type::Union(kInt8, kUint8, zone());
79   Type* const kAsmSize16 = Type::Union(kInt16, kUint16, zone());
80   Type* const kAsmSize32 =
81       Type::Union(Type::Union(kInt32, kUint32, zone()), kAsmFloat, zone());
82   Type* const kAsmSize64 = kFloat64;
83   // Asm.js other types.
84   Type* const kAsmComparable = Type::Union(
85       kAsmSigned,
86       Type::Union(kAsmUnsigned, Type::Union(kAsmDouble, kAsmFloat, zone()),
87                   zone()),
88       zone());
89   Type* const kAsmIntArrayElement =
90       Type::Union(Type::Union(kInt8, kUint8, zone()),
91                   Type::Union(Type::Union(kInt16, kUint16, zone()),
92                               Type::Union(kInt32, kUint32, zone()), zone()),
93                   zone());
94 
95   // The FixedArray::length property always containts a smi in the range
96   // [0, FixedArray::kMaxLength].
97   Type* const kFixedArrayLengthType = CreateNative(
98       CreateRange(0.0, FixedArray::kMaxLength), Type::TaggedSigned());
99 
100   // The FixedDoubleArray::length property always containts a smi in the range
101   // [0, FixedDoubleArray::kMaxLength].
102   Type* const kFixedDoubleArrayLengthType = CreateNative(
103       CreateRange(0.0, FixedDoubleArray::kMaxLength), Type::TaggedSigned());
104 
105   // The JSArray::length property always contains a tagged number in the range
106   // [0, kMaxUInt32].
107   Type* const kJSArrayLengthType =
108       CreateNative(Type::Unsigned32(), Type::Tagged());
109 
110   // The String::length property always contains a smi in the range
111   // [0, String::kMaxLength].
112   Type* const kStringLengthType =
113       CreateNative(CreateRange(0.0, String::kMaxLength), Type::TaggedSigned());
114 
115   // When initializing arrays, we'll unfold the loop if the number of
116   // elements is known to be of this type.
117   Type* const kElementLoopUnrollType = CreateRange(0.0, 16.0);
118 
119 #define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \
120   Type* const k##TypeName##Array = CreateArray(k##TypeName);
TYPED_ARRAYS(TYPED_ARRAY)121   TYPED_ARRAYS(TYPED_ARRAY)
122 #undef TYPED_ARRAY
123 
124  private:
125   Type* CreateArray(Type* element) { return Type::Array(element, zone()); }
126 
CreateArrayFunction(Type * array)127   Type* CreateArrayFunction(Type* array) {
128     Type* arg1 = Type::Union(Type::Unsigned32(), Type::Object(), zone());
129     Type* arg2 = Type::Union(Type::Unsigned32(), Type::Undefined(), zone());
130     Type* arg3 = arg2;
131     return Type::Function(array, arg1, arg2, arg3, zone());
132   }
133 
CreateNative(Type * semantic,Type * representation)134   Type* CreateNative(Type* semantic, Type* representation) {
135     return Type::Intersect(semantic, representation, zone());
136   }
137 
138   template <typename T>
CreateRange()139   Type* CreateRange() {
140     return CreateRange(std::numeric_limits<T>::min(),
141                        std::numeric_limits<T>::max());
142   }
143 
CreateRange(double min,double max)144   Type* CreateRange(double min, double max) {
145     return Type::Range(min, max, zone());
146   }
147 
zone()148   Zone* zone() { return &zone_; }
149 };
150 
151 }  // namespace internal
152 }  // namespace v8
153 
154 #endif  // V8_TYPE_CACHE_H_
155