OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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_STORE_BUFFER_H_ | 5 #ifndef V8_STORE_BUFFER_H_ |
6 #define V8_STORE_BUFFER_H_ | 6 #define V8_STORE_BUFFER_H_ |
7 | 7 |
8 #include "src/allocation.h" | 8 #include "src/allocation.h" |
9 #include "src/base/logging.h" | 9 #include "src/base/logging.h" |
10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
11 #include "src/globals.h" | 11 #include "src/globals.h" |
12 #include "src/heap/slot-set.h" | 12 #include "src/heap/slot-set.h" |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 | 16 |
17 class Page; | 17 // Intermediate buffer that accumulates old-to-new stores from the generated |
18 class PagedSpace; | 18 // code. On buffer overflow the slots are moved to the remembered set. |
19 class StoreBuffer; | |
20 | |
21 typedef void (*ObjectSlotCallback)(HeapObject** from, HeapObject* to); | |
22 | |
23 // Used to implement the write barrier by collecting addresses of pointers | |
24 // between spaces. | |
25 class StoreBuffer { | 19 class StoreBuffer { |
26 public: | 20 public: |
27 explicit StoreBuffer(Heap* heap); | 21 explicit StoreBuffer(Heap* heap); |
28 static void StoreBufferOverflow(Isolate* isolate); | 22 static void StoreBufferOverflow(Isolate* isolate); |
29 void SetUp(); | 23 void SetUp(); |
30 void TearDown(); | 24 void TearDown(); |
31 | 25 |
32 static const int kStoreBufferOverflowBit = 1 << (14 + kPointerSizeLog2); | 26 static const int kStoreBufferOverflowBit = 1 << (14 + kPointerSizeLog2); |
33 static const int kStoreBufferSize = kStoreBufferOverflowBit; | 27 static const int kStoreBufferSize = kStoreBufferOverflowBit; |
34 static const int kStoreBufferLength = kStoreBufferSize / sizeof(Address); | 28 static const int kStoreBufferLength = kStoreBufferSize / sizeof(Address); |
35 | 29 |
36 // This is used to add addresses to the store buffer non-concurrently. | 30 void MoveEntriesToRememberedSet(); |
37 inline void Mark(Address addr); | |
38 | |
39 // Removes the given slot from the store buffer non-concurrently. If the | |
40 // slot was never added to the store buffer, then the function does nothing. | |
41 void Remove(Address addr); | |
42 | |
43 // Slots that do not point to the ToSpace after callback invocation will be | |
44 // removed from the set. | |
45 void IteratePointersToNewSpace(ObjectSlotCallback callback); | |
46 | |
47 void Verify(); | |
48 | |
49 // Eliminates all stale store buffer entries from the store buffer, i.e., | |
50 // slots that are not part of live objects anymore. This method must be | |
51 // called after marking, when the whole transitive closure is known and | |
52 // must be called before sweeping when mark bits are still intact. | |
53 void ClearInvalidStoreBufferEntries(); | |
54 void VerifyValidStoreBufferEntries(); | |
55 | 31 |
56 private: | 32 private: |
57 Heap* heap_; | 33 Heap* heap_; |
58 | 34 |
59 // The start and the limit of the buffer that contains store slots | 35 // The start and the limit of the buffer that contains store slots |
60 // added from the generated code. | 36 // added from the generated code. |
61 Address* start_; | 37 Address* start_; |
62 Address* limit_; | 38 Address* limit_; |
63 | 39 |
64 base::VirtualMemory* virtual_memory_; | 40 base::VirtualMemory* virtual_memory_; |
65 | |
66 // Used for synchronization of concurrent store buffer access. | |
67 base::Mutex mutex_; | |
68 | |
69 void InsertEntriesFromBuffer(); | |
70 | |
71 inline uint32_t AddressToSlotSetAndOffset(Address slot_address, | |
72 SlotSet** slots); | |
73 | |
74 template <typename Callback> | |
75 void Iterate(Callback callback); | |
76 | |
77 #ifdef VERIFY_HEAP | |
78 void VerifyPointers(LargeObjectSpace* space); | |
79 #endif | |
80 }; | 41 }; |
81 | 42 |
82 | 43 |
83 class LocalStoreBuffer BASE_EMBEDDED { | 44 class LocalStoreBuffer BASE_EMBEDDED { |
84 public: | 45 public: |
85 LocalStoreBuffer() : top_(new Node(nullptr)) {} | 46 explicit LocalStoreBuffer(Heap* heap) |
| 47 : top_(new Node(nullptr)), heap_(heap) {} |
86 | 48 |
87 ~LocalStoreBuffer() { | 49 ~LocalStoreBuffer() { |
88 Node* current = top_; | 50 Node* current = top_; |
89 while (current != nullptr) { | 51 while (current != nullptr) { |
90 Node* tmp = current->next; | 52 Node* tmp = current->next; |
91 delete current; | 53 delete current; |
92 current = tmp; | 54 current = tmp; |
93 } | 55 } |
94 } | 56 } |
95 | 57 |
96 inline void Record(Address addr); | 58 inline void Record(Address addr); |
97 inline void Process(StoreBuffer* store_buffer); | 59 inline void Process(StoreBuffer* store_buffer); |
98 | 60 |
99 private: | 61 private: |
100 static const int kBufferSize = 16 * KB; | 62 static const int kBufferSize = 16 * KB; |
101 | 63 |
102 struct Node : Malloced { | 64 struct Node : Malloced { |
103 explicit Node(Node* next_node) : next(next_node), count(0) {} | 65 explicit Node(Node* next_node) : next(next_node), count(0) {} |
104 | 66 |
105 inline bool is_full() { return count == kBufferSize; } | 67 inline bool is_full() { return count == kBufferSize; } |
106 | 68 |
107 Node* next; | 69 Node* next; |
108 Address buffer[kBufferSize]; | 70 Address buffer[kBufferSize]; |
109 int count; | 71 int count; |
110 }; | 72 }; |
111 | 73 |
112 Node* top_; | 74 Node* top_; |
| 75 Heap* heap_; |
113 }; | 76 }; |
114 | 77 |
115 } // namespace internal | 78 } // namespace internal |
116 } // namespace v8 | 79 } // namespace v8 |
117 | 80 |
118 #endif // V8_STORE_BUFFER_H_ | 81 #endif // V8_STORE_BUFFER_H_ |
OLD | NEW |