| 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 |