machine-type.h 16.2 KB
Newer Older
1 2 3 4
// 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.

5 6
#ifndef V8_CODEGEN_MACHINE_TYPE_H_
#define V8_CODEGEN_MACHINE_TYPE_H_
7

8
#include <iosfwd>
9
#include <limits>
10

11
#include "include/v8-fast-api-calls.h"
12
#include "src/base/bits.h"
13
#include "src/common/globals.h"
14
#include "src/flags/flags.h"
15

16 17 18
namespace v8 {
namespace internal {

19
enum class MachineRepresentation : uint8_t {
20 21
  kNone,
  kBit,
22
  // Integral representations must be consecutive, in order of increasing order.
23 24 25 26
  kWord8,
  kWord16,
  kWord32,
  kWord64,
27 28 29 30 31 32 33 34 35 36 37 38 39
  // (uncompressed) MapWord
  // kMapWord is the representation of a map word, i.e. a map in the header
  // of a HeapObject.
  // If V8_MAP_PACKING is disabled, a map word is just the map itself. Hence
  //     kMapWord is equivalent to kTaggedPointer -- in fact it will be
  //     translated to kTaggedPointer during memory lowering.
  // If V8_MAP_PACKING is enabled, a map word is a Smi-like encoding of a map
  //     and some meta data. Memory lowering of kMapWord loads/stores
  //     produces low-level kTagged loads/stores plus the necessary
  //     decode/encode operations.
  // In either case, the kMapWord representation is not used after memory
  // lowering.
  kMapWord,
40 41 42 43 44
  kTaggedSigned,       // (uncompressed) Smi
  kTaggedPointer,      // (uncompressed) HeapObject
  kTagged,             // (uncompressed) Object (Smi or HeapObject)
  kCompressedPointer,  // (compressed) HeapObject
  kCompressed,         // (compressed) Object (Smi or HeapObject)
45
  // A 64-bit pointer encoded in a way (e.g. as offset) that guarantees it will
Samuel Groß's avatar
Samuel Groß committed
46 47
  // point into the sandbox.
  kSandboxedPointer,
48
  // FP and SIMD representations must be last, and in order of increasing size.
49 50 51
  kFloat32,
  kFloat64,
  kSimd128,
52
  kSimd256,
53
  kFirstFPRepresentation = kFloat32,
54
  kLastRepresentation = kSimd256
55
};
56

57 58
bool IsSubtype(MachineRepresentation rep1, MachineRepresentation rep2);

59 60 61 62 63 64 65 66 67 68
#define ASSERT_CONSECUTIVE(rep1, rep2)                                      \
  static_assert(static_cast<uint8_t>(MachineRepresentation::k##rep1) + 1 == \
                    static_cast<uint8_t>(MachineRepresentation::k##rep2),   \
                #rep1 " and " #rep2 " must be consecutive.");

ASSERT_CONSECUTIVE(Word8, Word16)
ASSERT_CONSECUTIVE(Word16, Word32)
ASSERT_CONSECUTIVE(Word32, Word64)
ASSERT_CONSECUTIVE(Float32, Float64)
ASSERT_CONSECUTIVE(Float64, Simd128)
69
ASSERT_CONSECUTIVE(Simd128, Simd256)
70 71 72
#undef ASSERT_CONSECUTIVE

static_assert(MachineRepresentation::kLastRepresentation ==
73
                  MachineRepresentation::kSimd256,
74 75
              "FP and SIMD representations must be last.");

76 77 78 79
static_assert(static_cast<int>(MachineRepresentation::kLastRepresentation) <
                  kIntSize * kBitsPerByte,
              "Bit masks of MachineRepresentation should fit in an int");

80
V8_EXPORT_PRIVATE const char* MachineReprToString(MachineRepresentation);
81

82
enum class MachineSemantic : uint8_t {
83 84 85 86 87 88 89 90 91 92
  kNone,
  kBool,
  kInt32,
  kUint32,
  kInt64,
  kUint64,
  kNumber,
  kAny
};

93
V8_EXPORT_PRIVATE inline constexpr int ElementSizeLog2Of(MachineRepresentation);
94

95 96
V8_EXPORT_PRIVATE inline constexpr int ElementSizeInBytes(
    MachineRepresentation);
97

98 99
class MachineType {
 public:
100
  constexpr MachineType()
101 102
      : representation_(MachineRepresentation::kNone),
        semantic_(MachineSemantic::kNone) {}
103 104
  constexpr MachineType(MachineRepresentation representation,
                        MachineSemantic semantic)
105 106
      : representation_(representation), semantic_(semantic) {}

107
  constexpr bool operator==(MachineType other) const {
108 109 110 111
    return representation() == other.representation() &&
           semantic() == other.semantic();
  }

112 113 114
  constexpr bool operator!=(MachineType other) const {
    return !(*this == other);
  }
115

116 117 118 119
  constexpr MachineRepresentation representation() const {
    return representation_;
  }
  constexpr MachineSemantic semantic() const { return semantic_; }
120

121 122 123
  constexpr bool IsNone() const {
    return representation() == MachineRepresentation::kNone;
  }
124

125 126 127 128
  constexpr bool IsMapWord() const {
    return representation() == MachineRepresentation::kMapWord;
  }

129
  constexpr bool IsSigned() const {
130 131 132
    return semantic() == MachineSemantic::kInt32 ||
           semantic() == MachineSemantic::kInt64;
  }
133
  constexpr bool IsUnsigned() const {
134 135 136
    return semantic() == MachineSemantic::kUint32 ||
           semantic() == MachineSemantic::kUint64;
  }
137 138 139 140 141
  constexpr bool IsTagged() const {
    return representation() == MachineRepresentation::kTaggedPointer ||
           representation() == MachineRepresentation::kTaggedSigned ||
           representation() == MachineRepresentation::kTagged;
  }
142 143 144 145 146 147
  constexpr bool IsTaggedSigned() const {
    return representation() == MachineRepresentation::kTaggedSigned;
  }
  constexpr bool IsTaggedPointer() const {
    return representation() == MachineRepresentation::kTaggedPointer;
  }
148 149 150 151 152 153 154
  constexpr bool IsCompressed() const {
    return representation() == MachineRepresentation::kCompressedPointer ||
           representation() == MachineRepresentation::kCompressed;
  }
  constexpr bool IsCompressedPointer() const {
    return representation() == MachineRepresentation::kCompressedPointer;
  }
155 156 157 158
  constexpr static MachineRepresentation TaggedRepresentation() {
    return (kTaggedSize == 4) ? MachineRepresentation::kWord32
                              : MachineRepresentation::kWord64;
  }
159
  constexpr static MachineRepresentation PointerRepresentation() {
160 161
    return (kSystemPointerSize == 4) ? MachineRepresentation::kWord32
                                     : MachineRepresentation::kWord64;
162
  }
163
  constexpr static MachineType UintPtr() {
164
    return (kSystemPointerSize == 4) ? Uint32() : Uint64();
165
  }
166
  constexpr static MachineType IntPtr() {
167
    return (kSystemPointerSize == 4) ? Int32() : Int64();
168
  }
169
  constexpr static MachineType Int8() {
170 171
    return MachineType(MachineRepresentation::kWord8, MachineSemantic::kInt32);
  }
172
  constexpr static MachineType Uint8() {
173 174
    return MachineType(MachineRepresentation::kWord8, MachineSemantic::kUint32);
  }
175
  constexpr static MachineType Int16() {
176 177
    return MachineType(MachineRepresentation::kWord16, MachineSemantic::kInt32);
  }
178
  constexpr static MachineType Uint16() {
179 180 181
    return MachineType(MachineRepresentation::kWord16,
                       MachineSemantic::kUint32);
  }
182
  constexpr static MachineType Int32() {
183 184
    return MachineType(MachineRepresentation::kWord32, MachineSemantic::kInt32);
  }
185
  constexpr static MachineType Uint32() {
186 187 188
    return MachineType(MachineRepresentation::kWord32,
                       MachineSemantic::kUint32);
  }
189
  constexpr static MachineType Int64() {
190 191
    return MachineType(MachineRepresentation::kWord64, MachineSemantic::kInt64);
  }
192
  constexpr static MachineType Uint64() {
193 194 195
    return MachineType(MachineRepresentation::kWord64,
                       MachineSemantic::kUint64);
  }
196
  constexpr static MachineType Float32() {
197 198 199
    return MachineType(MachineRepresentation::kFloat32,
                       MachineSemantic::kNumber);
  }
200
  constexpr static MachineType Float64() {
201 202 203
    return MachineType(MachineRepresentation::kFloat64,
                       MachineSemantic::kNumber);
  }
204
  constexpr static MachineType Simd128() {
205 206
    return MachineType(MachineRepresentation::kSimd128, MachineSemantic::kNone);
  }
207 208 209
  constexpr static MachineType Simd256() {
    return MachineType(MachineRepresentation::kSimd256, MachineSemantic::kNone);
  }
210
  constexpr static MachineType Pointer() {
211 212
    return MachineType(PointerRepresentation(), MachineSemantic::kNone);
  }
213
  constexpr static MachineType TaggedPointer() {
214 215 216
    return MachineType(MachineRepresentation::kTaggedPointer,
                       MachineSemantic::kAny);
  }
217 218 219
  constexpr static MachineType MapInHeader() {
    return MachineType(MachineRepresentation::kMapWord, MachineSemantic::kAny);
  }
220
  constexpr static MachineType TaggedSigned() {
221 222 223
    return MachineType(MachineRepresentation::kTaggedSigned,
                       MachineSemantic::kInt32);
  }
224
  constexpr static MachineType AnyTagged() {
225 226
    return MachineType(MachineRepresentation::kTagged, MachineSemantic::kAny);
  }
227 228 229 230 231 232 233 234
  constexpr static MachineType CompressedPointer() {
    return MachineType(MachineRepresentation::kCompressedPointer,
                       MachineSemantic::kAny);
  }
  constexpr static MachineType AnyCompressed() {
    return MachineType(MachineRepresentation::kCompressed,
                       MachineSemantic::kAny);
  }
Samuel Groß's avatar
Samuel Groß committed
235 236
  constexpr static MachineType SandboxedPointer() {
    return MachineType(MachineRepresentation::kSandboxedPointer,
Samuel Groß's avatar
Samuel Groß committed
237 238
                       MachineSemantic::kNone);
  }
239
  constexpr static MachineType Bool() {
240 241
    return MachineType(MachineRepresentation::kBit, MachineSemantic::kBool);
  }
242
  constexpr static MachineType None() {
243 244 245
    return MachineType(MachineRepresentation::kNone, MachineSemantic::kNone);
  }

246
  static MachineType TypeForRepresentation(const MachineRepresentation& rep,
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
                                           bool isSigned = true) {
    switch (rep) {
      case MachineRepresentation::kNone:
        return MachineType::None();
      case MachineRepresentation::kBit:
        return MachineType::Bool();
      case MachineRepresentation::kWord8:
        return isSigned ? MachineType::Int8() : MachineType::Uint8();
      case MachineRepresentation::kWord16:
        return isSigned ? MachineType::Int16() : MachineType::Uint16();
      case MachineRepresentation::kWord32:
        return isSigned ? MachineType::Int32() : MachineType::Uint32();
      case MachineRepresentation::kWord64:
        return isSigned ? MachineType::Int64() : MachineType::Uint64();
      case MachineRepresentation::kFloat32:
        return MachineType::Float32();
      case MachineRepresentation::kFloat64:
        return MachineType::Float64();
      case MachineRepresentation::kSimd128:
        return MachineType::Simd128();
267 268
      case MachineRepresentation::kSimd256:
        return MachineType::Simd256();
269 270
      case MachineRepresentation::kTagged:
        return MachineType::AnyTagged();
271 272 273 274
      case MachineRepresentation::kTaggedSigned:
        return MachineType::TaggedSigned();
      case MachineRepresentation::kTaggedPointer:
        return MachineType::TaggedPointer();
275 276 277 278
      case MachineRepresentation::kCompressed:
        return MachineType::AnyCompressed();
      case MachineRepresentation::kCompressedPointer:
        return MachineType::CompressedPointer();
Samuel Groß's avatar
Samuel Groß committed
279 280
      case MachineRepresentation::kSandboxedPointer:
        return MachineType::SandboxedPointer();
281 282 283 284 285
      default:
        UNREACHABLE();
    }
  }

286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
  static MachineType TypeForCType(const CTypeInfo& type) {
    switch (type.GetType()) {
      case CTypeInfo::Type::kVoid:
        return MachineType::AnyTagged();
      case CTypeInfo::Type::kBool:
        return MachineType::Bool();
      case CTypeInfo::Type::kInt32:
        return MachineType::Int32();
      case CTypeInfo::Type::kUint32:
        return MachineType::Uint32();
      case CTypeInfo::Type::kInt64:
        return MachineType::Int64();
      case CTypeInfo::Type::kAny:
        static_assert(
            sizeof(AnyCType) == kInt64Size,
            "CTypeInfo::Type::kAny is assumed to be of size 64 bits.");
        return MachineType::Int64();
      case CTypeInfo::Type::kUint64:
        return MachineType::Uint64();
      case CTypeInfo::Type::kFloat32:
        return MachineType::Float32();
      case CTypeInfo::Type::kFloat64:
        return MachineType::Float64();
      case CTypeInfo::Type::kV8Value:
      case CTypeInfo::Type::kApiObject:
        return MachineType::AnyTagged();
    }
  }

315
  constexpr bool LessThanOrEqualPointerSize() const {
316
    return ElementSizeLog2Of(this->representation()) <= kSystemPointerSizeLog2;
317 318
  }

319 320 321 322
  constexpr byte MemSize() const {
    return 1 << i::ElementSizeLog2Of(this->representation());
  }

323 324 325 326 327 328 329
 private:
  MachineRepresentation representation_;
  MachineSemantic semantic_;
};

V8_INLINE size_t hash_value(MachineRepresentation rep) {
  return static_cast<size_t>(rep);
330 331
}

332 333 334 335 336
V8_INLINE size_t hash_value(MachineType type) {
  return static_cast<size_t>(type.representation()) +
         static_cast<size_t>(type.semantic()) * 16;
}

337 338
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
                                           MachineRepresentation rep);
339
std::ostream& operator<<(std::ostream& os, MachineSemantic type);
340
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, MachineType type);
341

342 343 344 345 346
inline bool IsIntegral(MachineRepresentation rep) {
  return rep >= MachineRepresentation::kWord8 &&
         rep <= MachineRepresentation::kWord64;
}

347
inline bool IsFloatingPoint(MachineRepresentation rep) {
348
  return rep >= MachineRepresentation::kFirstFPRepresentation;
349 350
}

351 352 353 354
inline bool IsSimd128(MachineRepresentation rep) {
  return rep == MachineRepresentation::kSimd128;
}

355 356
inline bool CanBeTaggedPointer(MachineRepresentation rep) {
  return rep == MachineRepresentation::kTagged ||
357 358
         rep == MachineRepresentation::kTaggedPointer ||
         rep == MachineRepresentation::kMapWord;
359 360
}

361 362 363 364 365
inline bool CanBeTaggedSigned(MachineRepresentation rep) {
  return rep == MachineRepresentation::kTagged ||
         rep == MachineRepresentation::kTaggedSigned;
}

366 367 368 369
inline bool IsAnyTagged(MachineRepresentation rep) {
  return CanBeTaggedPointer(rep) || rep == MachineRepresentation::kTaggedSigned;
}

370 371 372 373 374
inline bool CanBeCompressedPointer(MachineRepresentation rep) {
  return rep == MachineRepresentation::kCompressed ||
         rep == MachineRepresentation::kCompressedPointer;
}

375 376 377 378
inline bool CanBeTaggedOrCompressedPointer(MachineRepresentation rep) {
  return CanBeTaggedPointer(rep) || CanBeCompressedPointer(rep);
}

379
inline bool IsAnyCompressed(MachineRepresentation rep) {
380
  return CanBeCompressedPointer(rep);
381 382
}

383
// Gets the log2 of the element size in bytes of the machine type.
384 385
V8_EXPORT_PRIVATE inline constexpr int ElementSizeLog2Of(
    MachineRepresentation rep) {
386 387 388
  switch (rep) {
    case MachineRepresentation::kBit:
    case MachineRepresentation::kWord8:
389
      return 0;
390
    case MachineRepresentation::kWord16:
391
      return 1;
392 393
    case MachineRepresentation::kWord32:
    case MachineRepresentation::kFloat32:
394
      return 2;
395 396
    case MachineRepresentation::kWord64:
    case MachineRepresentation::kFloat64:
397
      return 3;
398 399
    case MachineRepresentation::kSimd128:
      return 4;
400 401
    case MachineRepresentation::kSimd256:
      return 5;
402 403
    case MachineRepresentation::kTaggedSigned:
    case MachineRepresentation::kTaggedPointer:
404
    case MachineRepresentation::kTagged:
405
    case MachineRepresentation::kMapWord:
406 407
    case MachineRepresentation::kCompressedPointer:
    case MachineRepresentation::kCompressed:
408
      return kTaggedSizeLog2;
Samuel Groß's avatar
Samuel Groß committed
409
    case MachineRepresentation::kSandboxedPointer:
Samuel Groß's avatar
Samuel Groß committed
410
      return kSystemPointerSizeLog2;
411
    default:
412
      UNREACHABLE();
413
  }
414 415
}

416 417 418 419
constexpr int kMaximumReprSizeLog2 =
    ElementSizeLog2Of(MachineRepresentation::kSimd128);
constexpr int kMaximumReprSizeInBytes = 1 << kTaggedSizeLog2;

420
static_assert(kMaximumReprSizeLog2 >=
421
              ElementSizeLog2Of(MachineRepresentation::kTagged));
422
static_assert(kMaximumReprSizeLog2 >=
423 424
              ElementSizeLog2Of(MachineRepresentation::kWord64));

425 426
V8_EXPORT_PRIVATE inline constexpr int ElementSizeInBytes(
    MachineRepresentation rep) {
427 428 429
  return 1 << ElementSizeLog2Of(rep);
}

430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
inline constexpr int ElementSizeInBits(MachineRepresentation rep) {
  return 8 * ElementSizeInBytes(rep);
}

inline constexpr uint64_t MaxUnsignedValue(MachineRepresentation rep) {
  switch (rep) {
    case MachineRepresentation::kWord8:
      return std::numeric_limits<uint8_t>::max();
    case MachineRepresentation::kWord16:
      return std::numeric_limits<uint16_t>::max();
    case MachineRepresentation::kWord32:
      return std::numeric_limits<uint32_t>::max();
    case MachineRepresentation::kWord64:
      return std::numeric_limits<uint64_t>::max();
    default:
      UNREACHABLE();
  }
}

449 450 451 452 453 454
V8_EXPORT_PRIVATE inline constexpr int ElementSizeInPointers(
    MachineRepresentation rep) {
  return (ElementSizeInBytes(rep) + kSystemPointerSize - 1) /
         kSystemPointerSize;
}

455 456 457 458 459 460
// Converts representation to bit for representation masks.
V8_EXPORT_PRIVATE inline constexpr int RepresentationBit(
    MachineRepresentation rep) {
  return 1 << static_cast<int>(rep);
}

461 462
}  // namespace internal
}  // namespace v8
463

464
#endif  // V8_CODEGEN_MACHINE_TYPE_H_