OLD | NEW |
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 RawObject; | 16 class RawObject; |
16 | 17 |
17 class StoreBufferBlock { | 18 class StoreBufferBlock { |
18 public: | 19 public: |
19 // Each block contains kSize pointers. | 20 // Each full block contains kSize pointers. |
20 static const int32_t kSize = 1024; | 21 static const int32_t kSize = 1024; |
21 | 22 |
22 explicit StoreBufferBlock(StoreBufferBlock* next) : next_(next), top_(0) {} | |
23 | |
24 void Reset() { top_ = 0; } | 23 void Reset() { top_ = 0; } |
25 | 24 |
| 25 // TODO(koda): Make private after adding visitor interface to StoreBuffer. |
26 StoreBufferBlock* next() const { return next_; } | 26 StoreBufferBlock* next() const { return next_; } |
27 | 27 |
28 intptr_t Count() const { return top_; } | 28 intptr_t Count() const { return top_; } |
| 29 bool IsFull() const { return Count() == kSize; } |
| 30 |
| 31 void Add(RawObject* obj) { |
| 32 ASSERT(!IsFull()); |
| 33 pointers_[top_++] = obj; |
| 34 } |
29 | 35 |
30 RawObject* At(intptr_t i) const { | 36 RawObject* At(intptr_t i) const { |
31 ASSERT(i >= 0); | 37 ASSERT(i >= 0); |
32 ASSERT(i < top_); | 38 ASSERT(i < top_); |
33 return pointers_[i]; | 39 return pointers_[i]; |
34 } | 40 } |
35 | 41 |
| 42 #if defined(TESTING) |
| 43 bool Contains(RawObject* obj) const { |
| 44 for (intptr_t i = 0; i < Count(); i++) { |
| 45 if (At(i) == obj) { |
| 46 return true; |
| 47 } |
| 48 } |
| 49 return false; |
| 50 } |
| 51 #endif // TESTING |
| 52 |
36 static intptr_t top_offset() { return OFFSET_OF(StoreBufferBlock, top_); } | 53 static intptr_t top_offset() { return OFFSET_OF(StoreBufferBlock, top_); } |
37 static intptr_t pointers_offset() { | 54 static intptr_t pointers_offset() { |
38 return OFFSET_OF(StoreBufferBlock, pointers_); | 55 return OFFSET_OF(StoreBufferBlock, pointers_); |
39 } | 56 } |
40 | 57 |
41 private: | 58 private: |
| 59 StoreBufferBlock() : next_(NULL), top_(0) {} |
| 60 |
42 StoreBufferBlock* next_; | 61 StoreBufferBlock* next_; |
43 int32_t top_; | 62 int32_t top_; |
44 RawObject* pointers_[kSize]; | 63 RawObject* pointers_[kSize]; |
45 | 64 |
46 friend class StoreBuffer; | 65 friend class StoreBuffer; |
47 | 66 |
48 DISALLOW_COPY_AND_ASSIGN(StoreBufferBlock); | 67 DISALLOW_COPY_AND_ASSIGN(StoreBufferBlock); |
49 }; | 68 }; |
50 | 69 |
51 | 70 |
52 class StoreBuffer { | 71 class StoreBuffer { |
53 public: | 72 public: |
54 StoreBuffer() : blocks_(new StoreBufferBlock(NULL)), full_count_(0) {} | 73 StoreBuffer(); |
55 explicit StoreBuffer(bool shallow_copy) : blocks_(NULL), full_count_(0) { | |
56 // The value shallow_copy is only used to select this non-allocating | |
57 // constructor. It is always expected to be true. | |
58 ASSERT(shallow_copy); | |
59 } | |
60 ~StoreBuffer(); | 74 ~StoreBuffer(); |
61 | 75 |
62 intptr_t Count() const { | 76 // Adds and transfers ownership of the block to the buffer. |
63 return blocks_->Count() + (full_count_ * StoreBufferBlock::kSize); | 77 void PushBlock(StoreBufferBlock* block, bool check_threshold = true); |
64 } | 78 // Partially filled blocks can be reused, and there is an "inifite" supply |
| 79 // of empty blocks (reused or newly allocated). In any case, the caller |
| 80 // takes ownership of the returned block. |
| 81 StoreBufferBlock* PopBlock(); |
| 82 StoreBufferBlock* PopEmptyBlock(); |
65 | 83 |
| 84 // Pops and returns all non-empty blocks as a linked list (owned by caller). |
| 85 // TODO(koda): Replace with VisitObjectPointers. |
| 86 StoreBufferBlock* Blocks(); |
| 87 |
| 88 // Discards the contents of this store buffer. |
66 void Reset(); | 89 void Reset(); |
67 | 90 |
68 void AddObject(RawObject* obj) { | 91 private: |
69 StoreBufferBlock* block = blocks_; | 92 class List { |
70 ASSERT(block->top_ < StoreBufferBlock::kSize); | 93 public: |
71 block->pointers_[block->top_++] = obj; | 94 List() : head_(NULL), length_(0) {} |
72 if (block->top_ == StoreBufferBlock::kSize) { | 95 ~List(); |
73 Expand(true); | 96 void Push(StoreBufferBlock* block); |
74 } | 97 StoreBufferBlock* Pop(); |
75 } | 98 intptr_t length() const { return length_; } |
| 99 bool IsEmpty() const { return head_ == NULL; } |
| 100 StoreBufferBlock* PopAll(); |
| 101 private: |
| 102 StoreBufferBlock* head_; |
| 103 intptr_t length_; |
| 104 DISALLOW_COPY_AND_ASSIGN(List); |
| 105 }; |
76 | 106 |
77 void AddObjectGC(RawObject* obj) { | |
78 StoreBufferBlock* block = blocks_; | |
79 ASSERT(block->top_ < StoreBufferBlock::kSize); | |
80 block->pointers_[block->top_++] = obj; | |
81 if (block->top_ == StoreBufferBlock::kSize) { | |
82 Expand(false); | |
83 } | |
84 } | |
85 | |
86 StoreBufferBlock* Blocks() { | |
87 StoreBufferBlock* result = blocks_; | |
88 blocks_ = new StoreBufferBlock(NULL); | |
89 full_count_ = 0; | |
90 return result; | |
91 } | |
92 | |
93 // Expand the storage and optionally check whethe to schedule an interrupt. | |
94 void Expand(bool check); | |
95 | |
96 bool Contains(RawObject* raw); | |
97 | |
98 static int blocks_offset() { return OFFSET_OF(StoreBuffer, blocks_); } | |
99 | |
100 private: | |
101 // Check if we run over the max number of deduplication sets. | 107 // Check if we run over the max number of deduplication sets. |
102 // If we did schedule an interrupt. | 108 // If we did schedule an interrupt. |
103 void CheckThreshold(); | 109 void CheckThreshold(); |
104 | 110 |
105 StoreBufferBlock* blocks_; | 111 List full_; |
106 intptr_t full_count_; | 112 List partial_; |
| 113 // TODO(koda): static List empty_ |
| 114 Mutex* mutex_; |
107 | 115 |
108 DISALLOW_COPY_AND_ASSIGN(StoreBuffer); | 116 DISALLOW_COPY_AND_ASSIGN(StoreBuffer); |
109 }; | 117 }; |
110 | 118 |
111 } // namespace dart | 119 } // namespace dart |
112 | 120 |
113 #endif // VM_STORE_BUFFER_H_ | 121 #endif // VM_STORE_BUFFER_H_ |
OLD | NEW |