Line data Source code
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_INL_H_
6 : #define V8_OBJECTS_EMBEDDER_DATA_SLOT_INL_H_
7 :
8 : #include "src/objects/embedder-data-slot.h"
9 :
10 : #include "src/heap/heap-write-barrier-inl.h"
11 : #include "src/objects-inl.h"
12 : #include "src/objects/embedder-data-array.h"
13 : #include "src/objects/js-objects-inl.h"
14 : #include "src/v8memory.h"
15 :
16 : // Has to be the last include (doesn't have include guards):
17 : #include "src/objects/object-macros.h"
18 :
19 : namespace v8 {
20 : namespace internal {
21 :
22 : EmbedderDataSlot::EmbedderDataSlot(EmbedderDataArray array, int entry_index)
23 114340 : : SlotBase(FIELD_ADDR(array,
24 114340 : EmbedderDataArray::OffsetOfElementAt(entry_index))) {}
25 :
26 : EmbedderDataSlot::EmbedderDataSlot(JSObject object, int embedder_field_index)
27 1108080 : : SlotBase(FIELD_ADDR(
28 1108087 : object, object->GetEmbedderFieldOffset(embedder_field_index))) {}
29 :
30 : Object EmbedderDataSlot::load_tagged() const {
31 1105901 : return ObjectSlot(address() + kTaggedPayloadOffset).Relaxed_Load();
32 : }
33 :
34 : void EmbedderDataSlot::store_smi(Smi value) {
35 : ObjectSlot(address() + kTaggedPayloadOffset).Relaxed_Store(value);
36 : #ifdef V8_COMPRESS_POINTERS
37 : // See gc_safe_store() for the reasons behind two stores.
38 : ObjectSlot(address() + kRawPayloadOffset).Relaxed_Store(Smi::kZero);
39 : #endif
40 : }
41 :
42 : // static
43 : void EmbedderDataSlot::store_tagged(EmbedderDataArray array, int entry_index,
44 : Object value) {
45 : int slot_offset = EmbedderDataArray::OffsetOfElementAt(entry_index);
46 60 : ObjectSlot(FIELD_ADDR(array, slot_offset + kTaggedPayloadOffset))
47 120 : .Relaxed_Store(value);
48 60 : WRITE_BARRIER(array, slot_offset + kTaggedPayloadOffset, value);
49 : #ifdef V8_COMPRESS_POINTERS
50 : // See gc_safe_store() for the reasons behind two stores.
51 : ObjectSlot(FIELD_ADDR(array, slot_offset + kRawPayloadOffset))
52 : .Relaxed_Store(Smi::kZero);
53 : #endif
54 : }
55 :
56 : // static
57 : void EmbedderDataSlot::store_tagged(JSObject object, int embedder_field_index,
58 : Object value) {
59 1039246 : int slot_offset = object->GetEmbedderFieldOffset(embedder_field_index);
60 1039273 : ObjectSlot(FIELD_ADDR(object, slot_offset + kTaggedPayloadOffset))
61 1039273 : .Relaxed_Store(value);
62 1039269 : WRITE_BARRIER(object, slot_offset + kTaggedPayloadOffset, value);
63 : #ifdef V8_COMPRESS_POINTERS
64 : // See gc_safe_store() for the reasons behind two stores.
65 : ObjectSlot(FIELD_ADDR(object, slot_offset + kRawPayloadOffset))
66 : .Relaxed_Store(Smi::kZero);
67 : #endif
68 : }
69 :
70 : bool EmbedderDataSlot::ToAlignedPointer(void** out_pointer) const {
71 : // We don't care about atomicity of access here because embedder slots
72 : // are accessed this way only from the main thread via API during "mutator"
73 : // phase which is propely synched with GC (concurrent marker may still look
74 : // at the tagged part of the embedder slot but read-only access is ok).
75 : #ifdef V8_COMPRESS_POINTERS
76 : // TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size
77 : // fields (external pointers, doubles and BigInt data) are only kTaggedSize
78 : // aligned so we have to use unaligned pointer friendly way of accessing them
79 : // in order to avoid undefined behavior in C++ code.
80 : Address raw_value = ReadUnalignedValue<Address>(address());
81 : #else
82 234 : Address raw_value = *location();
83 : #endif
84 234 : *out_pointer = reinterpret_cast<void*>(raw_value);
85 234 : return HAS_SMI_TAG(raw_value);
86 : }
87 :
88 : bool EmbedderDataSlot::store_aligned_pointer(void* ptr) {
89 115882 : Address value = reinterpret_cast<Address>(ptr);
90 115882 : if (!HAS_SMI_TAG(value)) return false;
91 : gc_safe_store(value);
92 : return true;
93 : }
94 :
95 : EmbedderDataSlot::RawData EmbedderDataSlot::load_raw(
96 : const DisallowHeapAllocation& no_gc) const {
97 : // We don't care about atomicity of access here because embedder slots
98 : // are accessed this way only by serializer from the main thread when
99 : // GC is not active (concurrent marker may still look at the tagged part
100 : // of the embedder slot but read-only access is ok).
101 : #ifdef V8_COMPRESS_POINTERS
102 : // TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size
103 : // fields (external pointers, doubles and BigInt data) are only kTaggedSize
104 : // aligned so we have to use unaligned pointer friendly way of accessing them
105 : // in order to avoid undefined behavior in C++ code.
106 : return ReadUnalignedValue<Address>(address());
107 : #else
108 380 : return *location();
109 : #endif
110 : }
111 :
112 : void EmbedderDataSlot::store_raw(EmbedderDataSlot::RawData data,
113 : const DisallowHeapAllocation& no_gc) {
114 : gc_safe_store(data);
115 : }
116 :
117 : void EmbedderDataSlot::gc_safe_store(Address value) {
118 : #ifdef V8_COMPRESS_POINTERS
119 : STATIC_ASSERT(kSmiShiftSize == 0);
120 : STATIC_ASSERT(SmiValuesAre31Bits());
121 : STATIC_ASSERT(kTaggedSize == kInt32Size);
122 : // We have to do two 32-bit stores here because
123 : // 1) tagged part modifications must be atomic to be properly synchronized
124 : // with the concurrent marker.
125 : // 2) atomicity of full pointer store is not guaranteed for embedder slots
126 : // since the address of the slot may not be kSystemPointerSize aligned
127 : // (only kTaggedSize alignment is guaranteed).
128 : // TODO(ishell, v8:8875): revisit this once the allocation alignment
129 : // inconsistency is fixed.
130 : Address lo = static_cast<intptr_t>(static_cast<int32_t>(value));
131 : ObjectSlot(address() + kTaggedPayloadOffset).Relaxed_Store(Smi(lo));
132 : Address hi = value >> 32;
133 : ObjectSlot(address() + kRawPayloadOffset).Relaxed_Store(Object(hi));
134 : #else
135 114364 : ObjectSlot(address() + kTaggedPayloadOffset).Relaxed_Store(Smi(value));
136 : #endif
137 : }
138 :
139 : } // namespace internal
140 : } // namespace v8
141 :
142 : #include "src/objects/object-macros-undef.h"
143 :
144 : #endif // V8_OBJECTS_EMBEDDER_DATA_SLOT_INL_H_
|