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

Side by Side Diff: runtime/vm/store_buffer.h

Issue 1350933004: Distinct block sizes for StoreBuffer/MarkingStack. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Address review comments. Created 5 years, 3 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
« no previous file with comments | « runtime/vm/scavenger.cc ('k') | runtime/vm/store_buffer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #ifndef VM_STORE_BUFFER_H_ 5 #ifndef VM_STORE_BUFFER_H_
6 #define VM_STORE_BUFFER_H_ 6 #define VM_STORE_BUFFER_H_
7 7
8 #include "platform/assert.h" 8 #include "platform/assert.h"
9 #include "vm/globals.h" 9 #include "vm/globals.h"
10 10
11 namespace dart { 11 namespace dart {
12 12
13 // Forward declarations. 13 // Forward declarations.
14 class Isolate; 14 class Isolate;
15 class Mutex; 15 class Mutex;
16 class RawObject; 16 class RawObject;
17 17
18 // A set of RawObject*. Must be emptied before destruction (using Pop/Reset). 18 // A set of RawObject*. Must be emptied before destruction (using Pop/Reset).
19 class StoreBufferBlock { 19 template<int Size>
20 class PointerBlock {
20 public: 21 public:
21 // Each full block contains kSize pointers. 22 enum { kSize = Size };
22 static const int32_t kSize = 1024;
23 23
24 void Reset() { 24 void Reset() {
25 top_ = 0; 25 top_ = 0;
26 next_ = NULL; 26 next_ = NULL;
27 } 27 }
28 28
29 StoreBufferBlock* next() const { return next_; } 29 PointerBlock<Size>* next() const { return next_; }
30 30
31 intptr_t Count() const { return top_; } 31 intptr_t Count() const { return top_; }
32 bool IsFull() const { return Count() == kSize; } 32 bool IsFull() const { return Count() == kSize; }
33 bool IsEmpty() const { return Count() == 0; } 33 bool IsEmpty() const { return Count() == 0; }
34 34
35 void Push(RawObject* obj) { 35 void Push(RawObject* obj) {
36 ASSERT(!IsFull()); 36 ASSERT(!IsFull());
37 pointers_[top_++] = obj; 37 pointers_[top_++] = obj;
38 } 38 }
39 39
40 RawObject* Pop() { 40 RawObject* Pop() {
41 ASSERT(!IsEmpty()); 41 ASSERT(!IsEmpty());
42 return pointers_[--top_]; 42 return pointers_[--top_];
43 } 43 }
44 44
45 #if defined(TESTING) 45 #if defined(TESTING)
46 bool Contains(RawObject* obj) const { 46 bool Contains(RawObject* obj) const {
47 for (intptr_t i = 0; i < Count(); i++) { 47 for (intptr_t i = 0; i < Count(); i++) {
48 if (pointers_[i] == obj) { 48 if (pointers_[i] == obj) {
49 return true; 49 return true;
50 } 50 }
51 } 51 }
52 return false; 52 return false;
53 } 53 }
54 #endif // TESTING 54 #endif // TESTING
55 55
56 static intptr_t top_offset() { return OFFSET_OF(StoreBufferBlock, top_); } 56 static intptr_t top_offset() { return OFFSET_OF(PointerBlock<Size>, top_); }
57 static intptr_t pointers_offset() { 57 static intptr_t pointers_offset() {
58 return OFFSET_OF(StoreBufferBlock, pointers_); 58 return OFFSET_OF(PointerBlock<Size>, pointers_);
59 } 59 }
60 60
61 private: 61 private:
62 StoreBufferBlock() : next_(NULL), top_(0) {} 62 PointerBlock() : next_(NULL), top_(0) {}
63 ~StoreBufferBlock() { 63 ~PointerBlock() {
64 ASSERT(IsEmpty()); // Guard against unintentionally discarding pointers. 64 ASSERT(IsEmpty()); // Guard against unintentionally discarding pointers.
65 } 65 }
66 66
67 StoreBufferBlock* next_; 67 PointerBlock<Size>* next_;
68 int32_t top_; 68 int32_t top_;
69 RawObject* pointers_[kSize]; 69 RawObject* pointers_[kSize];
70 70
71 friend class StoreBuffer; 71 template<int> friend class BlockStack;
72 72
73 DISALLOW_COPY_AND_ASSIGN(StoreBufferBlock); 73 DISALLOW_COPY_AND_ASSIGN(PointerBlock);
74 }; 74 };
75 75
76 76
77 class StoreBuffer { 77 // A synchronized collection of pointer blocks of a particular size.
78 // This class is meant to be used as a base (note PushBlockImpl is protected).
79 // The global list of cached empty blocks is currently per-size.
80 template<int BlockSize>
81 class BlockStack {
78 public: 82 public:
79 StoreBuffer(); 83 typedef PointerBlock<BlockSize> Block;
80 ~StoreBuffer(); 84
85 BlockStack();
86 ~BlockStack();
81 static void InitOnce(); 87 static void InitOnce();
82 static void ShutDown(); 88 static void ShutDown();
83 89
84 // Interrupt when crossing this threshold of non-empty blocks in the buffer.
85 static const intptr_t kMaxNonEmpty = 100;
86
87 // Adds and transfers ownership of the block to the buffer.
88 void PushBlock(StoreBufferBlock* block, bool check_threshold = true);
89 // Partially filled blocks can be reused, and there is an "inifite" supply 90 // Partially filled blocks can be reused, and there is an "inifite" supply
90 // of empty blocks (reused or newly allocated). In any case, the caller 91 // of empty blocks (reused or newly allocated). In any case, the caller
91 // takes ownership of the returned block. 92 // takes ownership of the returned block.
92 StoreBufferBlock* PopNonFullBlock(); 93 Block* PopNonFullBlock();
93 StoreBufferBlock* PopEmptyBlock(); 94 Block* PopEmptyBlock();
94 StoreBufferBlock* PopNonEmptyBlock(); 95 Block* PopNonEmptyBlock();
95 96
96 // Pops and returns all non-empty blocks as a linked list (owned by caller). 97 // Pops and returns all non-empty blocks as a linked list (owned by caller).
97 StoreBufferBlock* Blocks(); 98 Block* Blocks();
98 99
99 // Discards the contents of this store buffer. 100 // Discards the contents of all non-empty blocks.
100 void Reset(); 101 void Reset();
101 102
102 // Check whether non-empty blocks have exceeded kMaxNonEmpty.
103 bool Overflowed();
104
105 bool IsEmpty(); 103 bool IsEmpty();
106 104
107 private: 105 protected:
108 class List { 106 class List {
109 public: 107 public:
110 List() : head_(NULL), length_(0) {} 108 List() : head_(NULL), length_(0) {}
111 ~List(); 109 ~List();
112 void Push(StoreBufferBlock* block); 110 void Push(Block* block);
113 StoreBufferBlock* Pop(); 111 Block* Pop();
114 intptr_t length() const { return length_; } 112 intptr_t length() const { return length_; }
115 bool IsEmpty() const { return head_ == NULL; } 113 bool IsEmpty() const { return head_ == NULL; }
116 StoreBufferBlock* PopAll(); 114 Block* PopAll();
117 private: 115 private:
118 StoreBufferBlock* head_; 116 Block* head_;
119 intptr_t length_; 117 intptr_t length_;
120 DISALLOW_COPY_AND_ASSIGN(List); 118 DISALLOW_COPY_AND_ASSIGN(List);
121 }; 119 };
122 120
121 // Adds and transfers ownership of the block to the buffer.
122 void PushBlockImpl(Block* block);
123
123 // If needed, trims the the global cache of empty blocks. 124 // If needed, trims the the global cache of empty blocks.
124 static void TrimGlobalEmpty(); 125 static void TrimGlobalEmpty();
125 126
126 List full_; 127 List full_;
127 List partial_; 128 List partial_;
128 Mutex* mutex_; 129 Mutex* mutex_;
129 130
131 // Note: This is shared on the basis of block size.
130 static const intptr_t kMaxGlobalEmpty = 100; 132 static const intptr_t kMaxGlobalEmpty = 100;
131 static List* global_empty_; 133 static List* global_empty_;
132 static Mutex* global_mutex_; 134 static Mutex* global_mutex_;
133 135
134 DISALLOW_COPY_AND_ASSIGN(StoreBuffer); 136 private:
137 DISALLOW_COPY_AND_ASSIGN(BlockStack);
135 }; 138 };
136 139
140
141 static const int kStoreBufferBlockSize = 1024;
142 class StoreBuffer : public BlockStack<kStoreBufferBlockSize> {
143 public:
144 // Interrupt when crossing this threshold of non-empty blocks in the buffer.
145 static const intptr_t kMaxNonEmpty = 100;
146
147 enum ThresholdPolicy {
148 kCheckThreshold,
149 kIgnoreThreshold
150 };
151
152 // Adds and transfers ownership of the block to the buffer. Optionally
153 // checks the number of non-empty blocks for overflow, and schedules an
154 // interrupt on the current isolate if so.
155 void PushBlock(Block* block, ThresholdPolicy policy);
156
157 // Check whether non-empty blocks have exceeded kMaxNonEmpty (but takes no
158 // action).
159 bool Overflowed();
160 };
161
162
163 typedef StoreBuffer::Block StoreBufferBlock;
164
165
166 static const int kMarkingStackBlockSize = 64;
167 class MarkingStack : public BlockStack<kMarkingStackBlockSize> {
168 public:
169 // Adds and transfers ownership of the block to the buffer.
170 void PushBlock(Block* block) {
171 BlockStack<Block::kSize>::PushBlockImpl(block);
172 }
173 };
174
175
137 } // namespace dart 176 } // namespace dart
138 177
139 #endif // VM_STORE_BUFFER_H_ 178 #endif // VM_STORE_BUFFER_H_
OLDNEW
« no previous file with comments | « runtime/vm/scavenger.cc ('k') | runtime/vm/store_buffer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698