libv8-node 15.5.1.0.beta1-x86_64-darwin-19 → 16.10.0.0-x86_64-darwin-19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/ext/libv8-node/.location.yml +0 -1
  3. data/ext/libv8-node/location.rb +23 -38
  4. data/ext/libv8-node/paths.rb +2 -2
  5. data/lib/libv8/node/version.rb +3 -3
  6. data/vendor/v8/include/cppgc/allocation.h +104 -45
  7. data/vendor/v8/include/cppgc/common.h +9 -6
  8. data/vendor/v8/include/cppgc/cross-thread-persistent.h +384 -0
  9. data/vendor/v8/include/cppgc/custom-space.h +37 -2
  10. data/vendor/v8/include/cppgc/default-platform.h +47 -48
  11. data/vendor/v8/include/cppgc/ephemeron-pair.h +30 -0
  12. data/vendor/v8/include/cppgc/explicit-management.h +82 -0
  13. data/vendor/v8/include/cppgc/garbage-collected.h +4 -3
  14. data/vendor/v8/include/cppgc/heap-consistency.h +236 -0
  15. data/vendor/v8/include/cppgc/heap-state.h +70 -0
  16. data/vendor/v8/include/cppgc/heap-statistics.h +120 -0
  17. data/vendor/v8/include/cppgc/heap.h +68 -6
  18. data/vendor/v8/include/cppgc/internal/api-constants.h +3 -3
  19. data/vendor/v8/include/cppgc/internal/caged-heap-local-data.h +2 -1
  20. data/vendor/v8/include/cppgc/internal/compiler-specific.h +2 -2
  21. data/vendor/v8/include/cppgc/internal/gc-info.h +44 -13
  22. data/vendor/v8/include/cppgc/internal/name-trait.h +111 -0
  23. data/vendor/v8/include/cppgc/internal/persistent-node.h +57 -1
  24. data/vendor/v8/include/cppgc/internal/pointer-policies.h +69 -28
  25. data/vendor/v8/include/cppgc/internal/prefinalizer-handler.h +1 -1
  26. data/vendor/v8/include/cppgc/internal/write-barrier.h +353 -35
  27. data/vendor/v8/include/cppgc/liveness-broker.h +7 -1
  28. data/vendor/v8/include/cppgc/macros.h +2 -0
  29. data/vendor/v8/include/cppgc/member.h +85 -25
  30. data/vendor/v8/include/cppgc/name-provider.h +65 -0
  31. data/vendor/v8/include/cppgc/object-size-trait.h +58 -0
  32. data/vendor/v8/include/cppgc/persistent.h +33 -9
  33. data/vendor/v8/include/cppgc/platform.h +48 -25
  34. data/vendor/v8/include/cppgc/prefinalizer.h +1 -1
  35. data/vendor/v8/include/cppgc/process-heap-statistics.h +36 -0
  36. data/vendor/v8/include/cppgc/sentinel-pointer.h +32 -0
  37. data/vendor/v8/include/cppgc/source-location.h +2 -1
  38. data/vendor/v8/include/cppgc/testing.h +99 -0
  39. data/vendor/v8/include/cppgc/trace-trait.h +8 -3
  40. data/vendor/v8/include/cppgc/type-traits.h +157 -19
  41. data/vendor/v8/include/cppgc/visitor.h +187 -23
  42. data/vendor/v8/include/libplatform/libplatform.h +11 -0
  43. data/vendor/v8/include/libplatform/v8-tracing.h +2 -0
  44. data/vendor/v8/include/v8-cppgc.h +258 -159
  45. data/vendor/v8/include/v8-fast-api-calls.h +562 -159
  46. data/vendor/v8/include/v8-inspector.h +23 -2
  47. data/vendor/v8/include/v8-internal.h +99 -27
  48. data/vendor/v8/include/v8-metrics.h +77 -8
  49. data/vendor/v8/include/v8-platform.h +47 -22
  50. data/vendor/v8/include/v8-profiler.h +75 -11
  51. data/vendor/v8/include/v8-unwinder-state.h +30 -0
  52. data/vendor/v8/include/v8-util.h +1 -1
  53. data/vendor/v8/include/v8-version.h +4 -4
  54. data/vendor/v8/include/v8.h +1192 -642
  55. data/vendor/v8/include/v8config.h +40 -9
  56. data/vendor/v8/{out.gn → x86_64-darwin-19}/libv8/obj/libv8_monolith.a +0 -0
  57. metadata +34 -8
  58. data/vendor/v8/include/cppgc/internal/process-heap.h +0 -34
@@ -5,8 +5,14 @@
5
5
  #ifndef INCLUDE_CPPGC_INTERNAL_WRITE_BARRIER_H_
6
6
  #define INCLUDE_CPPGC_INTERNAL_WRITE_BARRIER_H_
7
7
 
8
+ #include <cstddef>
9
+ #include <cstdint>
10
+
11
+ #include "cppgc/heap-state.h"
8
12
  #include "cppgc/internal/api-constants.h"
9
- #include "cppgc/internal/process-heap.h"
13
+ #include "cppgc/internal/atomic-entry-flag.h"
14
+ #include "cppgc/sentinel-pointer.h"
15
+ #include "cppgc/trace-trait.h"
10
16
  #include "v8config.h" // NOLINT(build/include_directory)
11
17
 
12
18
  #if defined(CPPGC_CAGED_HEAP)
@@ -14,64 +20,376 @@
14
20
  #endif
15
21
 
16
22
  namespace cppgc {
23
+
24
+ class HeapHandle;
25
+
17
26
  namespace internal {
18
27
 
28
+ #if defined(CPPGC_CAGED_HEAP)
29
+ class WriteBarrierTypeForCagedHeapPolicy;
30
+ #else // !CPPGC_CAGED_HEAP
31
+ class WriteBarrierTypeForNonCagedHeapPolicy;
32
+ #endif // !CPPGC_CAGED_HEAP
33
+
19
34
  class V8_EXPORT WriteBarrier final {
20
35
  public:
21
- static V8_INLINE void MarkingBarrier(const void* slot, const void* value) {
36
+ enum class Type : uint8_t {
37
+ kNone,
38
+ kMarking,
39
+ kGenerational,
40
+ };
41
+
42
+ struct Params {
43
+ HeapHandle* heap = nullptr;
44
+ #if V8_ENABLE_CHECKS
45
+ Type type = Type::kNone;
46
+ #endif // !V8_ENABLE_CHECKS
47
+ #if defined(CPPGC_CAGED_HEAP)
48
+ uintptr_t start = 0;
49
+ CagedHeapLocalData& caged_heap() const {
50
+ return *reinterpret_cast<CagedHeapLocalData*>(start);
51
+ }
52
+ uintptr_t slot_offset = 0;
53
+ uintptr_t value_offset = 0;
54
+ #endif // CPPGC_CAGED_HEAP
55
+ };
56
+
57
+ enum class ValueMode {
58
+ kValuePresent,
59
+ kNoValuePresent,
60
+ };
61
+
62
+ // Returns the required write barrier for a given `slot` and `value`.
63
+ static V8_INLINE Type GetWriteBarrierType(const void* slot, const void* value,
64
+ Params& params);
65
+ // Returns the required write barrier for a given `slot`.
66
+ template <typename HeapHandleCallback>
67
+ static V8_INLINE Type GetWriteBarrierType(const void* slot, Params& params,
68
+ HeapHandleCallback callback);
69
+
70
+ template <typename HeapHandleCallback>
71
+ static V8_INLINE Type GetWriteBarrierTypeForExternallyReferencedObject(
72
+ const void* value, Params& params, HeapHandleCallback callback);
73
+
74
+ static V8_INLINE void DijkstraMarkingBarrier(const Params& params,
75
+ const void* object);
76
+ static V8_INLINE void DijkstraMarkingBarrierRange(
77
+ const Params& params, const void* first_element, size_t element_size,
78
+ size_t number_of_elements, TraceCallback trace_callback);
79
+ static V8_INLINE void SteeleMarkingBarrier(const Params& params,
80
+ const void* object);
81
+ #if defined(CPPGC_YOUNG_GENERATION)
82
+ static V8_INLINE void GenerationalBarrier(const Params& params,
83
+ const void* slot);
84
+ #else // !CPPGC_YOUNG_GENERATION
85
+ static V8_INLINE void GenerationalBarrier(const Params& params,
86
+ const void* slot) {}
87
+ #endif // CPPGC_YOUNG_GENERATION
88
+
89
+ #if V8_ENABLE_CHECKS
90
+ static void CheckParams(Type expected_type, const Params& params);
91
+ #else // !V8_ENABLE_CHECKS
92
+ static void CheckParams(Type expected_type, const Params& params) {}
93
+ #endif // !V8_ENABLE_CHECKS
94
+
95
+ // The IncrementalOrConcurrentUpdater class allows cppgc internal to update
96
+ // |incremental_or_concurrent_marking_flag_|.
97
+ class IncrementalOrConcurrentMarkingFlagUpdater;
98
+ static bool IsAnyIncrementalOrConcurrentMarking() {
99
+ return incremental_or_concurrent_marking_flag_.MightBeEntered();
100
+ }
101
+
102
+ private:
103
+ WriteBarrier() = delete;
104
+
22
105
  #if defined(CPPGC_CAGED_HEAP)
23
- const uintptr_t start =
24
- reinterpret_cast<uintptr_t>(value) &
25
- ~(api_constants::kCagedHeapReservationAlignment - 1);
26
- const uintptr_t slot_offset = reinterpret_cast<uintptr_t>(slot) - start;
106
+ using WriteBarrierTypePolicy = WriteBarrierTypeForCagedHeapPolicy;
107
+ #else // !CPPGC_CAGED_HEAP
108
+ using WriteBarrierTypePolicy = WriteBarrierTypeForNonCagedHeapPolicy;
109
+ #endif // !CPPGC_CAGED_HEAP
110
+
111
+ static void DijkstraMarkingBarrierSlow(const void* value);
112
+ static void DijkstraMarkingBarrierSlowWithSentinelCheck(const void* value);
113
+ static void DijkstraMarkingBarrierRangeSlow(HeapHandle& heap_handle,
114
+ const void* first_element,
115
+ size_t element_size,
116
+ size_t number_of_elements,
117
+ TraceCallback trace_callback);
118
+ static void SteeleMarkingBarrierSlow(const void* value);
119
+ static void SteeleMarkingBarrierSlowWithSentinelCheck(const void* value);
120
+
121
+ #if defined(CPPGC_YOUNG_GENERATION)
122
+ static CagedHeapLocalData& GetLocalData(HeapHandle&);
123
+ static void GenerationalBarrierSlow(const CagedHeapLocalData& local_data,
124
+ const AgeTable& ageTable,
125
+ const void* slot, uintptr_t value_offset);
126
+ #endif // CPPGC_YOUNG_GENERATION
127
+
128
+ static AtomicEntryFlag incremental_or_concurrent_marking_flag_;
129
+ };
130
+
131
+ template <WriteBarrier::Type type>
132
+ V8_INLINE WriteBarrier::Type SetAndReturnType(WriteBarrier::Params& params) {
133
+ if (type == WriteBarrier::Type::kNone) return WriteBarrier::Type::kNone;
134
+ #if V8_ENABLE_CHECKS
135
+ params.type = type;
136
+ #endif // !V8_ENABLE_CHECKS
137
+ return type;
138
+ }
139
+
140
+ #if defined(CPPGC_CAGED_HEAP)
141
+ class V8_EXPORT WriteBarrierTypeForCagedHeapPolicy final {
142
+ public:
143
+ template <WriteBarrier::ValueMode value_mode, typename HeapHandleCallback>
144
+ static V8_INLINE WriteBarrier::Type Get(const void* slot, const void* value,
145
+ WriteBarrier::Params& params,
146
+ HeapHandleCallback callback) {
147
+ return ValueModeDispatch<value_mode>::Get(slot, value, params, callback);
148
+ }
149
+
150
+ template <typename HeapHandleCallback>
151
+ static V8_INLINE WriteBarrier::Type GetForExternallyReferenced(
152
+ const void* value, WriteBarrier::Params& params, HeapHandleCallback) {
153
+ if (!TryGetCagedHeap(value, value, params)) {
154
+ return WriteBarrier::Type::kNone;
155
+ }
156
+ if (V8_UNLIKELY(params.caged_heap().is_incremental_marking_in_progress)) {
157
+ return SetAndReturnType<WriteBarrier::Type::kMarking>(params);
158
+ }
159
+ return SetAndReturnType<WriteBarrier::Type::kNone>(params);
160
+ }
161
+
162
+ private:
163
+ WriteBarrierTypeForCagedHeapPolicy() = delete;
164
+
165
+ template <WriteBarrier::ValueMode value_mode>
166
+ struct ValueModeDispatch;
167
+
168
+ static V8_INLINE bool TryGetCagedHeap(const void* slot, const void* value,
169
+ WriteBarrier::Params& params) {
170
+ params.start = reinterpret_cast<uintptr_t>(value) &
171
+ ~(api_constants::kCagedHeapReservationAlignment - 1);
172
+ const uintptr_t slot_offset =
173
+ reinterpret_cast<uintptr_t>(slot) - params.start;
27
174
  if (slot_offset > api_constants::kCagedHeapReservationSize) {
28
175
  // Check if slot is on stack or value is sentinel or nullptr. This relies
29
176
  // on the fact that kSentinelPointer is encoded as 0x1.
30
- return;
177
+ return false;
31
178
  }
179
+ return true;
180
+ }
32
181
 
33
- CagedHeapLocalData* local_data =
34
- reinterpret_cast<CagedHeapLocalData*>(start);
35
- if (V8_UNLIKELY(local_data->is_marking_in_progress)) {
36
- MarkingBarrierSlow(value);
37
- return;
182
+ // Returns whether marking is in progress. If marking is not in progress
183
+ // sets the start of the cage accordingly.
184
+ //
185
+ // TODO(chromium:1056170): Create fast path on API.
186
+ static bool IsMarking(const HeapHandle&, WriteBarrier::Params&);
187
+ };
188
+
189
+ template <>
190
+ struct WriteBarrierTypeForCagedHeapPolicy::ValueModeDispatch<
191
+ WriteBarrier::ValueMode::kValuePresent> {
192
+ template <typename HeapHandleCallback>
193
+ static V8_INLINE WriteBarrier::Type Get(const void* slot, const void* value,
194
+ WriteBarrier::Params& params,
195
+ HeapHandleCallback) {
196
+ bool within_cage = TryGetCagedHeap(slot, value, params);
197
+ if (!within_cage) {
198
+ return WriteBarrier::Type::kNone;
38
199
  }
200
+ if (V8_LIKELY(!params.caged_heap().is_incremental_marking_in_progress)) {
39
201
  #if defined(CPPGC_YOUNG_GENERATION)
40
- GenerationalBarrier(local_data, slot, slot_offset,
41
- reinterpret_cast<uintptr_t>(value) - start);
42
- #endif
43
- #else
44
- if (V8_LIKELY(!ProcessHeap::IsAnyIncrementalOrConcurrentMarking())) return;
202
+ params.heap = reinterpret_cast<HeapHandle*>(params.start);
203
+ params.slot_offset = reinterpret_cast<uintptr_t>(slot) - params.start;
204
+ params.value_offset = reinterpret_cast<uintptr_t>(value) - params.start;
205
+ return SetAndReturnType<WriteBarrier::Type::kGenerational>(params);
206
+ #else // !CPPGC_YOUNG_GENERATION
207
+ return SetAndReturnType<WriteBarrier::Type::kNone>(params);
208
+ #endif // !CPPGC_YOUNG_GENERATION
209
+ }
210
+ params.heap = reinterpret_cast<HeapHandle*>(params.start);
211
+ return SetAndReturnType<WriteBarrier::Type::kMarking>(params);
212
+ }
213
+ };
214
+
215
+ template <>
216
+ struct WriteBarrierTypeForCagedHeapPolicy::ValueModeDispatch<
217
+ WriteBarrier::ValueMode::kNoValuePresent> {
218
+ template <typename HeapHandleCallback>
219
+ static V8_INLINE WriteBarrier::Type Get(const void* slot, const void*,
220
+ WriteBarrier::Params& params,
221
+ HeapHandleCallback callback) {
222
+ #if defined(CPPGC_YOUNG_GENERATION)
223
+ HeapHandle& handle = callback();
224
+ if (V8_LIKELY(!IsMarking(handle, params))) {
225
+ // params.start is populated by IsMarking().
226
+ params.heap = &handle;
227
+ params.slot_offset = reinterpret_cast<uintptr_t>(slot) - params.start;
228
+ // params.value_offset stays 0.
229
+ if (params.slot_offset > api_constants::kCagedHeapReservationSize) {
230
+ // Check if slot is on stack.
231
+ return SetAndReturnType<WriteBarrier::Type::kNone>(params);
232
+ }
233
+ return SetAndReturnType<WriteBarrier::Type::kGenerational>(params);
234
+ }
235
+ #else // !CPPGC_YOUNG_GENERATION
236
+ if (V8_LIKELY(!WriteBarrier::IsAnyIncrementalOrConcurrentMarking())) {
237
+ return SetAndReturnType<WriteBarrier::Type::kNone>(params);
238
+ }
239
+ HeapHandle& handle = callback();
240
+ if (V8_UNLIKELY(!subtle::HeapState::IsMarking(handle))) {
241
+ return SetAndReturnType<WriteBarrier::Type::kNone>(params);
242
+ }
243
+ #endif // !CPPGC_YOUNG_GENERATION
244
+ params.heap = &handle;
245
+ return SetAndReturnType<WriteBarrier::Type::kMarking>(params);
246
+ }
247
+ };
45
248
 
46
- MarkingBarrierSlowWithSentinelCheck(value);
47
249
  #endif // CPPGC_CAGED_HEAP
250
+
251
+ class V8_EXPORT WriteBarrierTypeForNonCagedHeapPolicy final {
252
+ public:
253
+ template <WriteBarrier::ValueMode value_mode, typename HeapHandleCallback>
254
+ static V8_INLINE WriteBarrier::Type Get(const void* slot, const void* value,
255
+ WriteBarrier::Params& params,
256
+ HeapHandleCallback callback) {
257
+ return ValueModeDispatch<value_mode>::Get(slot, value, params, callback);
48
258
  }
49
259
 
50
- private:
51
- WriteBarrier() = delete;
260
+ template <typename HeapHandleCallback>
261
+ static V8_INLINE WriteBarrier::Type GetForExternallyReferenced(
262
+ const void* value, WriteBarrier::Params& params,
263
+ HeapHandleCallback callback) {
264
+ // The slot will never be used in `Get()` below.
265
+ return Get<WriteBarrier::ValueMode::kValuePresent>(nullptr, value, params,
266
+ callback);
267
+ }
52
268
 
53
- static void MarkingBarrierSlow(const void* value);
54
- static void MarkingBarrierSlowWithSentinelCheck(const void* value);
269
+ private:
270
+ template <WriteBarrier::ValueMode value_mode>
271
+ struct ValueModeDispatch;
55
272
 
56
- #if defined(CPPGC_YOUNG_GENERATION)
57
- static V8_INLINE void GenerationalBarrier(CagedHeapLocalData* local_data,
58
- const void* slot,
59
- uintptr_t slot_offset,
60
- uintptr_t value_offset) {
61
- const AgeTable& age_table = local_data->age_table;
273
+ // TODO(chromium:1056170): Create fast path on API.
274
+ static bool IsMarking(const void*, HeapHandle**);
275
+ // TODO(chromium:1056170): Create fast path on API.
276
+ static bool IsMarking(HeapHandle&);
62
277
 
63
- // Bail out if the slot is in young generation.
64
- if (V8_LIKELY(age_table[slot_offset] == AgeTable::Age::kYoung)) return;
278
+ WriteBarrierTypeForNonCagedHeapPolicy() = delete;
279
+ };
65
280
 
66
- GenerationalBarrierSlow(local_data, age_table, slot, value_offset);
281
+ template <>
282
+ struct WriteBarrierTypeForNonCagedHeapPolicy::ValueModeDispatch<
283
+ WriteBarrier::ValueMode::kValuePresent> {
284
+ template <typename HeapHandleCallback>
285
+ static V8_INLINE WriteBarrier::Type Get(const void*, const void* object,
286
+ WriteBarrier::Params& params,
287
+ HeapHandleCallback callback) {
288
+ // The following check covers nullptr as well as sentinel pointer.
289
+ if (object <= static_cast<void*>(kSentinelPointer)) {
290
+ return WriteBarrier::Type::kNone;
291
+ }
292
+ if (IsMarking(object, &params.heap)) {
293
+ return SetAndReturnType<WriteBarrier::Type::kMarking>(params);
294
+ }
295
+ return SetAndReturnType<WriteBarrier::Type::kNone>(params);
67
296
  }
297
+ };
68
298
 
69
- static void GenerationalBarrierSlow(CagedHeapLocalData* local_data,
70
- const AgeTable& ageTable,
71
- const void* slot, uintptr_t value_offset);
72
- #endif
299
+ template <>
300
+ struct WriteBarrierTypeForNonCagedHeapPolicy::ValueModeDispatch<
301
+ WriteBarrier::ValueMode::kNoValuePresent> {
302
+ template <typename HeapHandleCallback>
303
+ static V8_INLINE WriteBarrier::Type Get(const void*, const void*,
304
+ WriteBarrier::Params& params,
305
+ HeapHandleCallback callback) {
306
+ if (V8_UNLIKELY(WriteBarrier::IsAnyIncrementalOrConcurrentMarking())) {
307
+ HeapHandle& handle = callback();
308
+ if (IsMarking(handle)) {
309
+ params.heap = &handle;
310
+ return SetAndReturnType<WriteBarrier::Type::kMarking>(params);
311
+ }
312
+ }
313
+ return WriteBarrier::Type::kNone;
314
+ }
73
315
  };
74
316
 
317
+ // static
318
+ WriteBarrier::Type WriteBarrier::GetWriteBarrierType(
319
+ const void* slot, const void* value, WriteBarrier::Params& params) {
320
+ return WriteBarrierTypePolicy::Get<ValueMode::kValuePresent>(slot, value,
321
+ params, []() {});
322
+ }
323
+
324
+ // static
325
+ template <typename HeapHandleCallback>
326
+ WriteBarrier::Type WriteBarrier::GetWriteBarrierType(
327
+ const void* slot, WriteBarrier::Params& params,
328
+ HeapHandleCallback callback) {
329
+ return WriteBarrierTypePolicy::Get<ValueMode::kNoValuePresent>(
330
+ slot, nullptr, params, callback);
331
+ }
332
+
333
+ // static
334
+ template <typename HeapHandleCallback>
335
+ WriteBarrier::Type
336
+ WriteBarrier::GetWriteBarrierTypeForExternallyReferencedObject(
337
+ const void* value, Params& params, HeapHandleCallback callback) {
338
+ return WriteBarrierTypePolicy::GetForExternallyReferenced(value, params,
339
+ callback);
340
+ }
341
+
342
+ // static
343
+ void WriteBarrier::DijkstraMarkingBarrier(const Params& params,
344
+ const void* object) {
345
+ CheckParams(Type::kMarking, params);
346
+ #if defined(CPPGC_CAGED_HEAP)
347
+ // Caged heap already filters out sentinels.
348
+ DijkstraMarkingBarrierSlow(object);
349
+ #else // !CPPGC_CAGED_HEAP
350
+ DijkstraMarkingBarrierSlowWithSentinelCheck(object);
351
+ #endif // !CPPGC_CAGED_HEAP
352
+ }
353
+
354
+ // static
355
+ void WriteBarrier::DijkstraMarkingBarrierRange(const Params& params,
356
+ const void* first_element,
357
+ size_t element_size,
358
+ size_t number_of_elements,
359
+ TraceCallback trace_callback) {
360
+ CheckParams(Type::kMarking, params);
361
+ DijkstraMarkingBarrierRangeSlow(*params.heap, first_element, element_size,
362
+ number_of_elements, trace_callback);
363
+ }
364
+
365
+ // static
366
+ void WriteBarrier::SteeleMarkingBarrier(const Params& params,
367
+ const void* object) {
368
+ CheckParams(Type::kMarking, params);
369
+ #if defined(CPPGC_CAGED_HEAP)
370
+ // Caged heap already filters out sentinels.
371
+ SteeleMarkingBarrierSlow(object);
372
+ #else // !CPPGC_CAGED_HEAP
373
+ SteeleMarkingBarrierSlowWithSentinelCheck(object);
374
+ #endif // !CPPGC_CAGED_HEAP
375
+ }
376
+
377
+ #if defined(CPPGC_YOUNG_GENERATION)
378
+ // static
379
+ void WriteBarrier::GenerationalBarrier(const Params& params, const void* slot) {
380
+ CheckParams(Type::kGenerational, params);
381
+
382
+ const CagedHeapLocalData& local_data = params.caged_heap();
383
+ const AgeTable& age_table = local_data.age_table;
384
+
385
+ // Bail out if the slot is in young generation.
386
+ if (V8_LIKELY(age_table[params.slot_offset] == AgeTable::Age::kYoung)) return;
387
+
388
+ GenerationalBarrierSlow(local_data, age_table, slot, params.value_offset);
389
+ }
390
+
391
+ #endif // !CPPGC_YOUNG_GENERATION
392
+
75
393
  } // namespace internal
76
394
  } // namespace cppgc
77
395
 
@@ -19,7 +19,7 @@ class LivenessBrokerFactory;
19
19
  /**
20
20
  * The broker is passed to weak callbacks to allow (temporarily) querying
21
21
  * the liveness state of an object. References to non-live objects must be
22
- * cleared when IsHeapObjectAlive() returns false.
22
+ * cleared when `IsHeapObjectAlive()` returns false.
23
23
  *
24
24
  * \code
25
25
  * class GCedWithCustomWeakCallback final
@@ -49,6 +49,12 @@ class V8_EXPORT LivenessBroker final {
49
49
  TraceTrait<T>::GetTraceDescriptor(object).base_object_payload);
50
50
  }
51
51
 
52
+ template <typename T>
53
+ bool IsHeapObjectAlive(const WeakMember<T>& weak_member) const {
54
+ return (weak_member != kSentinelPointer) &&
55
+ IsHeapObjectAlive<T>(weak_member.Get());
56
+ }
57
+
52
58
  template <typename T>
53
59
  bool IsHeapObjectAlive(const UntracedMember<T>& untraced_member) const {
54
60
  return (untraced_member != kSentinelPointer) &&
@@ -5,6 +5,8 @@
5
5
  #ifndef INCLUDE_CPPGC_MACROS_H_
6
6
  #define INCLUDE_CPPGC_MACROS_H_
7
7
 
8
+ #include <cstddef>
9
+
8
10
  #include "cppgc/internal/compiler-specific.h"
9
11
 
10
12
  namespace cppgc {
@@ -10,6 +10,7 @@
10
10
  #include <type_traits>
11
11
 
12
12
  #include "cppgc/internal/pointer-policies.h"
13
+ #include "cppgc/sentinel-pointer.h"
13
14
  #include "cppgc/type-traits.h"
14
15
  #include "v8config.h" // NOLINT(build/include_directory)
15
16
 
@@ -19,28 +20,33 @@ class Visitor;
19
20
 
20
21
  namespace internal {
21
22
 
23
+ // MemberBase always refers to the object as const object and defers to
24
+ // BasicMember on casting to the right type as needed.
22
25
  class MemberBase {
23
26
  protected:
27
+ struct AtomicInitializerTag {};
28
+
24
29
  MemberBase() = default;
25
- explicit MemberBase(void* value) : raw_(value) {}
30
+ explicit MemberBase(const void* value) : raw_(value) {}
31
+ MemberBase(const void* value, AtomicInitializerTag) { SetRawAtomic(value); }
26
32
 
27
- void* const* GetRawSlot() const { return &raw_; }
28
- void* GetRaw() const { return raw_; }
33
+ const void** GetRawSlot() const { return &raw_; }
34
+ const void* GetRaw() const { return raw_; }
29
35
  void SetRaw(void* value) { raw_ = value; }
30
36
 
31
- void* GetRawAtomic() const {
32
- return reinterpret_cast<const std::atomic<void*>*>(&raw_)->load(
37
+ const void* GetRawAtomic() const {
38
+ return reinterpret_cast<const std::atomic<const void*>*>(&raw_)->load(
33
39
  std::memory_order_relaxed);
34
40
  }
35
- void SetRawAtomic(void* value) {
36
- reinterpret_cast<std::atomic<void*>*>(&raw_)->store(
41
+ void SetRawAtomic(const void* value) {
42
+ reinterpret_cast<std::atomic<const void*>*>(&raw_)->store(
37
43
  value, std::memory_order_relaxed);
38
44
  }
39
45
 
40
46
  void ClearFromGC() const { raw_ = nullptr; }
41
47
 
42
48
  private:
43
- mutable void* raw_ = nullptr;
49
+ mutable const void* raw_ = nullptr;
44
50
  };
45
51
 
46
52
  // The basic class from which all Member classes are 'generated'.
@@ -58,6 +64,21 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
58
64
  this->CheckPointer(Get());
59
65
  }
60
66
  BasicMember(T& raw) : BasicMember(&raw) {} // NOLINT
67
+ // Atomic ctor. Using the AtomicInitializerTag forces BasicMember to
68
+ // initialize using atomic assignments. This is required for preventing
69
+ // data races with concurrent marking.
70
+ using AtomicInitializerTag = MemberBase::AtomicInitializerTag;
71
+ BasicMember(std::nullptr_t, AtomicInitializerTag atomic)
72
+ : MemberBase(nullptr, atomic) {}
73
+ BasicMember(SentinelPointer s, AtomicInitializerTag atomic)
74
+ : MemberBase(s, atomic) {}
75
+ BasicMember(T* raw, AtomicInitializerTag atomic) : MemberBase(raw, atomic) {
76
+ InitializingWriteBarrier();
77
+ this->CheckPointer(Get());
78
+ }
79
+ BasicMember(T& raw, AtomicInitializerTag atomic)
80
+ : BasicMember(&raw, atomic) {}
81
+ // Copy ctor.
61
82
  BasicMember(const BasicMember& other) : BasicMember(other.Get()) {}
62
83
  // Allow heterogeneous construction.
63
84
  template <typename U, typename OtherBarrierPolicy, typename OtherWeaknessTag,
@@ -67,21 +88,34 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
67
88
  const BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
68
89
  OtherCheckingPolicy>& other)
69
90
  : BasicMember(other.Get()) {}
91
+ // Move ctor.
92
+ BasicMember(BasicMember&& other) noexcept : BasicMember(other.Get()) {
93
+ other.Clear();
94
+ }
95
+ // Allow heterogeneous move construction.
96
+ template <typename U, typename OtherBarrierPolicy, typename OtherWeaknessTag,
97
+ typename OtherCheckingPolicy,
98
+ typename = std::enable_if_t<std::is_base_of<T, U>::value>>
99
+ BasicMember(BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
100
+ OtherCheckingPolicy>&& other) noexcept
101
+ : BasicMember(other.Get()) {
102
+ other.Clear();
103
+ }
70
104
  // Construction from Persistent.
71
105
  template <typename U, typename PersistentWeaknessPolicy,
72
106
  typename PersistentLocationPolicy,
73
107
  typename PersistentCheckingPolicy,
74
108
  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
75
- BasicMember( // NOLINT
76
- const BasicPersistent<U, PersistentWeaknessPolicy,
77
- PersistentLocationPolicy, PersistentCheckingPolicy>&
78
- p)
109
+ BasicMember(const BasicPersistent<U, PersistentWeaknessPolicy,
110
+ PersistentLocationPolicy,
111
+ PersistentCheckingPolicy>& p)
79
112
  : BasicMember(p.Get()) {}
80
113
 
114
+ // Copy assignment.
81
115
  BasicMember& operator=(const BasicMember& other) {
82
116
  return operator=(other.Get());
83
117
  }
84
- // Allow heterogeneous assignment.
118
+ // Allow heterogeneous copy assignment.
85
119
  template <typename U, typename OtherWeaknessTag, typename OtherBarrierPolicy,
86
120
  typename OtherCheckingPolicy,
87
121
  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
@@ -90,6 +124,22 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
90
124
  OtherCheckingPolicy>& other) {
91
125
  return operator=(other.Get());
92
126
  }
127
+ // Move assignment.
128
+ BasicMember& operator=(BasicMember&& other) noexcept {
129
+ operator=(other.Get());
130
+ other.Clear();
131
+ return *this;
132
+ }
133
+ // Heterogeneous move assignment.
134
+ template <typename U, typename OtherWeaknessTag, typename OtherBarrierPolicy,
135
+ typename OtherCheckingPolicy,
136
+ typename = std::enable_if_t<std::is_base_of<T, U>::value>>
137
+ BasicMember& operator=(BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
138
+ OtherCheckingPolicy>&& other) noexcept {
139
+ operator=(other.Get());
140
+ other.Clear();
141
+ return *this;
142
+ }
93
143
  // Assignment from Persistent.
94
144
  template <typename U, typename PersistentWeaknessPolicy,
95
145
  typename PersistentLocationPolicy,
@@ -126,7 +176,7 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
126
176
  }
127
177
 
128
178
  explicit operator bool() const { return Get(); }
129
- operator T*() const { return Get(); } // NOLINT
179
+ operator T*() const { return Get(); }
130
180
  T* operator->() const { return Get(); }
131
181
  T& operator*() const { return *Get(); }
132
182
 
@@ -135,7 +185,11 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
135
185
  // based on their actual types.
136
186
  V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T* Get() const {
137
187
  // Executed by the mutator, hence non atomic load.
138
- return static_cast<T*>(MemberBase::GetRaw());
188
+ //
189
+ // The const_cast below removes the constness from MemberBase storage. The
190
+ // following static_cast re-adds any constness if specified through the
191
+ // user-visible template parameter T.
192
+ return static_cast<T*>(const_cast<void*>(MemberBase::GetRaw()));
139
193
  }
140
194
 
141
195
  void Clear() { SetRawAtomic(nullptr); }
@@ -146,9 +200,13 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
146
200
  return result;
147
201
  }
148
202
 
203
+ const T** GetSlotForTesting() const {
204
+ return reinterpret_cast<const T**>(GetRawSlot());
205
+ }
206
+
149
207
  private:
150
- T* GetRawAtomic() const {
151
- return static_cast<T*>(MemberBase::GetRawAtomic());
208
+ const T* GetRawAtomic() const {
209
+ return static_cast<const T*>(MemberBase::GetRawAtomic());
152
210
  }
153
211
 
154
212
  void InitializingWriteBarrier() const {
@@ -161,25 +219,27 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
161
219
  void ClearFromGC() const { MemberBase::ClearFromGC(); }
162
220
 
163
221
  friend class cppgc::Visitor;
222
+ template <typename U>
223
+ friend struct cppgc::TraceTrait;
164
224
  };
165
225
 
166
226
  template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,
167
227
  typename CheckingPolicy1, typename T2, typename WeaknessTag2,
168
228
  typename WriteBarrierPolicy2, typename CheckingPolicy2>
169
- bool operator==(
170
- BasicMember<T1, WeaknessTag1, WriteBarrierPolicy1, CheckingPolicy1> member1,
171
- BasicMember<T2, WeaknessTag2, WriteBarrierPolicy2, CheckingPolicy2>
172
- member2) {
229
+ bool operator==(const BasicMember<T1, WeaknessTag1, WriteBarrierPolicy1,
230
+ CheckingPolicy1>& member1,
231
+ const BasicMember<T2, WeaknessTag2, WriteBarrierPolicy2,
232
+ CheckingPolicy2>& member2) {
173
233
  return member1.Get() == member2.Get();
174
234
  }
175
235
 
176
236
  template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,
177
237
  typename CheckingPolicy1, typename T2, typename WeaknessTag2,
178
238
  typename WriteBarrierPolicy2, typename CheckingPolicy2>
179
- bool operator!=(
180
- BasicMember<T1, WeaknessTag1, WriteBarrierPolicy1, CheckingPolicy1> member1,
181
- BasicMember<T2, WeaknessTag2, WriteBarrierPolicy2, CheckingPolicy2>
182
- member2) {
239
+ bool operator!=(const BasicMember<T1, WeaknessTag1, WriteBarrierPolicy1,
240
+ CheckingPolicy1>& member1,
241
+ const BasicMember<T2, WeaknessTag2, WriteBarrierPolicy2,
242
+ CheckingPolicy2>& member2) {
183
243
  return !(member1 == member2);
184
244
  }
185
245