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