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_CODEGEN_MACHINE_TYPE_H_
6 #define V8_CODEGEN_MACHINE_TYPE_H_
7
8 #include <iosfwd>
9
10 #include "include/v8-fast-api-calls.h"
11 #include "src/base/bits.h"
12 #include "src/common/globals.h"
13 #include "src/flags/flags.h"
14
15 namespace v8 {
16 namespace internal {
17
18 enum class MachineRepresentation : uint8_t {
19 kNone,
20 kBit,
21 // Integral representations must be consecutive, in order of increasing order.
22 kWord8,
23 kWord16,
24 kWord32,
25 kWord64,
26 // (uncompressed) MapWord
27 // kMapWord is the representation of a map word, i.e. a map in the header
28 // of a HeapObject.
29 // If V8_MAP_PACKING is disabled, a map word is just the map itself. Hence
30 // kMapWord is equivalent to kTaggedPointer -- in fact it will be
31 // translated to kTaggedPointer during memory lowering.
32 // If V8_MAP_PACKING is enabled, a map word is a Smi-like encoding of a map
33 // and some meta data. Memory lowering of kMapWord loads/stores
34 // produces low-level kTagged loads/stores plus the necessary
35 // decode/encode operations.
36 // In either case, the kMapWord representation is not used after memory
37 // lowering.
38 kMapWord,
39 kTaggedSigned, // (uncompressed) Smi
40 kTaggedPointer, // (uncompressed) HeapObject
41 kTagged, // (uncompressed) Object (Smi or HeapObject)
42 kCompressedPointer, // (compressed) HeapObject
43 kCompressed, // (compressed) Object (Smi or HeapObject)
44 // A 64-bit pointer encoded in a way (e.g. as offset) that guarantees it will
45 // point into the sandbox.
46 kSandboxedPointer,
47 // FP and SIMD representations must be last, and in order of increasing size.
48 kFloat32,
49 kFloat64,
50 kSimd128,
51 kFirstFPRepresentation = kFloat32,
52 kLastRepresentation = kSimd128
53 };
54
55 bool IsSubtype(MachineRepresentation rep1, MachineRepresentation rep2);
56
57 #define ASSERT_CONSECUTIVE(rep1, rep2) \
58 static_assert(static_cast<uint8_t>(MachineRepresentation::k##rep1) + 1 == \
59 static_cast<uint8_t>(MachineRepresentation::k##rep2), \
60 #rep1 " and " #rep2 " must be consecutive.");
61
62 ASSERT_CONSECUTIVE(Word8, Word16)
63 ASSERT_CONSECUTIVE(Word16, Word32)
64 ASSERT_CONSECUTIVE(Word32, Word64)
65 ASSERT_CONSECUTIVE(Float32, Float64)
66 ASSERT_CONSECUTIVE(Float64, Simd128)
67 #undef ASSERT_CONSECUTIVE
68
69 static_assert(MachineRepresentation::kLastRepresentation ==
70 MachineRepresentation::kSimd128,
71 "FP and SIMD representations must be last.");
72
73 static_assert(static_cast<int>(MachineRepresentation::kLastRepresentation) <
74 kIntSize * kBitsPerByte,
75 "Bit masks of MachineRepresentation should fit in an int");
76
77 V8_EXPORT_PRIVATE const char* MachineReprToString(MachineRepresentation);
78
79 enum class MachineSemantic : uint8_t {
80 kNone,
81 kBool,
82 kInt32,
83 kUint32,
84 kInt64,
85 kUint64,
86 kNumber,
87 kAny
88 };
89
90 V8_EXPORT_PRIVATE inline constexpr int ElementSizeLog2Of(MachineRepresentation);
91
92 V8_EXPORT_PRIVATE inline constexpr int ElementSizeInBytes(
93 MachineRepresentation);
94
95 class MachineType {
96 public:
MachineType()97 constexpr MachineType()
98 : representation_(MachineRepresentation::kNone),
99 semantic_(MachineSemantic::kNone) {}
MachineType(MachineRepresentation representation,MachineSemantic semantic)100 constexpr MachineType(MachineRepresentation representation,
101 MachineSemantic semantic)
102 : representation_(representation), semantic_(semantic) {}
103
104 constexpr bool operator==(MachineType other) const {
105 return representation() == other.representation() &&
106 semantic() == other.semantic();
107 }
108
109 constexpr bool operator!=(MachineType other) const {
110 return !(*this == other);
111 }
112
representation()113 constexpr MachineRepresentation representation() const {
114 return representation_;
115 }
semantic()116 constexpr MachineSemantic semantic() const { return semantic_; }
117
IsNone()118 constexpr bool IsNone() const {
119 return representation() == MachineRepresentation::kNone;
120 }
121
IsMapWord()122 constexpr bool IsMapWord() const {
123 return representation() == MachineRepresentation::kMapWord;
124 }
125
IsSigned()126 constexpr bool IsSigned() const {
127 return semantic() == MachineSemantic::kInt32 ||
128 semantic() == MachineSemantic::kInt64;
129 }
IsUnsigned()130 constexpr bool IsUnsigned() const {
131 return semantic() == MachineSemantic::kUint32 ||
132 semantic() == MachineSemantic::kUint64;
133 }
IsTagged()134 constexpr bool IsTagged() const {
135 return representation() == MachineRepresentation::kTaggedPointer ||
136 representation() == MachineRepresentation::kTaggedSigned ||
137 representation() == MachineRepresentation::kTagged;
138 }
IsTaggedSigned()139 constexpr bool IsTaggedSigned() const {
140 return representation() == MachineRepresentation::kTaggedSigned;
141 }
IsTaggedPointer()142 constexpr bool IsTaggedPointer() const {
143 return representation() == MachineRepresentation::kTaggedPointer;
144 }
IsCompressed()145 constexpr bool IsCompressed() const {
146 return representation() == MachineRepresentation::kCompressedPointer ||
147 representation() == MachineRepresentation::kCompressed;
148 }
IsCompressedPointer()149 constexpr bool IsCompressedPointer() const {
150 return representation() == MachineRepresentation::kCompressedPointer;
151 }
TaggedRepresentation()152 constexpr static MachineRepresentation TaggedRepresentation() {
153 return (kTaggedSize == 4) ? MachineRepresentation::kWord32
154 : MachineRepresentation::kWord64;
155 }
PointerRepresentation()156 constexpr static MachineRepresentation PointerRepresentation() {
157 return (kSystemPointerSize == 4) ? MachineRepresentation::kWord32
158 : MachineRepresentation::kWord64;
159 }
UintPtr()160 constexpr static MachineType UintPtr() {
161 return (kSystemPointerSize == 4) ? Uint32() : Uint64();
162 }
IntPtr()163 constexpr static MachineType IntPtr() {
164 return (kSystemPointerSize == 4) ? Int32() : Int64();
165 }
Int8()166 constexpr static MachineType Int8() {
167 return MachineType(MachineRepresentation::kWord8, MachineSemantic::kInt32);
168 }
Uint8()169 constexpr static MachineType Uint8() {
170 return MachineType(MachineRepresentation::kWord8, MachineSemantic::kUint32);
171 }
Int16()172 constexpr static MachineType Int16() {
173 return MachineType(MachineRepresentation::kWord16, MachineSemantic::kInt32);
174 }
Uint16()175 constexpr static MachineType Uint16() {
176 return MachineType(MachineRepresentation::kWord16,
177 MachineSemantic::kUint32);
178 }
Int32()179 constexpr static MachineType Int32() {
180 return MachineType(MachineRepresentation::kWord32, MachineSemantic::kInt32);
181 }
Uint32()182 constexpr static MachineType Uint32() {
183 return MachineType(MachineRepresentation::kWord32,
184 MachineSemantic::kUint32);
185 }
Int64()186 constexpr static MachineType Int64() {
187 return MachineType(MachineRepresentation::kWord64, MachineSemantic::kInt64);
188 }
Uint64()189 constexpr static MachineType Uint64() {
190 return MachineType(MachineRepresentation::kWord64,
191 MachineSemantic::kUint64);
192 }
Float32()193 constexpr static MachineType Float32() {
194 return MachineType(MachineRepresentation::kFloat32,
195 MachineSemantic::kNumber);
196 }
Float64()197 constexpr static MachineType Float64() {
198 return MachineType(MachineRepresentation::kFloat64,
199 MachineSemantic::kNumber);
200 }
Simd128()201 constexpr static MachineType Simd128() {
202 return MachineType(MachineRepresentation::kSimd128, MachineSemantic::kNone);
203 }
Pointer()204 constexpr static MachineType Pointer() {
205 return MachineType(PointerRepresentation(), MachineSemantic::kNone);
206 }
TaggedPointer()207 constexpr static MachineType TaggedPointer() {
208 return MachineType(MachineRepresentation::kTaggedPointer,
209 MachineSemantic::kAny);
210 }
MapInHeader()211 constexpr static MachineType MapInHeader() {
212 return MachineType(MachineRepresentation::kMapWord, MachineSemantic::kAny);
213 }
TaggedSigned()214 constexpr static MachineType TaggedSigned() {
215 return MachineType(MachineRepresentation::kTaggedSigned,
216 MachineSemantic::kInt32);
217 }
AnyTagged()218 constexpr static MachineType AnyTagged() {
219 return MachineType(MachineRepresentation::kTagged, MachineSemantic::kAny);
220 }
CompressedPointer()221 constexpr static MachineType CompressedPointer() {
222 return MachineType(MachineRepresentation::kCompressedPointer,
223 MachineSemantic::kAny);
224 }
AnyCompressed()225 constexpr static MachineType AnyCompressed() {
226 return MachineType(MachineRepresentation::kCompressed,
227 MachineSemantic::kAny);
228 }
SandboxedPointer()229 constexpr static MachineType SandboxedPointer() {
230 return MachineType(MachineRepresentation::kSandboxedPointer,
231 MachineSemantic::kNone);
232 }
Bool()233 constexpr static MachineType Bool() {
234 return MachineType(MachineRepresentation::kBit, MachineSemantic::kBool);
235 }
None()236 constexpr static MachineType None() {
237 return MachineType(MachineRepresentation::kNone, MachineSemantic::kNone);
238 }
239
240 static MachineType TypeForRepresentation(const MachineRepresentation& rep,
241 bool isSigned = true) {
242 switch (rep) {
243 case MachineRepresentation::kNone:
244 return MachineType::None();
245 case MachineRepresentation::kBit:
246 return MachineType::Bool();
247 case MachineRepresentation::kWord8:
248 return isSigned ? MachineType::Int8() : MachineType::Uint8();
249 case MachineRepresentation::kWord16:
250 return isSigned ? MachineType::Int16() : MachineType::Uint16();
251 case MachineRepresentation::kWord32:
252 return isSigned ? MachineType::Int32() : MachineType::Uint32();
253 case MachineRepresentation::kWord64:
254 return isSigned ? MachineType::Int64() : MachineType::Uint64();
255 case MachineRepresentation::kFloat32:
256 return MachineType::Float32();
257 case MachineRepresentation::kFloat64:
258 return MachineType::Float64();
259 case MachineRepresentation::kSimd128:
260 return MachineType::Simd128();
261 case MachineRepresentation::kTagged:
262 return MachineType::AnyTagged();
263 case MachineRepresentation::kTaggedSigned:
264 return MachineType::TaggedSigned();
265 case MachineRepresentation::kTaggedPointer:
266 return MachineType::TaggedPointer();
267 case MachineRepresentation::kCompressed:
268 return MachineType::AnyCompressed();
269 case MachineRepresentation::kCompressedPointer:
270 return MachineType::CompressedPointer();
271 case MachineRepresentation::kSandboxedPointer:
272 return MachineType::SandboxedPointer();
273 default:
274 UNREACHABLE();
275 }
276 }
277
TypeForCType(const CTypeInfo & type)278 static MachineType TypeForCType(const CTypeInfo& type) {
279 switch (type.GetType()) {
280 case CTypeInfo::Type::kVoid:
281 return MachineType::AnyTagged();
282 case CTypeInfo::Type::kBool:
283 return MachineType::Bool();
284 case CTypeInfo::Type::kInt32:
285 return MachineType::Int32();
286 case CTypeInfo::Type::kUint32:
287 return MachineType::Uint32();
288 case CTypeInfo::Type::kInt64:
289 return MachineType::Int64();
290 case CTypeInfo::Type::kAny:
291 static_assert(
292 sizeof(AnyCType) == kInt64Size,
293 "CTypeInfo::Type::kAny is assumed to be of size 64 bits.");
294 return MachineType::Int64();
295 case CTypeInfo::Type::kUint64:
296 return MachineType::Uint64();
297 case CTypeInfo::Type::kFloat32:
298 return MachineType::Float32();
299 case CTypeInfo::Type::kFloat64:
300 return MachineType::Float64();
301 case CTypeInfo::Type::kV8Value:
302 case CTypeInfo::Type::kApiObject:
303 return MachineType::AnyTagged();
304 }
305 }
306
LessThanOrEqualPointerSize()307 constexpr bool LessThanOrEqualPointerSize() const {
308 return ElementSizeLog2Of(this->representation()) <= kSystemPointerSizeLog2;
309 }
310
MemSize()311 constexpr byte MemSize() const {
312 return 1 << i::ElementSizeLog2Of(this->representation());
313 }
314
315 private:
316 MachineRepresentation representation_;
317 MachineSemantic semantic_;
318 };
319
hash_value(MachineRepresentation rep)320 V8_INLINE size_t hash_value(MachineRepresentation rep) {
321 return static_cast<size_t>(rep);
322 }
323
hash_value(MachineType type)324 V8_INLINE size_t hash_value(MachineType type) {
325 return static_cast<size_t>(type.representation()) +
326 static_cast<size_t>(type.semantic()) * 16;
327 }
328
329 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
330 MachineRepresentation rep);
331 std::ostream& operator<<(std::ostream& os, MachineSemantic type);
332 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, MachineType type);
333
IsIntegral(MachineRepresentation rep)334 inline bool IsIntegral(MachineRepresentation rep) {
335 return rep >= MachineRepresentation::kWord8 &&
336 rep <= MachineRepresentation::kWord64;
337 }
338
IsFloatingPoint(MachineRepresentation rep)339 inline bool IsFloatingPoint(MachineRepresentation rep) {
340 return rep >= MachineRepresentation::kFirstFPRepresentation;
341 }
342
IsSimd128(MachineRepresentation rep)343 inline bool IsSimd128(MachineRepresentation rep) {
344 return rep == MachineRepresentation::kSimd128;
345 }
346
CanBeTaggedPointer(MachineRepresentation rep)347 inline bool CanBeTaggedPointer(MachineRepresentation rep) {
348 return rep == MachineRepresentation::kTagged ||
349 rep == MachineRepresentation::kTaggedPointer ||
350 rep == MachineRepresentation::kMapWord;
351 }
352
CanBeTaggedSigned(MachineRepresentation rep)353 inline bool CanBeTaggedSigned(MachineRepresentation rep) {
354 return rep == MachineRepresentation::kTagged ||
355 rep == MachineRepresentation::kTaggedSigned;
356 }
357
IsAnyTagged(MachineRepresentation rep)358 inline bool IsAnyTagged(MachineRepresentation rep) {
359 return CanBeTaggedPointer(rep) || rep == MachineRepresentation::kTaggedSigned;
360 }
361
CanBeCompressedPointer(MachineRepresentation rep)362 inline bool CanBeCompressedPointer(MachineRepresentation rep) {
363 return rep == MachineRepresentation::kCompressed ||
364 rep == MachineRepresentation::kCompressedPointer;
365 }
366
CanBeTaggedOrCompressedPointer(MachineRepresentation rep)367 inline bool CanBeTaggedOrCompressedPointer(MachineRepresentation rep) {
368 return CanBeTaggedPointer(rep) || CanBeCompressedPointer(rep);
369 }
370
IsAnyCompressed(MachineRepresentation rep)371 inline bool IsAnyCompressed(MachineRepresentation rep) {
372 return CanBeCompressedPointer(rep);
373 }
374
375 // Gets the log2 of the element size in bytes of the machine type.
ElementSizeLog2Of(MachineRepresentation rep)376 V8_EXPORT_PRIVATE inline constexpr int ElementSizeLog2Of(
377 MachineRepresentation rep) {
378 switch (rep) {
379 case MachineRepresentation::kBit:
380 case MachineRepresentation::kWord8:
381 return 0;
382 case MachineRepresentation::kWord16:
383 return 1;
384 case MachineRepresentation::kWord32:
385 case MachineRepresentation::kFloat32:
386 return 2;
387 case MachineRepresentation::kWord64:
388 case MachineRepresentation::kFloat64:
389 return 3;
390 case MachineRepresentation::kSimd128:
391 return 4;
392 case MachineRepresentation::kTaggedSigned:
393 case MachineRepresentation::kTaggedPointer:
394 case MachineRepresentation::kTagged:
395 case MachineRepresentation::kMapWord:
396 case MachineRepresentation::kCompressedPointer:
397 case MachineRepresentation::kCompressed:
398 return kTaggedSizeLog2;
399 case MachineRepresentation::kSandboxedPointer:
400 return kSystemPointerSizeLog2;
401 default:
402 UNREACHABLE();
403 }
404 }
405
406 constexpr int kMaximumReprSizeLog2 =
407 ElementSizeLog2Of(MachineRepresentation::kSimd128);
408 constexpr int kMaximumReprSizeInBytes = 1 << kTaggedSizeLog2;
409
410 STATIC_ASSERT(kMaximumReprSizeLog2 >=
411 ElementSizeLog2Of(MachineRepresentation::kTagged));
412 STATIC_ASSERT(kMaximumReprSizeLog2 >=
413 ElementSizeLog2Of(MachineRepresentation::kWord64));
414
ElementSizeInBytes(MachineRepresentation rep)415 V8_EXPORT_PRIVATE inline constexpr int ElementSizeInBytes(
416 MachineRepresentation rep) {
417 return 1 << ElementSizeLog2Of(rep);
418 }
419
ElementSizeInPointers(MachineRepresentation rep)420 V8_EXPORT_PRIVATE inline constexpr int ElementSizeInPointers(
421 MachineRepresentation rep) {
422 return (ElementSizeInBytes(rep) + kSystemPointerSize - 1) /
423 kSystemPointerSize;
424 }
425
426 // Converts representation to bit for representation masks.
RepresentationBit(MachineRepresentation rep)427 V8_EXPORT_PRIVATE inline constexpr int RepresentationBit(
428 MachineRepresentation rep) {
429 return 1 << static_cast<int>(rep);
430 }
431
432 } // namespace internal
433 } // namespace v8
434
435 #endif // V8_CODEGEN_MACHINE_TYPE_H_
436