28 #include "gc/shared/oopStorage.hpp" |
28 #include "gc/shared/oopStorage.hpp" |
29 #include "metaprogramming/conditional.hpp" |
29 #include "metaprogramming/conditional.hpp" |
30 #include "metaprogramming/isConst.hpp" |
30 #include "metaprogramming/isConst.hpp" |
31 #include "oops/oop.hpp" |
31 #include "oops/oop.hpp" |
32 #include "runtime/safepoint.hpp" |
32 #include "runtime/safepoint.hpp" |
|
33 #include "utilities/align.hpp" |
33 #include "utilities/count_trailing_zeros.hpp" |
34 #include "utilities/count_trailing_zeros.hpp" |
34 #include "utilities/debug.hpp" |
35 #include "utilities/debug.hpp" |
35 #include "utilities/globalDefinitions.hpp" |
36 #include "utilities/globalDefinitions.hpp" |
36 |
37 |
|
38 // Array of all active blocks. Refcounted for lock-free reclaim of |
|
39 // old array when a new array is allocated for expansion. |
|
40 class OopStorage::BlockArray { |
|
41 friend class OopStorage::TestAccess; |
|
42 |
|
43 size_t _size; |
|
44 volatile size_t _block_count; |
|
45 mutable volatile int _refcount; |
|
46 // Block* _blocks[1]; // Pseudo flexible array member. |
|
47 |
|
48 BlockArray(size_t size); |
|
49 ~BlockArray(); |
|
50 |
|
51 // Noncopyable |
|
52 BlockArray(const BlockArray&); |
|
53 BlockArray& operator=(const BlockArray&); |
|
54 |
|
55 static size_t blocks_offset(); |
|
56 Block* const* base_ptr() const; |
|
57 |
|
58 Block* const* block_ptr(size_t index) const; |
|
59 Block** block_ptr(size_t index); |
|
60 |
|
61 public: |
|
62 static BlockArray* create(size_t size, AllocFailType alloc_fail = AllocFailStrategy::EXIT_OOM); |
|
63 static void destroy(BlockArray* ba); |
|
64 |
|
65 inline Block* at(size_t i) const; |
|
66 |
|
67 size_t size() const; |
|
68 size_t block_count() const; |
|
69 size_t block_count_acquire() const; |
|
70 void increment_refcount() const; |
|
71 bool decrement_refcount() const; // Return true if zero, otherwise false |
|
72 |
|
73 // Support for OopStorage::allocate. |
|
74 // Add block to the end of the array. Updates block count at the |
|
75 // end of the operation, with a release_store. Returns true if the |
|
76 // block was added, false if there was no room available. |
|
77 // precondition: owner's _allocation_mutex is locked, or at safepoint. |
|
78 bool push(Block* block); |
|
79 |
|
80 // Support OopStorage::delete_empty_blocks_xxx operations. |
|
81 // Remove block from the array. |
|
82 // precondition: block must be present at its active_index element. |
|
83 void remove(Block* block); |
|
84 |
|
85 void copy_from(const BlockArray* from); |
|
86 }; |
|
87 |
|
88 inline size_t OopStorage::BlockArray::blocks_offset() { |
|
89 return align_up(sizeof(BlockArray), sizeof(Block*)); |
|
90 } |
|
91 |
|
92 inline OopStorage::Block* const* OopStorage::BlockArray::base_ptr() const { |
|
93 const void* ptr = reinterpret_cast<const char*>(this) + blocks_offset(); |
|
94 return reinterpret_cast<Block* const*>(ptr); |
|
95 } |
|
96 |
|
97 inline OopStorage::Block* const* OopStorage::BlockArray::block_ptr(size_t index) const { |
|
98 return base_ptr() + index; |
|
99 } |
|
100 |
|
101 inline OopStorage::Block** OopStorage::BlockArray::block_ptr(size_t index) { |
|
102 return const_cast<Block**>(base_ptr() + index); |
|
103 } |
|
104 |
|
105 inline OopStorage::Block* OopStorage::BlockArray::at(size_t index) const { |
|
106 assert(index < _block_count, "precondition"); |
|
107 return *block_ptr(index); |
|
108 } |
|
109 |
|
110 // A Block has an embedded BlockEntry to provide the links between |
|
111 // Blocks in a BlockList. |
|
112 class OopStorage::BlockEntry { |
|
113 friend class OopStorage::BlockList; |
|
114 |
|
115 // Members are mutable, and we deal exclusively with pointers to |
|
116 // const, to make const blocks easier to use; a block being const |
|
117 // doesn't prevent modifying its list state. |
|
118 mutable const Block* _prev; |
|
119 mutable const Block* _next; |
|
120 |
|
121 // Noncopyable. |
|
122 BlockEntry(const BlockEntry&); |
|
123 BlockEntry& operator=(const BlockEntry&); |
|
124 |
|
125 public: |
|
126 BlockEntry(); |
|
127 ~BlockEntry(); |
|
128 }; |
|
129 |
|
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. |
|
132 // Non-full blocks are in the storage's _allocate_list, linked through the |
|
133 // block's _allocate_entry. Empty blocks are at the end of that list. |
37 class OopStorage::Block /* No base class, to avoid messing up alignment. */ { |
134 class OopStorage::Block /* No base class, to avoid messing up alignment. */ { |
38 // _data must be the first non-static data member, for alignment. |
135 // _data must be the first non-static data member, for alignment. |
39 oop _data[BitsPerWord]; |
136 oop _data[BitsPerWord]; |
40 static const unsigned _data_pos = 0; // Position of _data. |
137 static const unsigned _data_pos = 0; // Position of _data. |
41 |
138 |
42 volatile uintx _allocated_bitmask; // One bit per _data element. |
139 volatile uintx _allocated_bitmask; // One bit per _data element. |
43 const OopStorage* _owner; |
140 const OopStorage* _owner; |
44 void* _memory; // Unaligned storage containing block. |
141 void* _memory; // Unaligned storage containing block. |
45 BlockEntry _active_entry; |
142 size_t _active_index; |
46 BlockEntry _allocate_entry; |
143 BlockEntry _allocate_entry; |
47 Block* volatile _deferred_updates_next; |
144 Block* volatile _deferred_updates_next; |
48 volatile uintx _release_refcount; |
145 volatile uintx _release_refcount; |
49 |
146 |
50 Block(const OopStorage* owner, void* memory); |
147 Block(const OopStorage* owner, void* memory); |