9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 #include "precompiled.hpp"
27 #include "memory/metaspace/chunkManager.hpp"
28 #include "memory/metaspace/counters.hpp"
29 #include "memory/metaspace/metaspaceArena.hpp"
30 #include "memory/metaspace/metaspaceArenaGrowthPolicy.hpp"
31 #include "memory/metaspace/metaspaceSettings.hpp"
32 #include "memory/metaspace/metaspaceStatistics.hpp"
33 #include "runtime/mutexLocker.hpp"
34 #include "utilities/debug.hpp"
35 #include "utilities/globalDefinitions.hpp"
36 //#define LOG_PLEASE
37 #include "metaspaceGtestCommon.hpp"
38 #include "metaspaceGtestContexts.hpp"
39 #include "metaspaceGtestSparseArray.hpp"
40
41 using metaspace::AllocationAlignmentByteSize;
42 using metaspace::ArenaGrowthPolicy;
43 using metaspace::ChunkManager;
44 using metaspace::IntCounter;
45 using metaspace::MemRangeCounter;
46 using metaspace::MetaspaceArena;
47 using metaspace::SizeAtomicCounter;
48 using metaspace::ArenaStats;
49 using metaspace::InUseChunkStats;
50
51 // Little randomness helper
52 static bool fifty_fifty() {
53 return IntRange(100).random_value() < 50;
54 }
55
56 // A MetaspaceArenaTestBed contains a single MetaspaceArena and its lock.
57 // It keeps track of allocations done from this MetaspaceArena.
58 class MetaspaceArenaTestBed : public CHeapObj<mtInternal> {
59
60 MetaspaceArena* _arena;
61
62 const SizeRange _allocation_range;
63 size_t _size_of_last_failed_allocation;
64
65 // We keep track of all allocations done thru the MetaspaceArena to
66 // later check for overwriters.
109 // - if +MetaspaceGuardAllocations, guard costs
110
111 // Since what we deallocated may have been given back to us in a following allocation,
112 // we only know fore sure we allocated what we did not give back.
113 const size_t at_least_allocated = _alloc_count.total_size() - _dealloc_count.total_size();
114
115 // At most we allocated this:
116 const size_t max_word_overhead_per_alloc =
117 4 + (metaspace::Settings::use_allocation_guard() ? 4 : 0);
118 const size_t at_most_allocated = _alloc_count.total_size() + max_word_overhead_per_alloc * _alloc_count.count();
119
120 ASSERT_LE(at_least_allocated, in_use_stats._used_words - stats._free_blocks_word_size);
121 ASSERT_GE(at_most_allocated, in_use_stats._used_words - stats._free_blocks_word_size);
122
123 }
124
125 public:
126
127 MetaspaceArena* arena() { return _arena; }
128
129 MetaspaceArenaTestBed(ChunkManager* cm, const ArenaGrowthPolicy* alloc_sequence,
130 SizeAtomicCounter* used_words_counter, SizeRange allocation_range) :
131 _arena(nullptr),
132 _allocation_range(allocation_range),
133 _size_of_last_failed_allocation(0),
134 _allocations(nullptr),
135 _alloc_count(),
136 _dealloc_count()
137 {
138 _arena = new MetaspaceArena(cm, alloc_sequence, used_words_counter, "gtest-MetaspaceArenaTestBed-sm");
139 }
140
141 ~MetaspaceArenaTestBed() {
142
143 verify_arena_statistics();
144
145 allocation_t* a = _allocations;
146 while (a != nullptr) {
147 allocation_t* b = a->next;
148 a->verify();
149 FREE_C_HEAP_OBJ(a);
150 a = b;
151 }
152
153 DEBUG_ONLY(_arena->verify();)
154
155 // Delete MetaspaceArena. That should clean up all metaspace.
156 delete _arena;
157
158 }
159
160 size_t words_allocated() const { return _alloc_count.total_size(); }
161 int num_allocations() const { return _alloc_count.count(); }
162
163 size_t size_of_last_failed_allocation() const { return _size_of_last_failed_allocation; }
164
165 // Allocate a random amount. Return false if the allocation failed.
166 bool checked_random_allocate() {
167 size_t word_size = 1 + _allocation_range.random_value();
168 MetaWord* p = _arena->allocate(word_size);
169 if (p != nullptr) {
170 EXPECT_TRUE(is_aligned(p, AllocationAlignmentByteSize));
171
172 allocation_t* a = NEW_C_HEAP_OBJ(allocation_t, mtInternal);
173 a->word_size = word_size;
174 a->p = p;
175 a->mark();
176 a->next = _allocations;
177 _allocations = a;
178 _alloc_count.add(word_size);
179 if ((_alloc_count.count() % 20) == 0) {
180 verify_arena_statistics();
181 DEBUG_ONLY(_arena->verify();)
182 }
183 return true;
184 } else {
185 _size_of_last_failed_allocation = word_size;
186 }
187 return false;
188 }
189
190 // Deallocate a random allocation
191 void checked_random_deallocate() {
192 allocation_t* a = _allocations;
193 while (a && a->p != nullptr && os::random() % 10 != 0) {
194 a = a->next;
195 }
196 if (a != nullptr && a->p != nullptr) {
197 a->verify();
198 _arena->deallocate(a->p, a->word_size);
199 _dealloc_count.add(a->word_size);
200 a->p = nullptr; a->word_size = 0;
201 if ((_dealloc_count.count() % 20) == 0) {
202 verify_arena_statistics();
203 DEBUG_ONLY(_arena->verify();)
204 }
205 }
206 }
207
208 }; // End: MetaspaceArenaTestBed
209
210 class MetaspaceArenaTest {
211
212 MetaspaceGtestContext _context;
213
214 SizeAtomicCounter _used_words_counter;
215
216 SparseArray<MetaspaceArenaTestBed*> _testbeds;
217 IntCounter _num_beds;
218
219 //////// Bed creation, destruction ///////
220
221 void create_new_test_bed_at(int slotindex, const ArenaGrowthPolicy* growth_policy, SizeRange allocation_range) {
222 DEBUG_ONLY(_testbeds.check_slot_is_null(slotindex));
223 MetaspaceArenaTestBed* bed = new MetaspaceArenaTestBed(&_context.cm(), growth_policy,
224 &_used_words_counter, allocation_range);
225 _testbeds.set_at(slotindex, bed);
226 _num_beds.increment();
227 }
228
229 void create_random_test_bed_at(int slotindex) {
230 SizeRange allocation_range(1, 100); // randomize too?
231 const ArenaGrowthPolicy* growth_policy = ArenaGrowthPolicy::policy_for_space_type(
232 (fifty_fifty() ? Metaspace::StandardMetaspaceType : Metaspace::ReflectionMetaspaceType),
233 fifty_fifty());
234 create_new_test_bed_at(slotindex, growth_policy, allocation_range);
235 }
236
237 // Randomly create a random test bed at a random slot, and return its slot index
238 // (returns false if we reached max number of test beds)
239 bool create_random_test_bed() {
240 const int slot = _testbeds.random_null_slot_index();
241 if (slot != -1) {
242 create_random_test_bed_at(slot);
243 }
244 return slot;
|
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 #include "precompiled.hpp"
27 #include "memory/metaspace/chunkManager.hpp"
28 #include "memory/metaspace/counters.hpp"
29 #include "memory/metaspace/metablock.hpp"
30 #include "memory/metaspace/metaspaceArena.hpp"
31 #include "memory/metaspace/metaspaceArenaGrowthPolicy.hpp"
32 #include "memory/metaspace/metaspaceContext.hpp"
33 #include "memory/metaspace/metaspaceSettings.hpp"
34 #include "memory/metaspace/metaspaceStatistics.hpp"
35 #include "runtime/mutexLocker.hpp"
36 #include "utilities/debug.hpp"
37 #include "utilities/globalDefinitions.hpp"
38 //#define LOG_PLEASE
39 #include "metaspaceGtestCommon.hpp"
40 #include "metaspaceGtestContexts.hpp"
41 #include "metaspaceGtestSparseArray.hpp"
42
43 using metaspace::AllocationAlignmentByteSize;
44 using metaspace::ArenaGrowthPolicy;
45 using metaspace::ChunkManager;
46 using metaspace::IntCounter;
47 using metaspace::MemRangeCounter;
48 using metaspace::MetaBlock;
49 using metaspace::MetaspaceArena;
50 using metaspace::MetaspaceContext;
51 using metaspace::SizeAtomicCounter;
52 using metaspace::ArenaStats;
53 using metaspace::InUseChunkStats;
54
55 // Little randomness helper
56 static bool fifty_fifty() {
57 return IntRange(100).random_value() < 50;
58 }
59
60 // A MetaspaceArenaTestBed contains a single MetaspaceArena and its lock.
61 // It keeps track of allocations done from this MetaspaceArena.
62 class MetaspaceArenaTestBed : public CHeapObj<mtInternal> {
63
64 MetaspaceArena* _arena;
65
66 const SizeRange _allocation_range;
67 size_t _size_of_last_failed_allocation;
68
69 // We keep track of all allocations done thru the MetaspaceArena to
70 // later check for overwriters.
113 // - if +MetaspaceGuardAllocations, guard costs
114
115 // Since what we deallocated may have been given back to us in a following allocation,
116 // we only know fore sure we allocated what we did not give back.
117 const size_t at_least_allocated = _alloc_count.total_size() - _dealloc_count.total_size();
118
119 // At most we allocated this:
120 const size_t max_word_overhead_per_alloc =
121 4 + (metaspace::Settings::use_allocation_guard() ? 4 : 0);
122 const size_t at_most_allocated = _alloc_count.total_size() + max_word_overhead_per_alloc * _alloc_count.count();
123
124 ASSERT_LE(at_least_allocated, in_use_stats._used_words - stats._free_blocks_word_size);
125 ASSERT_GE(at_most_allocated, in_use_stats._used_words - stats._free_blocks_word_size);
126
127 }
128
129 public:
130
131 MetaspaceArena* arena() { return _arena; }
132
133 MetaspaceArenaTestBed(MetaspaceContext* context, const ArenaGrowthPolicy* growth_policy,
134 size_t allocation_alignment_words, SizeRange allocation_range)
135 : _arena(nullptr)
136 , _allocation_range(allocation_range)
137 , _size_of_last_failed_allocation(0)
138 , _allocations(nullptr)
139 {
140 _arena = new MetaspaceArena(context, growth_policy, Metaspace::min_allocation_alignment_words, "gtest-MetaspaceArenaTestBed-sm");
141 }
142
143 ~MetaspaceArenaTestBed() {
144
145 verify_arena_statistics();
146
147 allocation_t* a = _allocations;
148 while (a != nullptr) {
149 allocation_t* b = a->next;
150 a->verify();
151 FREE_C_HEAP_OBJ(a);
152 a = b;
153 }
154
155 DEBUG_ONLY(_arena->verify();)
156
157 // Delete MetaspaceArena. That should clean up all metaspace.
158 delete _arena;
159
160 }
161
162 size_t words_allocated() const { return _alloc_count.total_size(); }
163 int num_allocations() const { return _alloc_count.count(); }
164
165 size_t size_of_last_failed_allocation() const { return _size_of_last_failed_allocation; }
166
167 // Allocate a random amount. Return false if the allocation failed.
168 bool checked_random_allocate() {
169 size_t word_size = 1 + _allocation_range.random_value();
170 MetaBlock wastage;
171 MetaBlock bl = _arena->allocate(word_size, wastage);
172 // We only expect wastage if either alignment was not met or the chunk remainder
173 // was not large enough.
174 if (wastage.is_nonempty()) {
175 _arena->deallocate(wastage);
176 wastage.reset();
177 }
178 if (bl.is_nonempty()) {
179 EXPECT_TRUE(is_aligned(bl.base(), AllocationAlignmentByteSize));
180
181 allocation_t* a = NEW_C_HEAP_OBJ(allocation_t, mtInternal);
182 a->word_size = word_size;
183 a->p = bl.base();
184 a->mark();
185 a->next = _allocations;
186 _allocations = a;
187 _alloc_count.add(word_size);
188 if ((_alloc_count.count() % 20) == 0) {
189 verify_arena_statistics();
190 DEBUG_ONLY(_arena->verify();)
191 }
192 return true;
193 } else {
194 _size_of_last_failed_allocation = word_size;
195 }
196 return false;
197 }
198
199 // Deallocate a random allocation
200 void checked_random_deallocate() {
201 allocation_t* a = _allocations;
202 while (a && a->p != nullptr && os::random() % 10 != 0) {
203 a = a->next;
204 }
205 if (a != nullptr && a->p != nullptr) {
206 a->verify();
207 _arena->deallocate(MetaBlock(a->p, a->word_size));
208 _dealloc_count.add(a->word_size);
209 a->p = nullptr; a->word_size = 0;
210 if ((_dealloc_count.count() % 20) == 0) {
211 verify_arena_statistics();
212 DEBUG_ONLY(_arena->verify();)
213 }
214 }
215 }
216
217 }; // End: MetaspaceArenaTestBed
218
219 class MetaspaceArenaTest {
220
221 MetaspaceGtestContext _context;
222
223 SizeAtomicCounter _used_words_counter;
224
225 SparseArray<MetaspaceArenaTestBed*> _testbeds;
226 IntCounter _num_beds;
227
228 //////// Bed creation, destruction ///////
229
230 void create_new_test_bed_at(int slotindex, const ArenaGrowthPolicy* growth_policy, SizeRange allocation_range) {
231 DEBUG_ONLY(_testbeds.check_slot_is_null(slotindex));
232 MetaspaceArenaTestBed* bed = new MetaspaceArenaTestBed(_context.context(), growth_policy,
233 Metaspace::min_allocation_alignment_words, allocation_range);
234 _testbeds.set_at(slotindex, bed);
235 _num_beds.increment();
236 }
237
238 void create_random_test_bed_at(int slotindex) {
239 SizeRange allocation_range(1, 100); // randomize too?
240 const ArenaGrowthPolicy* growth_policy = ArenaGrowthPolicy::policy_for_space_type(
241 (fifty_fifty() ? Metaspace::StandardMetaspaceType : Metaspace::ReflectionMetaspaceType),
242 fifty_fifty());
243 create_new_test_bed_at(slotindex, growth_policy, allocation_range);
244 }
245
246 // Randomly create a random test bed at a random slot, and return its slot index
247 // (returns false if we reached max number of test beds)
248 bool create_random_test_bed() {
249 const int slot = _testbeds.random_null_slot_index();
250 if (slot != -1) {
251 create_random_test_bed_at(slot);
252 }
253 return slot;
|