• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 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_OBJECTS_TAGGED_INDEX_H_
6 #define V8_OBJECTS_TAGGED_INDEX_H_
7 
8 #include "src/common/globals.h"
9 #include "src/objects/heap-object.h"
10 
11 // Has to be the last include (doesn't have include guards):
12 #include "src/objects/object-macros.h"
13 
14 namespace v8 {
15 namespace internal {
16 
17 // TaggedIndex represents integer values that can be stored in 31 bits.
18 // The on 32-bit architectures ptr_ value has the following format:
19 //   [31 bit signed int] 0
20 // The on 64-bit architectures ptr_ value has the following format:
21 //   [32 bits of sign-extended lower part][31 bit signed int] 0
22 // Thus, on 32-bit architectures TaggedIndex is exactly the same as Smi but
23 // on 64-bit architectures TaggedIndex differs from Smi in the following
24 // aspects:
25 // 1) TaggedIndex payload is always 31 bit independent of the Smi payload size
26 // 2) TaggedIndex is always properly sign-extended independent of whether
27 //    pointer compression is enabled or not. In the former case, upper 32 bits
28 //    of a Smi value may contain 0 or sign or isolate root value.
29 //
30 // Given the above constraints TaggedIndex has the following properties:
31 // 1) it still looks like a Smi from GC point of view and therefore it's safe
32 //   to pass TaggedIndex values to runtime functions or builtins on the stack
33 // 2) since the TaggedIndex values are already properly sign-extended it's
34 //   safe to use them as indices in offset-computation functions.
35 class TaggedIndex : public Object {
36  public:
37   // This replaces the OBJECT_CONSTRUCTORS macro, because TaggedIndex are
38   // special in that we want them to be constexprs.
TaggedIndex()39   constexpr TaggedIndex() : Object() {}
TaggedIndex(Address ptr)40   explicit constexpr TaggedIndex(Address ptr) : Object(ptr) {
41     DCHECK(HAS_SMI_TAG(ptr));
42   }
43 
44   // Returns the integer value.
value()45   inline intptr_t value() const {
46     // Truncate and shift down (requires >> to be sign extending).
47     return static_cast<intptr_t>(ptr()) >> kSmiTagSize;
48   }
49 
50   // Convert a value to a TaggedIndex object.
FromIntptr(intptr_t value)51   static inline TaggedIndex FromIntptr(intptr_t value) {
52     DCHECK(TaggedIndex::IsValid(value));
53     return TaggedIndex((static_cast<Address>(value) << kSmiTagSize) | kSmiTag);
54   }
55 
56   // Returns whether value can be represented in a TaggedIndex.
IsValid(intptr_t value)57   static inline bool constexpr IsValid(intptr_t value) {
58     return kMinValue <= value && value <= kMaxValue;
59   }
60 
61   DECL_CAST(TaggedIndex)
62 
63   // Dispatched behavior.
64   DECL_VERIFIER(TaggedIndex)
65 
66   STATIC_ASSERT(kSmiTagSize == 1);
67   static constexpr int kTaggedValueSize = 31;
68   static constexpr intptr_t kMinValue =
69       static_cast<intptr_t>(kUintptrAllBitsSet << (kTaggedValueSize - 1));
70   static constexpr intptr_t kMaxValue = -(kMinValue + 1);
71 };
72 
73 CAST_ACCESSOR(TaggedIndex)
74 
75 }  // namespace internal
76 }  // namespace v8
77 
78 #include "src/objects/object-macros-undef.h"
79 
80 #endif  // V8_OBJECTS_TAGGED_INDEX_H_
81