• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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