1 // Copyright 2018 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_EMBEDDER_DATA_SLOT_H_ 6 #define V8_OBJECTS_EMBEDDER_DATA_SLOT_H_ 7 8 #include <utility> 9 10 #include "src/common/assert-scope.h" 11 #include "src/common/globals.h" 12 #include "src/objects/slots.h" 13 14 // Has to be the last include (doesn't have include guards): 15 #include "src/objects/object-macros.h" 16 17 namespace v8 { 18 namespace internal { 19 20 class EmbedderDataArray; 21 class JSObject; 22 class Object; 23 24 // An EmbedderDataSlot instance describes a kEmbedderDataSlotSize field ("slot") 25 // holding an embedder data which may contain raw aligned pointer or a tagged 26 // pointer (smi or heap object). 27 // Its address() is the address of the slot. 28 // The slot's contents can be read and written using respective load_XX() and 29 // store_XX() methods. 30 // Storing heap object through this slot may require triggering write barriers 31 // so this operation must be done via static store_tagged() methods. 32 class EmbedderDataSlot 33 : public SlotBase<EmbedderDataSlot, Address, kTaggedSize> { 34 public: 35 #if defined(V8_SANDBOXED_EXTERNAL_POINTERS) 36 // When the sandbox is enabled, an EmbedderDataSlot always contains a valid 37 // external pointer table index (initially, zero) in it's "raw" part and a 38 // valid tagged value in its 32-bit "tagged" part. 39 // 40 // Layout (sandbox): 41 // +-----------------------------------+-----------------------------------+ 42 // | Tagged (Smi/CompressedPointer) | External Pointer Table Index | 43 // +-----------------------------------+-----------------------------------+ 44 // ^ ^ 45 // kTaggedPayloadOffset kRawPayloadOffset 46 // kExternalPointerOffset 47 static constexpr int kTaggedPayloadOffset = 0; 48 static constexpr int kRawPayloadOffset = kTaggedSize; 49 static constexpr int kExternalPointerOffset = kRawPayloadOffset; 50 #elif defined(V8_COMPRESS_POINTERS) && defined(V8_TARGET_BIG_ENDIAN) 51 // The raw payload is located in the other "tagged" part of the full pointer 52 // and cotains the upper part of an aligned address. The raw part is not 53 // expected to look like a tagged value. 54 // 55 // Layout (big endian pointer compression): 56 // +-----------------------------------+-----------------------------------+ 57 // | External Pointer (high word) | Tagged (Smi/CompressedPointer) | 58 // | | OR External Pointer (low word) | 59 // +-----------------------------------+-----------------------------------+ 60 // ^ ^ 61 // kRawPayloadOffset kTaggedayloadOffset 62 // kExternalPointerOffset 63 static constexpr int kExternalPointerOffset = 0; 64 static constexpr int kRawPayloadOffset = 0; 65 static constexpr int kTaggedPayloadOffset = kTaggedSize; 66 #elif defined(V8_COMPRESS_POINTERS) && defined(V8_TARGET_LITTLE_ENDIAN) 67 // Layout (little endian pointer compression): 68 // +-----------------------------------+-----------------------------------+ 69 // | Tagged (Smi/CompressedPointer) | External Pointer (high word) | 70 // | OR External Pointer (low word) | | 71 // +-----------------------------------+-----------------------------------+ 72 // ^ ^ 73 // kTaggedPayloadOffset kRawPayloadOffset 74 // kExternalPointerOffset 75 static constexpr int kExternalPointerOffset = 0; 76 static constexpr int kTaggedPayloadOffset = 0; 77 static constexpr int kRawPayloadOffset = kTaggedSize; 78 #else 79 // Layout (no pointer compression): 80 // +-----------------------------------------------------------------------+ 81 // | Tagged (Smi/Pointer) OR External Pointer | 82 // +-----------------------------------------------------------------------+ 83 // ^ 84 // kTaggedPayloadOffset 85 // kExternalPointerOffset 86 static constexpr int kTaggedPayloadOffset = 0; 87 static constexpr int kExternalPointerOffset = 0; 88 #endif // V8_SANDBOXED_EXTERNAL_POINTERS 89 90 static constexpr int kRequiredPtrAlignment = kSmiTagSize; 91 92 using EmbedderDataSlotSnapshot = Address; 93 V8_INLINE static void PopulateEmbedderDataSnapshot(Map map, 94 JSObject js_object, 95 int entry_index, 96 EmbedderDataSlotSnapshot&); 97 EmbedderDataSlot()98 EmbedderDataSlot() : SlotBase(kNullAddress) {} 99 V8_INLINE EmbedderDataSlot(EmbedderDataArray array, int entry_index); 100 V8_INLINE EmbedderDataSlot(JSObject object, int embedder_field_index); 101 V8_INLINE explicit EmbedderDataSlot(const EmbedderDataSlotSnapshot& snapshot); 102 103 // Opaque type used for storing raw embedder data. 104 using RawData = Address; 105 106 V8_INLINE void Initialize(Object initial_value); 107 108 V8_INLINE Object load_tagged() const; 109 V8_INLINE void store_smi(Smi value); 110 111 // Setting an arbitrary tagged value requires triggering a write barrier 112 // which requires separate object and offset values, therefore these static 113 // functions also has the target object parameter. 114 static V8_INLINE void store_tagged(EmbedderDataArray array, int entry_index, 115 Object value); 116 static V8_INLINE void store_tagged(JSObject object, int embedder_field_index, 117 Object value); 118 119 // Tries reinterpret the value as an aligned pointer and sets *out_result to 120 // the pointer-like value. Note, that some Smis could still look like an 121 // aligned pointers. 122 // Returns true on success. 123 // When sandboxed external pointers are enabled, calling this method when the 124 // raw part of the slot does not contain valid external pointer table index 125 // is undefined behaviour and most likely result in crashes. 126 V8_INLINE bool ToAlignedPointer(Isolate* isolate, void** out_result) const; 127 128 // Returns true if the pointer was successfully stored or false it the pointer 129 // was improperly aligned. 130 V8_INLINE V8_WARN_UNUSED_RESULT bool store_aligned_pointer(Isolate* isolate, 131 void* ptr); 132 133 V8_INLINE RawData load_raw(Isolate* isolate, 134 const DisallowGarbageCollection& no_gc) const; 135 V8_INLINE void store_raw(Isolate* isolate, RawData data, 136 const DisallowGarbageCollection& no_gc); 137 138 private: 139 // Stores given value to the embedder data slot in a concurrent-marker 140 // friendly manner (tagged part of the slot is written atomically). 141 V8_INLINE void gc_safe_store(Isolate* isolate, Address value); 142 }; 143 144 } // namespace internal 145 } // namespace v8 146 147 #include "src/objects/object-macros-undef.h" 148 149 #endif // V8_OBJECTS_EMBEDDER_DATA_SLOT_H_ 150