35 #include "utilities/debug.hpp" |
35 #include "utilities/debug.hpp" |
36 #include "utilities/globalDefinitions.hpp" |
36 #include "utilities/globalDefinitions.hpp" |
37 |
37 |
38 // Array of all active blocks. Refcounted for lock-free reclaim of |
38 // Array of all active blocks. Refcounted for lock-free reclaim of |
39 // old array when a new array is allocated for expansion. |
39 // old array when a new array is allocated for expansion. |
40 class OopStorage::BlockArray { |
40 class OopStorage::ActiveArray { |
41 friend class OopStorage::TestAccess; |
41 friend class OopStorage::TestAccess; |
42 |
42 |
43 size_t _size; |
43 size_t _size; |
44 volatile size_t _block_count; |
44 volatile size_t _block_count; |
45 mutable volatile int _refcount; |
45 mutable volatile int _refcount; |
46 // Block* _blocks[1]; // Pseudo flexible array member. |
46 // Block* _blocks[1]; // Pseudo flexible array member. |
47 |
47 |
48 BlockArray(size_t size); |
48 ActiveArray(size_t size); |
49 ~BlockArray(); |
49 ~ActiveArray(); |
50 |
50 |
51 // Noncopyable |
51 // Noncopyable |
52 BlockArray(const BlockArray&); |
52 ActiveArray(const ActiveArray&); |
53 BlockArray& operator=(const BlockArray&); |
53 ActiveArray& operator=(const ActiveArray&); |
54 |
54 |
55 static size_t blocks_offset(); |
55 static size_t blocks_offset(); |
56 Block* const* base_ptr() const; |
56 Block* const* base_ptr() const; |
57 |
57 |
58 Block* const* block_ptr(size_t index) const; |
58 Block* const* block_ptr(size_t index) const; |
59 Block** block_ptr(size_t index); |
59 Block** block_ptr(size_t index); |
60 |
60 |
61 public: |
61 public: |
62 static BlockArray* create(size_t size, AllocFailType alloc_fail = AllocFailStrategy::EXIT_OOM); |
62 static ActiveArray* create(size_t size, AllocFailType alloc_fail = AllocFailStrategy::EXIT_OOM); |
63 static void destroy(BlockArray* ba); |
63 static void destroy(ActiveArray* ba); |
64 |
64 |
65 inline Block* at(size_t i) const; |
65 inline Block* at(size_t i) const; |
66 |
66 |
67 size_t size() const; |
67 size_t size() const; |
68 size_t block_count() const; |
68 size_t block_count() const; |
80 // Support OopStorage::delete_empty_blocks_xxx operations. |
80 // Support OopStorage::delete_empty_blocks_xxx operations. |
81 // Remove block from the array. |
81 // Remove block from the array. |
82 // precondition: block must be present at its active_index element. |
82 // precondition: block must be present at its active_index element. |
83 void remove(Block* block); |
83 void remove(Block* block); |
84 |
84 |
85 void copy_from(const BlockArray* from); |
85 void copy_from(const ActiveArray* from); |
86 }; |
86 }; |
87 |
87 |
88 inline size_t OopStorage::BlockArray::blocks_offset() { |
88 inline size_t OopStorage::ActiveArray::blocks_offset() { |
89 return align_up(sizeof(BlockArray), sizeof(Block*)); |
89 return align_up(sizeof(ActiveArray), sizeof(Block*)); |
90 } |
90 } |
91 |
91 |
92 inline OopStorage::Block* const* OopStorage::BlockArray::base_ptr() const { |
92 inline OopStorage::Block* const* OopStorage::ActiveArray::base_ptr() const { |
93 const void* ptr = reinterpret_cast<const char*>(this) + blocks_offset(); |
93 const void* ptr = reinterpret_cast<const char*>(this) + blocks_offset(); |
94 return reinterpret_cast<Block* const*>(ptr); |
94 return reinterpret_cast<Block* const*>(ptr); |
95 } |
95 } |
96 |
96 |
97 inline OopStorage::Block* const* OopStorage::BlockArray::block_ptr(size_t index) const { |
97 inline OopStorage::Block* const* OopStorage::ActiveArray::block_ptr(size_t index) const { |
98 return base_ptr() + index; |
98 return base_ptr() + index; |
99 } |
99 } |
100 |
100 |
101 inline OopStorage::Block** OopStorage::BlockArray::block_ptr(size_t index) { |
101 inline OopStorage::Block** OopStorage::ActiveArray::block_ptr(size_t index) { |
102 return const_cast<Block**>(base_ptr() + index); |
102 return const_cast<Block**>(base_ptr() + index); |
103 } |
103 } |
104 |
104 |
105 inline OopStorage::Block* OopStorage::BlockArray::at(size_t index) const { |
105 inline OopStorage::Block* OopStorage::ActiveArray::at(size_t index) const { |
106 assert(index < _block_count, "precondition"); |
106 assert(index < _block_count, "precondition"); |
107 return *block_ptr(index); |
107 return *block_ptr(index); |
108 } |
108 } |
109 |
109 |
110 // A Block has an embedded BlockEntry to provide the links between |
110 // A Block has an embedded AllocateEntry to provide the links between |
111 // Blocks in a BlockList. |
111 // Blocks in a AllocateList. |
112 class OopStorage::BlockEntry { |
112 class OopStorage::AllocateEntry { |
113 friend class OopStorage::BlockList; |
113 friend class OopStorage::AllocateList; |
114 |
114 |
115 // Members are mutable, and we deal exclusively with pointers to |
115 // Members are mutable, and we deal exclusively with pointers to |
116 // const, to make const blocks easier to use; a block being const |
116 // const, to make const blocks easier to use; a block being const |
117 // doesn't prevent modifying its list state. |
117 // doesn't prevent modifying its list state. |
118 mutable const Block* _prev; |
118 mutable const Block* _prev; |
119 mutable const Block* _next; |
119 mutable const Block* _next; |
120 |
120 |
121 // Noncopyable. |
121 // Noncopyable. |
122 BlockEntry(const BlockEntry&); |
122 AllocateEntry(const AllocateEntry&); |
123 BlockEntry& operator=(const BlockEntry&); |
123 AllocateEntry& operator=(const AllocateEntry&); |
124 |
124 |
125 public: |
125 public: |
126 BlockEntry(); |
126 AllocateEntry(); |
127 ~BlockEntry(); |
127 ~AllocateEntry(); |
128 }; |
128 }; |
129 |
129 |
130 // Fixed-sized array of oops, plus bookkeeping data. |
130 // Fixed-sized array of oops, plus bookkeeping data. |
131 // All blocks are in the storage's _active_array, at the block's _active_index. |
131 // All blocks are in the storage's _active_array, at the block's _active_index. |
132 // Non-full blocks are in the storage's _allocate_list, linked through the |
132 // Non-full blocks are in the storage's _allocate_list, linked through the |
138 |
138 |
139 volatile uintx _allocated_bitmask; // One bit per _data element. |
139 volatile uintx _allocated_bitmask; // One bit per _data element. |
140 const OopStorage* _owner; |
140 const OopStorage* _owner; |
141 void* _memory; // Unaligned storage containing block. |
141 void* _memory; // Unaligned storage containing block. |
142 size_t _active_index; |
142 size_t _active_index; |
143 BlockEntry _allocate_entry; |
143 AllocateEntry _allocate_entry; |
144 Block* volatile _deferred_updates_next; |
144 Block* volatile _deferred_updates_next; |
145 volatile uintx _release_refcount; |
145 volatile uintx _release_refcount; |
146 |
146 |
147 Block(const OopStorage* owner, void* memory); |
147 Block(const OopStorage* owner, void* memory); |
148 ~Block(); |
148 ~Block(); |
195 |
195 |
196 template<typename F> bool iterate(F f); |
196 template<typename F> bool iterate(F f); |
197 template<typename F> bool iterate(F f) const; |
197 template<typename F> bool iterate(F f) const; |
198 }; // class Block |
198 }; // class Block |
199 |
199 |
200 inline OopStorage::Block* OopStorage::BlockList::head() { |
200 inline OopStorage::Block* OopStorage::AllocateList::head() { |
201 return const_cast<Block*>(_head); |
201 return const_cast<Block*>(_head); |
202 } |
202 } |
203 |
203 |
204 inline OopStorage::Block* OopStorage::BlockList::tail() { |
204 inline OopStorage::Block* OopStorage::AllocateList::tail() { |
205 return const_cast<Block*>(_tail); |
205 return const_cast<Block*>(_tail); |
206 } |
206 } |
207 |
207 |
208 inline const OopStorage::Block* OopStorage::BlockList::chead() const { |
208 inline const OopStorage::Block* OopStorage::AllocateList::chead() const { |
209 return _head; |
209 return _head; |
210 } |
210 } |
211 |
211 |
212 inline const OopStorage::Block* OopStorage::BlockList::ctail() const { |
212 inline const OopStorage::Block* OopStorage::AllocateList::ctail() const { |
213 return _tail; |
213 return _tail; |
214 } |
214 } |
215 |
215 |
216 inline OopStorage::Block* OopStorage::BlockList::prev(Block& block) { |
216 inline OopStorage::Block* OopStorage::AllocateList::prev(Block& block) { |
217 return const_cast<Block*>(_get_entry(block)._prev); |
217 return const_cast<Block*>(_get_entry(block)._prev); |
218 } |
218 } |
219 |
219 |
220 inline OopStorage::Block* OopStorage::BlockList::next(Block& block) { |
220 inline OopStorage::Block* OopStorage::AllocateList::next(Block& block) { |
221 return const_cast<Block*>(_get_entry(block)._next); |
221 return const_cast<Block*>(_get_entry(block)._next); |
222 } |
222 } |
223 |
223 |
224 inline const OopStorage::Block* OopStorage::BlockList::prev(const Block& block) const { |
224 inline const OopStorage::Block* OopStorage::AllocateList::prev(const Block& block) const { |
225 return _get_entry(block)._prev; |
225 return _get_entry(block)._prev; |
226 } |
226 } |
227 |
227 |
228 inline const OopStorage::Block* OopStorage::BlockList::next(const Block& block) const { |
228 inline const OopStorage::Block* OopStorage::AllocateList::next(const Block& block) const { |
229 return _get_entry(block)._next; |
229 return _get_entry(block)._next; |
230 } |
230 } |
231 |
231 |
232 template<typename Closure> |
232 template<typename Closure> |
233 class OopStorage::OopFn { |
233 class OopStorage::OopFn { |
355 inline bool OopStorage::iterate_impl(F f, Storage* storage) { |
355 inline bool OopStorage::iterate_impl(F f, Storage* storage) { |
356 assert_at_safepoint(); |
356 assert_at_safepoint(); |
357 // Propagate const/non-const iteration to the block layer, by using |
357 // Propagate const/non-const iteration to the block layer, by using |
358 // const or non-const blocks as corresponding to Storage. |
358 // const or non-const blocks as corresponding to Storage. |
359 typedef typename Conditional<IsConst<Storage>::value, const Block*, Block*>::type BlockPtr; |
359 typedef typename Conditional<IsConst<Storage>::value, const Block*, Block*>::type BlockPtr; |
360 BlockArray* blocks = storage->_active_array; |
360 ActiveArray* blocks = storage->_active_array; |
361 size_t limit = blocks->block_count(); |
361 size_t limit = blocks->block_count(); |
362 for (size_t i = 0; i < limit; ++i) { |
362 for (size_t i = 0; i < limit; ++i) { |
363 BlockPtr block = blocks->at(i); |
363 BlockPtr block = blocks->at(i); |
364 if (!block->iterate(f)) { |
364 if (!block->iterate(f)) { |
365 return false; |
365 return false; |