Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(539)

Side by Side Diff: src/heap/marking.h

Issue 2492263002: [heap] Add atomics to mark bit operations. (Closed)
Patch Set: fixup missing call sites Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef V8_MARKING_H 5 #ifndef V8_MARKING_H
6 #define V8_MARKING_H 6 #define V8_MARKING_H
7 7
8 #include "src/base/atomic-utils.h"
8 #include "src/utils.h" 9 #include "src/utils.h"
9 10
10 namespace v8 { 11 namespace v8 {
11 namespace internal { 12 namespace internal {
12 13
13 class MarkBit { 14 class MarkBit {
14 public: 15 public:
15 typedef uint32_t CellType; 16 typedef uint32_t CellType;
Michael Lippautz 2017/03/06 13:52:54 nit: Can we have a static_assert that sizeof(CellT
Hannes Payer (out of office) 2017/03/08 14:12:57 Done.
16 17
17 inline MarkBit(CellType* cell, CellType mask) : cell_(cell), mask_(mask) {} 18 enum ModificationMode { ATOMIC, NON_ATOMIC };
Michael Lippautz 2017/03/06 13:52:54 You could make an enum class ModicationMode out
Hannes Payer (out of office) 2017/03/08 14:12:57 I kind of like it to keep it in the MarkBit class
19
20 inline MarkBit(base::Atomic32* cell, CellType mask) : cell_(cell) {
21 mask_ = static_cast<base::Atomic32>(mask);
22 }
18 23
19 #ifdef DEBUG 24 #ifdef DEBUG
20 bool operator==(const MarkBit& other) { 25 bool operator==(const MarkBit& other) {
21 return cell_ == other.cell_ && mask_ == other.mask_; 26 return cell_ == other.cell_ && mask_ == other.mask_;
22 } 27 }
23 #endif 28 #endif
24 29
25 private: 30 private:
26 inline CellType* cell() { return cell_; }
27 inline CellType mask() { return mask_; }
28
29 inline MarkBit Next() { 31 inline MarkBit Next() {
30 CellType new_mask = mask_ << 1; 32 CellType new_mask = mask_ << 1;
31 if (new_mask == 0) { 33 if (new_mask == 0) {
32 return MarkBit(cell_ + 1, 1); 34 return MarkBit(cell_ + 1, 1);
33 } else { 35 } else {
34 return MarkBit(cell_, new_mask); 36 return MarkBit(cell_, new_mask);
35 } 37 }
36 } 38 }
37 39
38 inline void Set() { *cell_ |= mask_; } 40 template <ModificationMode mode>
39 inline bool Get() { return (*cell_ & mask_) != 0; } 41 inline bool Set() {
40 inline void Clear() { *cell_ &= ~mask_; } 42 if (mode == ATOMIC) {
43 base::Atomic32 old_value;
44 base::Atomic32 new_value;
45 do {
46 old_value = base::NoBarrier_Load(cell_);
47 if (old_value & mask_) return false;
48 new_value = old_value | mask_;
49 } while (base::Release_CompareAndSwap(cell_, old_value, new_value) !=
50 old_value);
51 } else {
52 *cell_ |= mask_;
53 }
54 return true;
55 }
41 56
42 CellType* cell_; 57 template <ModificationMode mode>
43 CellType mask_; 58 inline bool Get() {
59 if (mode == ATOMIC) {
60 return (base::Acquire_Load(cell_) & mask_) != 0;
61 } else {
62 return (base::NoBarrier_Load(cell_) & mask_) != 0;
63 }
64 }
65
66 template <ModificationMode mode>
67 inline bool Clear() {
68 if (mode == ATOMIC) {
69 base::Atomic32 old_value;
70 base::Atomic32 new_value;
71 do {
72 old_value = base::NoBarrier_Load(cell_);
73 if (!(old_value & mask_)) return false;
74 new_value = old_value & ~mask_;
75 } while (base::Release_CompareAndSwap(cell_, old_value, new_value) !=
76 old_value);
77 } else {
78 *cell_ &= ~mask_;
79 }
80 return true;
81 }
82
83 base::Atomic32* cell_;
84 base::Atomic32 mask_;
44 85
45 friend class IncrementalMarking; 86 friend class IncrementalMarking;
46 friend class Marking; 87 friend class Marking;
47 }; 88 };
48 89
49 // Bitmap is a sequence of cells each containing fixed number of bits. 90 // Bitmap is a sequence of cells each containing fixed number of bits.
50 class Bitmap { 91 class Bitmap {
51 public: 92 public:
52 static const uint32_t kBitsPerCell = 32; 93 static const uint32_t kBitsPerCell = 32;
53 static const uint32_t kBitsPerCellLog2 = 5; 94 static const uint32_t kBitsPerCellLog2 = 5;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 133
93 INLINE(Address address()) { return reinterpret_cast<Address>(this); } 134 INLINE(Address address()) { return reinterpret_cast<Address>(this); }
94 135
95 INLINE(static Bitmap* FromAddress(Address addr)) { 136 INLINE(static Bitmap* FromAddress(Address addr)) {
96 return reinterpret_cast<Bitmap*>(addr); 137 return reinterpret_cast<Bitmap*>(addr);
97 } 138 }
98 139
99 inline MarkBit MarkBitFromIndex(uint32_t index) { 140 inline MarkBit MarkBitFromIndex(uint32_t index) {
100 MarkBit::CellType mask = 1u << IndexInCell(index); 141 MarkBit::CellType mask = 1u << IndexInCell(index);
101 MarkBit::CellType* cell = this->cells() + (index >> kBitsPerCellLog2); 142 MarkBit::CellType* cell = this->cells() + (index >> kBitsPerCellLog2);
102 return MarkBit(cell, mask); 143 return MarkBit(reinterpret_cast<base::Atomic32*>(cell), mask);
103 } 144 }
104 145
105 void Clear() { 146 void Clear() {
106 for (int i = 0; i < CellsCount(); i++) cells()[i] = 0; 147 for (int i = 0; i < CellsCount(); i++) cells()[i] = 0;
107 } 148 }
108 149
109 // Sets all bits in the range [start_index, end_index). 150 // Sets all bits in the range [start_index, end_index).
110 void SetRange(uint32_t start_index, uint32_t end_index) { 151 void SetRange(uint32_t start_index, uint32_t end_index) {
111 unsigned int start_cell_index = start_index >> Bitmap::kBitsPerCellLog2; 152 unsigned int start_cell_index = start_index >> Bitmap::kBitsPerCellLog2;
112 MarkBit::CellType start_index_mask = 1u << Bitmap::IndexInCell(start_index); 153 MarkBit::CellType start_index_mask = 1u << Bitmap::IndexInCell(start_index);
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 if (cells()[i] != 0) { 303 if (cells()[i] != 0) {
263 return false; 304 return false;
264 } 305 }
265 } 306 }
266 return true; 307 return true;
267 } 308 }
268 }; 309 };
269 310
270 class Marking : public AllStatic { 311 class Marking : public AllStatic {
271 public: 312 public:
313 // TODO(hpayer): The current mark bit operations use as default NON_ATOMIC
314 // mode for access. We should remove the default value or switch it with
315 // ATOMIC as soon we add concurrency.
316
272 // Impossible markbits: 01 317 // Impossible markbits: 01
273 static const char* kImpossibleBitPattern; 318 static const char* kImpossibleBitPattern;
319 template <MarkBit::ModificationMode mode = MarkBit::NON_ATOMIC>
274 INLINE(static bool IsImpossible(MarkBit mark_bit)) { 320 INLINE(static bool IsImpossible(MarkBit mark_bit)) {
275 return !mark_bit.Get() && mark_bit.Next().Get(); 321 return !mark_bit.Get<mode>() && mark_bit.Next().Get<mode>();
ulan 2017/03/06 14:51:33 Atomic version can return false positive if betwee
Hannes Payer (out of office) 2017/03/08 14:12:57 This function is still useful. I made it safe for
276 } 322 }
277 323
278 // Black markbits: 11 324 // Black markbits: 11
279 static const char* kBlackBitPattern; 325 static const char* kBlackBitPattern;
326 template <MarkBit::ModificationMode mode = MarkBit::NON_ATOMIC>
280 INLINE(static bool IsBlack(MarkBit mark_bit)) { 327 INLINE(static bool IsBlack(MarkBit mark_bit)) {
281 return mark_bit.Get() && mark_bit.Next().Get(); 328 return mark_bit.Get<mode>() && mark_bit.Next().Get<mode>();
282 } 329 }
283 330
284 // White markbits: 00 - this is required by the mark bit clearer. 331 // White markbits: 00 - this is required by the mark bit clearer.
285 static const char* kWhiteBitPattern; 332 static const char* kWhiteBitPattern;
333 template <MarkBit::ModificationMode mode = MarkBit::NON_ATOMIC>
286 INLINE(static bool IsWhite(MarkBit mark_bit)) { 334 INLINE(static bool IsWhite(MarkBit mark_bit)) {
287 DCHECK(!IsImpossible(mark_bit)); 335 DCHECK(!IsImpossible(mark_bit));
288 return !mark_bit.Get(); 336 return !mark_bit.Get<mode>();
289 } 337 }
290 338
291 // Grey markbits: 10 339 // Grey markbits: 10
292 static const char* kGreyBitPattern; 340 static const char* kGreyBitPattern;
341 template <MarkBit::ModificationMode mode = MarkBit::NON_ATOMIC>
293 INLINE(static bool IsGrey(MarkBit mark_bit)) { 342 INLINE(static bool IsGrey(MarkBit mark_bit)) {
294 return mark_bit.Get() && !mark_bit.Next().Get(); 343 return mark_bit.Get<mode>() && !mark_bit.Next().Get<mode>();
295 } 344 }
296 345
297 // IsBlackOrGrey assumes that the first bit is set for black or grey 346 // IsBlackOrGrey assumes that the first bit is set for black or grey
298 // objects. 347 // objects.
299 INLINE(static bool IsBlackOrGrey(MarkBit mark_bit)) { return mark_bit.Get(); } 348 template <MarkBit::ModificationMode mode = MarkBit::NON_ATOMIC>
300 349 INLINE(static bool IsBlackOrGrey(MarkBit mark_bit)) {
301 INLINE(static void MarkWhite(MarkBit markbit)) { 350 return mark_bit.Get<mode>();
302 markbit.Clear();
303 markbit.Next().Clear();
304 } 351 }
305 352
306 INLINE(static void BlackToGrey(MarkBit markbit)) { 353 template <MarkBit::ModificationMode mode = MarkBit::NON_ATOMIC>
307 DCHECK(IsBlack(markbit)); 354 INLINE(static bool MarkWhite(MarkBit markbit)) {
ulan 2017/03/06 14:51:33 All functions that move the color in black -> grey
Hannes Payer (out of office) 2017/03/08 14:12:57 Done. Why is BlackToGrey a problem?
308 markbit.Next().Clear(); 355 if (!markbit.Clear<mode>()) return false;
356 return markbit.Next().Clear<mode>();
309 } 357 }
310 358
311 INLINE(static void WhiteToGrey(MarkBit markbit)) { 359 template <MarkBit::ModificationMode mode = MarkBit::NON_ATOMIC>
312 DCHECK(IsWhite(markbit)); 360 INLINE(static bool BlackToGrey(MarkBit markbit)) {
313 markbit.Set(); 361 DCHECK(IsBlack(markbit));
362 return markbit.Next().Clear<mode>();
314 } 363 }
315 364
316 INLINE(static void WhiteToBlack(MarkBit markbit)) { 365 template <MarkBit::ModificationMode mode = MarkBit::NON_ATOMIC>
366 INLINE(static bool WhiteToGrey(MarkBit markbit)) {
317 DCHECK(IsWhite(markbit)); 367 DCHECK(IsWhite(markbit));
318 markbit.Set(); 368 return markbit.Set<mode>();
319 markbit.Next().Set();
320 } 369 }
321 370
322 INLINE(static void GreyToBlack(MarkBit markbit)) { 371 template <MarkBit::ModificationMode mode = MarkBit::NON_ATOMIC>
372 INLINE(static bool WhiteToBlack(MarkBit markbit)) {
373 DCHECK(IsWhite(markbit));
374 if (!markbit.Set<mode>()) return false;
375 return markbit.Next().Set<mode>();
376 }
377
378 template <MarkBit::ModificationMode mode = MarkBit::NON_ATOMIC>
379 INLINE(static bool GreyToBlack(MarkBit markbit)) {
323 DCHECK(IsGrey(markbit)); 380 DCHECK(IsGrey(markbit));
324 markbit.Next().Set(); 381 return markbit.Next().Set<mode>();
325 } 382 }
326 383
327 enum ObjectColor { 384 enum ObjectColor {
328 BLACK_OBJECT, 385 BLACK_OBJECT,
329 WHITE_OBJECT, 386 WHITE_OBJECT,
330 GREY_OBJECT, 387 GREY_OBJECT,
331 IMPOSSIBLE_COLOR 388 IMPOSSIBLE_COLOR
332 }; 389 };
333 390
334 static const char* ColorName(ObjectColor color) { 391 static const char* ColorName(ObjectColor color) {
(...skipping 19 matching lines...) Expand all
354 } 411 }
355 412
356 private: 413 private:
357 DISALLOW_IMPLICIT_CONSTRUCTORS(Marking); 414 DISALLOW_IMPLICIT_CONSTRUCTORS(Marking);
358 }; 415 };
359 416
360 } // namespace internal 417 } // namespace internal
361 } // namespace v8 418 } // namespace v8
362 419
363 #endif // V8_MARKING_H_ 420 #endif // V8_MARKING_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698