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