Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium 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 CallbackStack_h | 5 #ifndef CallbackStack_h |
| 6 #define CallbackStack_h | 6 #define CallbackStack_h |
| 7 | 7 |
| 8 #include "platform/heap/BlinkGC.h" | 8 #include "platform/heap/BlinkGC.h" |
| 9 #include "wtf/Allocator.h" | 9 #include "wtf/Allocator.h" |
| 10 #include "wtf/Assertions.h" | 10 #include "wtf/Assertions.h" |
| 11 #include "wtf/Threading.h" | |
| 12 #include "wtf/ThreadingPrimitives.h" | |
| 11 | 13 |
| 12 namespace blink { | 14 namespace blink { |
| 13 | 15 |
| 14 // The CallbackStack contains all the visitor callbacks used to trace and mark | 16 // The CallbackStack contains all the visitor callbacks used to trace and mark |
| 15 // objects. A specific CallbackStack instance contains at most bufferSize elemen ts. | 17 // objects. A specific CallbackStack instance contains at most bufferSize elemen ts. |
| 16 // If more space is needed a new CallbackStack instance is created and chained | 18 // If more space is needed a new CallbackStack instance is created and chained |
| 17 // together with the former instance. I.e. a logical CallbackStack can be made o f | 19 // together with the former instance. I.e. a logical CallbackStack can be made o f |
| 18 // multiple chained CallbackStack object instances. | 20 // multiple chained CallbackStack object instances. |
| 19 class CallbackStack final { | 21 class CallbackStack final { |
| 20 USING_FAST_MALLOC(CallbackStack); | 22 USING_FAST_MALLOC(CallbackStack); |
| 21 public: | 23 public: |
| 22 class Item { | 24 class Item { |
| 23 DISALLOW_NEW(); | 25 DISALLOW_NEW(); |
| 24 public: | 26 public: |
| 25 Item() { } | 27 Item() { } |
| 26 Item(void* object, VisitorCallback callback) | 28 Item(void* object, VisitorCallback callback) |
| 27 : m_object(object) | 29 : m_object(object) |
| 28 , m_callback(callback) | 30 , m_callback(callback) |
| 29 { | 31 { |
| 30 } | 32 } |
| 31 void* object() { return m_object; } | 33 void* object() { return m_object; } |
| 32 VisitorCallback callback() { return m_callback; } | 34 VisitorCallback callback() { return m_callback; } |
| 33 void call(Visitor* visitor) { m_callback(visitor, m_object); } | 35 void call(Visitor* visitor) { m_callback(visitor, m_object); } |
| 34 | 36 |
| 35 private: | 37 private: |
| 36 void* m_object; | 38 void* m_object; |
| 37 VisitorCallback m_callback; | 39 VisitorCallback m_callback; |
| 38 }; | 40 }; |
| 39 | 41 |
| 40 explicit CallbackStack(size_t blockSize = kDefaultBlockSize); | 42 CallbackStack(); |
| 41 ~CallbackStack(); | 43 ~CallbackStack(); |
| 42 | 44 |
| 43 void clear(); | 45 void commit(); |
| 44 void decommit(); | 46 void decommit(); |
| 45 | 47 |
| 46 Item* allocateEntry(); | 48 Item* allocateEntry(); |
| 47 Item* pop(); | 49 Item* pop(); |
| 48 | 50 |
| 49 bool isEmpty() const; | 51 bool isEmpty() const; |
| 50 | 52 |
| 51 void invokeEphemeronCallbacks(Visitor*); | 53 void invokeEphemeronCallbacks(Visitor*); |
| 52 | 54 |
| 53 #if ENABLE(ASSERT) | 55 #if ENABLE(ASSERT) |
| 54 bool hasCallbackForObject(const void*); | 56 bool hasCallbackForObject(const void*); |
| 55 #endif | 57 #endif |
| 58 bool hasJustOneBlock() const; | |
| 56 | 59 |
| 57 static const size_t kMinimalBlockSize; | 60 static const size_t kMinimalBlockSize; |
| 58 static const size_t kDefaultBlockSize = (1 << 13); | 61 static const size_t kDefaultBlockSize = (1 << 13); |
| 59 | 62 |
| 60 private: | 63 private: |
| 61 class Block { | 64 class Block { |
| 62 USING_FAST_MALLOC(Block); | 65 USING_FAST_MALLOC(Block); |
| 63 public: | 66 public: |
| 64 Block(Block* next, size_t blockSize); | 67 explicit Block(Block* next); |
| 65 ~Block(); | 68 ~Block(); |
| 66 | 69 |
| 67 #if ENABLE(ASSERT) | 70 #if ENABLE(ASSERT) |
| 68 void clear(); | 71 void clear(); |
| 69 #endif | 72 #endif |
| 70 void reset(); | |
| 71 void decommit(); | |
| 72 | |
| 73 Block* next() const { return m_next; } | 73 Block* next() const { return m_next; } |
| 74 void setNext(Block* next) { m_next = next; } | 74 void setNext(Block* next) { m_next = next; } |
| 75 | 75 |
| 76 bool isEmptyBlock() const | 76 bool isEmptyBlock() const |
| 77 { | 77 { |
| 78 return m_current == &(m_buffer[0]); | 78 return m_current == &(m_buffer[0]); |
| 79 } | 79 } |
| 80 | 80 |
| 81 size_t blockSize() const { return m_blockSize; } | 81 size_t blockSize() const { return m_blockSize; } |
| 82 | 82 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 105 | 105 |
| 106 Item* m_buffer; | 106 Item* m_buffer; |
| 107 Item* m_limit; | 107 Item* m_limit; |
| 108 Item* m_current; | 108 Item* m_current; |
| 109 Block* m_next; | 109 Block* m_next; |
| 110 }; | 110 }; |
| 111 | 111 |
| 112 Item* popSlow(); | 112 Item* popSlow(); |
| 113 Item* allocateEntrySlow(); | 113 Item* allocateEntrySlow(); |
| 114 void invokeOldestCallbacks(Block*, Block*, Visitor*); | 114 void invokeOldestCallbacks(Block*, Block*, Visitor*); |
| 115 bool hasJustOneBlock() const; | |
| 116 | 115 |
| 117 Block* m_first; | 116 Block* m_first; |
| 118 Block* m_last; | 117 Block* m_last; |
| 119 }; | 118 }; |
| 120 | 119 |
| 120 class CallbackStackMemoryPool final { | |
| 121 USING_FAST_MALLOC(CallbackStackMemoryPool); | |
| 122 public: | |
| 123 // 2048 * 8 * sizeof(Item) = 256 KB is pre-allocated for the underlying | |
|
sof
2016/07/05 14:19:02
256Kb for some choice of pointer size, yes. :)
| |
| 124 // buffer of CallbackStacks. | |
| 125 static const size_t kBlockSize = 2048; | |
| 126 static const size_t kPooledBlockCount = 8; | |
| 127 | |
| 128 static CallbackStackMemoryPool& instance(); | |
| 129 | |
| 130 void initialize(); | |
| 131 void shutdown(); | |
| 132 CallbackStack::Item* allocate(); | |
| 133 void free(CallbackStack::Item*); | |
| 134 | |
| 135 private: | |
| 136 Mutex m_mutex; | |
| 137 int m_freeListFirst; | |
| 138 int m_freeListNext[kPooledBlockCount]; | |
| 139 CallbackStack::Item* m_pooledMemory; | |
| 140 }; | |
| 141 | |
| 121 ALWAYS_INLINE CallbackStack::Item* CallbackStack::allocateEntry() | 142 ALWAYS_INLINE CallbackStack::Item* CallbackStack::allocateEntry() |
| 122 { | 143 { |
| 144 DCHECK(m_first); | |
| 123 Item* item = m_first->allocateEntry(); | 145 Item* item = m_first->allocateEntry(); |
| 124 if (LIKELY(!!item)) | 146 if (LIKELY(!!item)) |
| 125 return item; | 147 return item; |
| 126 | 148 |
| 127 return allocateEntrySlow(); | 149 return allocateEntrySlow(); |
| 128 } | 150 } |
| 129 | 151 |
| 130 ALWAYS_INLINE CallbackStack::Item* CallbackStack::pop() | 152 ALWAYS_INLINE CallbackStack::Item* CallbackStack::pop() |
| 131 { | 153 { |
| 132 Item* item = m_first->pop(); | 154 Item* item = m_first->pop(); |
| 133 if (LIKELY(!!item)) | 155 if (LIKELY(!!item)) |
| 134 return item; | 156 return item; |
| 135 | 157 |
| 136 return popSlow(); | 158 return popSlow(); |
| 137 } | 159 } |
| 138 | 160 |
| 139 } // namespace blink | 161 } // namespace blink |
| 140 | 162 |
| 141 #endif // CallbackStack_h | 163 #endif // CallbackStack_h |
| OLD | NEW |