94 } |
95 } |
95 |
96 |
96 static size_t memory_per_block() { |
97 static size_t memory_per_block() { |
97 return Block::allocation_size(); |
98 return Block::allocation_size(); |
98 } |
99 } |
|
100 |
|
101 static void block_array_set_block_count(BlockArray* blocks, size_t count) { |
|
102 blocks->_block_count = count; |
|
103 } |
99 }; |
104 }; |
100 |
105 |
101 typedef OopStorage::TestAccess TestAccess; |
106 typedef OopStorage::TestAccess TestAccess; |
102 // --- FIXME: Should be just Block, but that collides with opto Block |
107 |
103 // when building with precompiled headers. There really should be |
108 // The "Oop" prefix is to avoid collision with similar opto names when |
104 // an opto namespace. |
109 // building with precompiled headers, or for consistency with that |
|
110 // workaround. There really should be an opto namespace. |
105 typedef TestAccess::Block OopBlock; |
111 typedef TestAccess::Block OopBlock; |
106 // --- FIXME: Similarly, this typedef collides with opto BlockList. |
112 typedef TestAccess::BlockList OopBlockList; |
107 // typedef TestAccess::BlockList BlockList; |
113 typedef TestAccess::BlockArray OopBlockArray; |
108 |
114 |
109 // Using EXPECT_EQ can't use NULL directly. Otherwise AIX build breaks. |
115 // Using EXPECT_EQ can't use NULL directly. Otherwise AIX build breaks. |
110 const OopBlock* const NULL_BLOCK = NULL; |
116 const OopBlock* const NULL_BLOCK = NULL; |
111 |
117 |
112 static size_t list_length(const TestAccess::BlockList& list) { |
118 static size_t list_length(const OopBlockList& list) { |
113 size_t result = 0; |
119 size_t result = 0; |
114 for (const OopBlock* block = list.chead(); |
120 for (const OopBlock* block = list.chead(); |
115 block != NULL; |
121 block != NULL; |
116 block = list.next(*block)) { |
122 block = list.next(*block)) { |
117 ++result; |
123 ++result; |
118 } |
124 } |
119 return result; |
125 return result; |
120 } |
126 } |
121 |
127 |
122 static void clear_list(TestAccess::BlockList& list) { |
128 static void clear_list(OopBlockList& list) { |
123 OopBlock* next; |
129 OopBlock* next; |
124 for (OopBlock* block = list.head(); block != NULL; block = next) { |
130 for (OopBlock* block = list.head(); block != NULL; block = next) { |
125 next = list.next(*block); |
131 next = list.next(*block); |
126 list.unlink(*block); |
132 list.unlink(*block); |
127 } |
133 } |
128 } |
134 } |
129 |
135 |
130 static bool is_list_empty(const TestAccess::BlockList& list) { |
136 static bool is_list_empty(const OopBlockList& list) { |
131 return list.chead() == NULL; |
137 return list.chead() == NULL; |
132 } |
138 } |
133 |
139 |
134 static bool process_deferred_updates(OopStorage& storage) { |
140 static bool process_deferred_updates(OopStorage& storage) { |
135 MutexLockerEx ml(TestAccess::allocate_mutex(storage), Mutex::_no_safepoint_check_flag); |
141 MutexLockerEx ml(TestAccess::allocate_mutex(storage), Mutex::_no_safepoint_check_flag); |
225 }; |
244 }; |
226 |
245 |
227 static bool is_allocate_list_sorted(const OopStorage& storage) { |
246 static bool is_allocate_list_sorted(const OopStorage& storage) { |
228 // The allocate_list isn't strictly sorted. Rather, all empty |
247 // The allocate_list isn't strictly sorted. Rather, all empty |
229 // blocks are segregated to the end of the list. |
248 // blocks are segregated to the end of the list. |
230 const TestAccess::BlockList& list = TestAccess::allocate_list(storage); |
249 const OopBlockList& list = TestAccess::allocate_list(storage); |
231 const OopBlock* block = list.ctail(); |
250 const OopBlock* block = list.ctail(); |
232 for ( ; (block != NULL) && block->is_empty(); block = list.prev(*block)) {} |
251 for ( ; (block != NULL) && block->is_empty(); block = list.prev(*block)) {} |
233 for ( ; block != NULL; block = list.prev(*block)) { |
252 for ( ; block != NULL; block = list.prev(*block)) { |
234 if (block->is_empty()) { |
253 if (block->is_empty()) { |
235 return false; |
254 return false; |
236 } |
255 } |
237 } |
256 } |
238 return true; |
257 return true; |
239 } |
258 } |
240 |
259 |
241 static size_t total_allocation_count(const TestAccess::BlockList& list) { |
260 static size_t total_allocation_count(const OopStorage& storage) { |
242 size_t total_count = 0; |
261 size_t total_count = 0; |
243 for (const OopBlock* block = list.chead(); |
262 const OopBlockArray& ba = TestAccess::active_array(storage); |
244 block != NULL; |
263 size_t limit = active_count(storage); |
245 block = list.next(*block)) { |
264 for (size_t i = 0; i < limit; ++i) { |
246 total_count += TestAccess::block_allocation_count(*block); |
265 total_count += TestAccess::block_allocation_count(*ba.at(i)); |
247 } |
266 } |
248 return total_count; |
267 return total_count; |
249 } |
268 } |
250 |
269 |
251 TEST_VM_F(OopStorageTest, allocate_one) { |
270 TEST_VM_F(OopStorageTest, allocate_one) { |
252 EXPECT_TRUE(is_list_empty(TestAccess::active_list(_storage))); |
271 EXPECT_EQ(0u, active_count(_storage)); |
253 EXPECT_TRUE(is_list_empty(TestAccess::allocate_list(_storage))); |
272 EXPECT_TRUE(is_list_empty(TestAccess::allocate_list(_storage))); |
254 |
273 |
255 oop* ptr = _storage.allocate(); |
274 oop* ptr = _storage.allocate(); |
256 EXPECT_TRUE(ptr != NULL); |
275 EXPECT_TRUE(ptr != NULL); |
257 EXPECT_EQ(1u, _storage.allocation_count()); |
276 EXPECT_EQ(1u, _storage.allocation_count()); |
258 |
277 |
259 EXPECT_EQ(1u, list_length(TestAccess::active_list(_storage))); |
278 EXPECT_EQ(1u, active_count(_storage)); |
260 EXPECT_EQ(1u, _storage.block_count()); |
279 EXPECT_EQ(1u, _storage.block_count()); |
261 EXPECT_EQ(1u, list_length(TestAccess::allocate_list(_storage))); |
280 EXPECT_EQ(1u, list_length(TestAccess::allocate_list(_storage))); |
262 |
281 |
263 EXPECT_EQ(0u, empty_block_count(_storage)); |
282 EXPECT_EQ(0u, empty_block_count(_storage)); |
264 |
283 |
265 const OopBlock* block = TestAccess::allocate_list(_storage).chead(); |
284 const OopBlock* block = TestAccess::allocate_list(_storage).chead(); |
266 EXPECT_NE(block, (OopBlock*)NULL); |
285 EXPECT_NE(block, (OopBlock*)NULL); |
267 EXPECT_EQ(block, (TestAccess::active_list(_storage).chead())); |
286 EXPECT_EQ(block, active_head(_storage)); |
268 EXPECT_FALSE(TestAccess::block_is_empty(*block)); |
287 EXPECT_FALSE(TestAccess::block_is_empty(*block)); |
269 EXPECT_FALSE(TestAccess::block_is_full(*block)); |
288 EXPECT_FALSE(TestAccess::block_is_full(*block)); |
270 EXPECT_EQ(1u, TestAccess::block_allocation_count(*block)); |
289 EXPECT_EQ(1u, TestAccess::block_allocation_count(*block)); |
271 |
290 |
272 release_entry(_storage, ptr); |
291 release_entry(_storage, ptr); |
273 EXPECT_EQ(0u, _storage.allocation_count()); |
292 EXPECT_EQ(0u, _storage.allocation_count()); |
274 |
293 |
275 EXPECT_EQ(1u, list_length(TestAccess::active_list(_storage))); |
294 EXPECT_EQ(1u, active_count(_storage)); |
276 EXPECT_EQ(1u, _storage.block_count()); |
295 EXPECT_EQ(1u, _storage.block_count()); |
277 EXPECT_EQ(1u, list_length(TestAccess::allocate_list(_storage))); |
296 EXPECT_EQ(1u, list_length(TestAccess::allocate_list(_storage))); |
278 |
297 |
279 EXPECT_EQ(1u, empty_block_count(_storage)); |
298 EXPECT_EQ(1u, empty_block_count(_storage)); |
280 |
299 |
281 const OopBlock* new_block = TestAccess::allocate_list(_storage).chead(); |
300 const OopBlock* new_block = TestAccess::allocate_list(_storage).chead(); |
282 EXPECT_EQ(block, new_block); |
301 EXPECT_EQ(block, new_block); |
283 EXPECT_EQ(block, (TestAccess::active_list(_storage).chead())); |
302 EXPECT_EQ(block, active_head(_storage)); |
284 EXPECT_TRUE(TestAccess::block_is_empty(*block)); |
303 EXPECT_TRUE(TestAccess::block_is_empty(*block)); |
285 EXPECT_FALSE(TestAccess::block_is_full(*block)); |
304 EXPECT_FALSE(TestAccess::block_is_full(*block)); |
286 EXPECT_EQ(0u, TestAccess::block_allocation_count(*block)); |
305 EXPECT_EQ(0u, TestAccess::block_allocation_count(*block)); |
287 } |
306 } |
288 |
307 |
289 TEST_VM_F(OopStorageTest, allocation_count) { |
308 TEST_VM_F(OopStorageTest, allocation_count) { |
290 static const size_t max_entries = 1000; |
309 static const size_t max_entries = 1000; |
291 oop* entries[max_entries]; |
310 oop* entries[max_entries]; |
292 |
311 |
293 TestAccess::BlockList& active_list = TestAccess::active_list(_storage); |
312 OopBlockList& allocate_list = TestAccess::allocate_list(_storage); |
294 TestAccess::BlockList& allocate_list = TestAccess::allocate_list(_storage); |
313 |
295 |
314 EXPECT_EQ(0u, active_count(_storage)); |
296 EXPECT_TRUE(is_list_empty(active_list)); |
|
297 EXPECT_EQ(0u, _storage.block_count()); |
315 EXPECT_EQ(0u, _storage.block_count()); |
298 EXPECT_TRUE(is_list_empty(allocate_list)); |
316 EXPECT_TRUE(is_list_empty(allocate_list)); |
299 |
317 |
300 size_t allocated = 0; |
318 size_t allocated = 0; |
301 for ( ; allocated < max_entries; ++allocated) { |
319 for ( ; allocated < max_entries; ++allocated) { |
302 EXPECT_EQ(allocated, _storage.allocation_count()); |
320 EXPECT_EQ(allocated, _storage.allocation_count()); |
303 if (!is_list_empty(active_list)) { |
321 if (active_count(_storage) != 0) { |
304 EXPECT_EQ(1u, list_length(active_list)); |
322 EXPECT_EQ(1u, active_count(_storage)); |
305 EXPECT_EQ(1u, _storage.block_count()); |
323 EXPECT_EQ(1u, _storage.block_count()); |
306 const OopBlock& block = *active_list.chead(); |
324 const OopBlock& block = *TestAccess::active_array(_storage).at(0); |
307 EXPECT_EQ(allocated, TestAccess::block_allocation_count(block)); |
325 EXPECT_EQ(allocated, TestAccess::block_allocation_count(block)); |
308 if (TestAccess::block_is_full(block)) { |
326 if (TestAccess::block_is_full(block)) { |
309 break; |
327 break; |
310 } else { |
328 } else { |
311 EXPECT_FALSE(is_list_empty(allocate_list)); |
329 EXPECT_FALSE(is_list_empty(allocate_list)); |
334 |
352 |
335 TEST_VM_F(OopStorageTest, allocate_many) { |
353 TEST_VM_F(OopStorageTest, allocate_many) { |
336 static const size_t max_entries = 1000; |
354 static const size_t max_entries = 1000; |
337 oop* entries[max_entries]; |
355 oop* entries[max_entries]; |
338 |
356 |
339 TestAccess::BlockList& active_list = TestAccess::active_list(_storage); |
357 OopBlockList& allocate_list = TestAccess::allocate_list(_storage); |
340 TestAccess::BlockList& allocate_list = TestAccess::allocate_list(_storage); |
|
341 |
358 |
342 EXPECT_EQ(0u, empty_block_count(_storage)); |
359 EXPECT_EQ(0u, empty_block_count(_storage)); |
343 |
360 |
344 entries[0] = _storage.allocate(); |
361 entries[0] = _storage.allocate(); |
345 ASSERT_TRUE(entries[0] != NULL); |
362 ASSERT_TRUE(entries[0] != NULL); |
346 EXPECT_EQ(1u, list_length(active_list)); |
363 EXPECT_EQ(1u, active_count(_storage)); |
347 EXPECT_EQ(1u, _storage.block_count()); |
364 EXPECT_EQ(1u, _storage.block_count()); |
348 EXPECT_EQ(1u, list_length(allocate_list)); |
365 EXPECT_EQ(1u, list_length(allocate_list)); |
349 EXPECT_EQ(0u, empty_block_count(_storage)); |
366 EXPECT_EQ(0u, empty_block_count(_storage)); |
350 |
367 |
351 const OopBlock* block = active_list.chead(); |
368 const OopBlock* block = TestAccess::active_array(_storage).at(0); |
352 EXPECT_EQ(1u, TestAccess::block_allocation_count(*block)); |
369 EXPECT_EQ(1u, TestAccess::block_allocation_count(*block)); |
353 EXPECT_EQ(block, allocate_list.chead()); |
370 EXPECT_EQ(block, allocate_list.chead()); |
354 |
371 |
355 for (size_t i = 1; i < max_entries; ++i) { |
372 for (size_t i = 1; i < max_entries; ++i) { |
356 entries[i] = _storage.allocate(); |
373 entries[i] = _storage.allocate(); |
361 if (block == NULL) { |
378 if (block == NULL) { |
362 ASSERT_FALSE(is_list_empty(allocate_list)); |
379 ASSERT_FALSE(is_list_empty(allocate_list)); |
363 EXPECT_EQ(1u, list_length(allocate_list)); |
380 EXPECT_EQ(1u, list_length(allocate_list)); |
364 block = allocate_list.chead(); |
381 block = allocate_list.chead(); |
365 EXPECT_EQ(1u, TestAccess::block_allocation_count(*block)); |
382 EXPECT_EQ(1u, TestAccess::block_allocation_count(*block)); |
366 EXPECT_EQ(block, active_list.chead()); |
383 EXPECT_EQ(block, active_head(_storage)); |
367 } else if (TestAccess::block_is_full(*block)) { |
384 } else if (TestAccess::block_is_full(*block)) { |
368 EXPECT_TRUE(is_list_empty(allocate_list)); |
385 EXPECT_TRUE(is_list_empty(allocate_list)); |
369 block = NULL; |
386 block = NULL; |
370 } else { |
387 } else { |
371 EXPECT_FALSE(is_list_empty(allocate_list)); |
388 EXPECT_FALSE(is_list_empty(allocate_list)); |
372 EXPECT_EQ(block, allocate_list.chead()); |
389 EXPECT_EQ(block, allocate_list.chead()); |
373 EXPECT_EQ(block, active_list.chead()); |
390 EXPECT_EQ(block, active_head(_storage)); |
374 } |
391 } |
375 } |
392 } |
376 |
393 |
377 if (block != NULL) { |
394 if (block != NULL) { |
378 EXPECT_NE(0u, TestAccess::block_allocation_count(*block)); |
395 EXPECT_NE(0u, TestAccess::block_allocation_count(*block)); |
379 EXPECT_FALSE(is_list_empty(allocate_list)); |
396 EXPECT_FALSE(is_list_empty(allocate_list)); |
380 EXPECT_EQ(block, allocate_list.chead()); |
397 EXPECT_EQ(block, allocate_list.chead()); |
381 EXPECT_EQ(block, active_list.chead()); |
398 EXPECT_EQ(block, active_head(_storage)); |
382 } |
399 } |
383 |
|
384 size_t active_count = list_length(active_list); |
|
385 |
400 |
386 for (size_t i = 0; i < max_entries; ++i) { |
401 for (size_t i = 0; i < max_entries; ++i) { |
387 release_entry(_storage, entries[i]); |
402 release_entry(_storage, entries[i]); |
388 EXPECT_TRUE(is_allocate_list_sorted(_storage)); |
403 EXPECT_TRUE(is_allocate_list_sorted(_storage)); |
389 EXPECT_EQ(max_entries - (i + 1), total_allocation_count(active_list)); |
404 EXPECT_EQ(max_entries - (i + 1), total_allocation_count(_storage)); |
390 } |
405 } |
391 |
406 |
392 EXPECT_EQ(list_length(active_list), list_length(allocate_list)); |
407 EXPECT_EQ(active_count(_storage), list_length(allocate_list)); |
393 EXPECT_EQ(list_length(active_list), _storage.block_count()); |
408 EXPECT_EQ(active_count(_storage), _storage.block_count()); |
394 EXPECT_EQ(list_length(active_list), empty_block_count(_storage)); |
409 EXPECT_EQ(active_count(_storage), empty_block_count(_storage)); |
395 for (const OopBlock* block = allocate_list.chead(); |
410 for (const OopBlock* block = allocate_list.chead(); |
396 block != NULL; |
411 block != NULL; |
397 block = allocate_list.next(*block)) { |
412 block = allocate_list.next(*block)) { |
398 EXPECT_TRUE(TestAccess::block_is_empty(*block)); |
413 EXPECT_TRUE(TestAccess::block_is_empty(*block)); |
399 } |
414 } |
403 static const size_t step = 11; |
418 static const size_t step = 11; |
404 ASSERT_NE(0u, _max_entries % step); // max_entries and step are mutually prime |
419 ASSERT_NE(0u, _max_entries % step); // max_entries and step are mutually prime |
405 |
420 |
406 EXPECT_EQ(0u, empty_block_count(_storage)); |
421 EXPECT_EQ(0u, empty_block_count(_storage)); |
407 |
422 |
408 TestAccess::BlockList& active_list = TestAccess::active_list(_storage); |
423 OopBlockList& allocate_list = TestAccess::allocate_list(_storage); |
409 TestAccess::BlockList& allocate_list = TestAccess::allocate_list(_storage); |
424 |
410 |
425 EXPECT_EQ(_max_entries, total_allocation_count(_storage)); |
411 EXPECT_EQ(_max_entries, total_allocation_count(active_list)); |
|
412 EXPECT_GE(1u, list_length(allocate_list)); |
426 EXPECT_GE(1u, list_length(allocate_list)); |
413 |
427 |
414 // Release all entries in "random" order. |
428 // Release all entries in "random" order. |
415 size_t released = 0; |
429 size_t released = 0; |
416 for (size_t i = 0; released < _max_entries; i = (i + step) % _max_entries) { |
430 for (size_t i = 0; released < _max_entries; i = (i + step) % _max_entries) { |
417 if (_entries[i] != NULL) { |
431 if (_entries[i] != NULL) { |
418 release_entry(_storage, _entries[i]); |
432 release_entry(_storage, _entries[i]); |
419 _entries[i] = NULL; |
433 _entries[i] = NULL; |
420 ++released; |
434 ++released; |
421 EXPECT_EQ(_max_entries - released, total_allocation_count(active_list)); |
435 EXPECT_EQ(_max_entries - released, total_allocation_count(_storage)); |
422 EXPECT_TRUE(is_allocate_list_sorted(_storage)); |
436 EXPECT_TRUE(is_allocate_list_sorted(_storage)); |
423 } |
437 } |
424 } |
438 } |
425 |
439 |
426 EXPECT_EQ(list_length(active_list), list_length(allocate_list)); |
440 EXPECT_EQ(active_count(_storage), list_length(allocate_list)); |
427 EXPECT_EQ(list_length(active_list), _storage.block_count()); |
441 EXPECT_EQ(active_count(_storage), _storage.block_count()); |
428 EXPECT_EQ(0u, total_allocation_count(active_list)); |
442 EXPECT_EQ(0u, total_allocation_count(_storage)); |
429 EXPECT_EQ(list_length(allocate_list), empty_block_count(_storage)); |
443 EXPECT_EQ(list_length(allocate_list), empty_block_count(_storage)); |
430 } |
444 } |
431 |
445 |
432 TEST_VM_F(OopStorageTestWithAllocation, random_allocate_release) { |
446 TEST_VM_F(OopStorageTestWithAllocation, random_allocate_release) { |
433 static const size_t release_step = 11; |
447 static const size_t release_step = 11; |
434 static const size_t allocate_step = 5; |
448 static const size_t allocate_step = 5; |
435 ASSERT_NE(0u, _max_entries % release_step); // max_entries and step are mutually prime |
449 ASSERT_NE(0u, _max_entries % release_step); // max_entries and step are mutually prime |
436 |
450 |
437 EXPECT_EQ(0u, empty_block_count(_storage)); |
451 EXPECT_EQ(0u, empty_block_count(_storage)); |
438 |
452 |
439 TestAccess::BlockList& active_list = TestAccess::active_list(_storage); |
453 OopBlockList& allocate_list = TestAccess::allocate_list(_storage); |
440 TestAccess::BlockList& allocate_list = TestAccess::allocate_list(_storage); |
454 |
441 |
455 EXPECT_EQ(_max_entries, total_allocation_count(_storage)); |
442 EXPECT_EQ(_max_entries, total_allocation_count(active_list)); |
|
443 EXPECT_GE(1u, list_length(allocate_list)); |
456 EXPECT_GE(1u, list_length(allocate_list)); |
444 |
457 |
445 // Release all entries in "random" order, "randomly" interspersed |
458 // Release all entries in "random" order, "randomly" interspersed |
446 // with additional allocations. |
459 // with additional allocations. |
447 size_t released = 0; |
460 size_t released = 0; |
450 if (_entries[i] != NULL) { |
463 if (_entries[i] != NULL) { |
451 release_entry(_storage, _entries[i]); |
464 release_entry(_storage, _entries[i]); |
452 _entries[i] = NULL; |
465 _entries[i] = NULL; |
453 ++released; |
466 ++released; |
454 ++total_released; |
467 ++total_released; |
455 EXPECT_EQ(_max_entries - released, total_allocation_count(active_list)); |
468 EXPECT_EQ(_max_entries - released, total_allocation_count(_storage)); |
456 EXPECT_TRUE(is_allocate_list_sorted(_storage)); |
469 EXPECT_TRUE(is_allocate_list_sorted(_storage)); |
457 if (total_released % allocate_step == 0) { |
470 if (total_released % allocate_step == 0) { |
458 _entries[i] = _storage.allocate(); |
471 _entries[i] = _storage.allocate(); |
459 --released; |
472 --released; |
460 EXPECT_EQ(_max_entries - released, total_allocation_count(active_list)); |
473 EXPECT_EQ(_max_entries - released, total_allocation_count(_storage)); |
461 EXPECT_TRUE(is_allocate_list_sorted(_storage)); |
474 EXPECT_TRUE(is_allocate_list_sorted(_storage)); |
462 } |
475 } |
463 } |
476 } |
464 } |
477 } |
465 |
478 |
466 EXPECT_EQ(list_length(active_list), list_length(allocate_list)); |
479 EXPECT_EQ(active_count(_storage), list_length(allocate_list)); |
467 EXPECT_EQ(list_length(active_list), _storage.block_count()); |
480 EXPECT_EQ(active_count(_storage), _storage.block_count()); |
468 EXPECT_EQ(0u, total_allocation_count(active_list)); |
481 EXPECT_EQ(0u, total_allocation_count(_storage)); |
469 EXPECT_EQ(list_length(allocate_list), empty_block_count(_storage)); |
482 EXPECT_EQ(list_length(allocate_list), empty_block_count(_storage)); |
470 } |
483 } |
471 |
484 |
472 template<bool sorted> |
485 template<bool sorted> |
473 class OopStorageTestBlockRelease : public OopStorageTestWithAllocation { |
486 class OopStorageTestBlockRelease : public OopStorageTestWithAllocation { |
1013 workers()->run_task(&task); |
1026 workers()->run_task(&task); |
1014 vstate.check(); |
1027 vstate.check(); |
1015 } |
1028 } |
1016 |
1029 |
1017 TEST_VM_F(OopStorageTestWithAllocation, delete_empty_blocks_safepoint) { |
1030 TEST_VM_F(OopStorageTestWithAllocation, delete_empty_blocks_safepoint) { |
1018 TestAccess::BlockList& active_list = TestAccess::active_list(_storage); |
1031 size_t initial_active_size = active_count(_storage); |
1019 |
|
1020 size_t initial_active_size = list_length(active_list); |
|
1021 EXPECT_EQ(initial_active_size, _storage.block_count()); |
1032 EXPECT_EQ(initial_active_size, _storage.block_count()); |
1022 ASSERT_LE(3u, initial_active_size); // Need at least 3 blocks for test |
1033 ASSERT_LE(3u, initial_active_size); // Need at least 3 blocks for test |
1023 |
1034 |
1024 for (size_t i = 0; empty_block_count(_storage) < 3; ++i) { |
1035 for (size_t i = 0; empty_block_count(_storage) < 3; ++i) { |
1025 ASSERT_GT(_max_entries, i); |
1036 ASSERT_GT(_max_entries, i); |
1026 release_entry(_storage, _entries[i]); |
1037 release_entry(_storage, _entries[i]); |
1027 } |
1038 } |
1028 |
1039 |
1029 EXPECT_EQ(initial_active_size, list_length(active_list)); |
1040 EXPECT_EQ(initial_active_size, active_count(_storage)); |
1030 EXPECT_EQ(initial_active_size, _storage.block_count()); |
1041 EXPECT_EQ(initial_active_size, _storage.block_count()); |
1031 EXPECT_EQ(3u, empty_block_count(_storage)); |
1042 EXPECT_EQ(3u, empty_block_count(_storage)); |
1032 |
1043 |
1033 { |
1044 { |
1034 ThreadInVMfromNative invm(JavaThread::current()); |
1045 ThreadInVMfromNative invm(JavaThread::current()); |
1035 VM_DeleteBlocksAtSafepoint op(&_storage); |
1046 VM_DeleteBlocksAtSafepoint op(&_storage); |
1036 VMThread::execute(&op); |
1047 VMThread::execute(&op); |
1037 } |
1048 } |
1038 EXPECT_EQ(0u, empty_block_count(_storage)); |
1049 EXPECT_EQ(0u, empty_block_count(_storage)); |
1039 EXPECT_EQ(initial_active_size - 3, list_length(active_list)); |
1050 EXPECT_EQ(initial_active_size - 3, active_count(_storage)); |
1040 EXPECT_EQ(initial_active_size - 3, _storage.block_count()); |
1051 EXPECT_EQ(initial_active_size - 3, _storage.block_count()); |
1041 } |
1052 } |
1042 |
1053 |
1043 TEST_VM_F(OopStorageTestWithAllocation, delete_empty_blocks_concurrent) { |
1054 TEST_VM_F(OopStorageTestWithAllocation, delete_empty_blocks_concurrent) { |
1044 TestAccess::BlockList& active_list = TestAccess::active_list(_storage); |
1055 size_t initial_active_size = active_count(_storage); |
1045 |
|
1046 size_t initial_active_size = list_length(active_list); |
|
1047 EXPECT_EQ(initial_active_size, _storage.block_count()); |
1056 EXPECT_EQ(initial_active_size, _storage.block_count()); |
1048 ASSERT_LE(3u, initial_active_size); // Need at least 3 blocks for test |
1057 ASSERT_LE(3u, initial_active_size); // Need at least 3 blocks for test |
1049 |
1058 |
1050 for (size_t i = 0; empty_block_count(_storage) < 3; ++i) { |
1059 for (size_t i = 0; empty_block_count(_storage) < 3; ++i) { |
1051 ASSERT_GT(_max_entries, i); |
1060 ASSERT_GT(_max_entries, i); |
1052 release_entry(_storage, _entries[i]); |
1061 release_entry(_storage, _entries[i]); |
1053 } |
1062 } |
1054 |
1063 |
1055 EXPECT_EQ(initial_active_size, list_length(active_list)); |
1064 EXPECT_EQ(initial_active_size, active_count(_storage)); |
1056 EXPECT_EQ(initial_active_size, _storage.block_count()); |
1065 EXPECT_EQ(initial_active_size, _storage.block_count()); |
1057 EXPECT_EQ(3u, empty_block_count(_storage)); |
1066 EXPECT_EQ(3u, empty_block_count(_storage)); |
1058 |
1067 |
1059 _storage.delete_empty_blocks_concurrent(); |
1068 _storage.delete_empty_blocks_concurrent(); |
1060 EXPECT_EQ(0u, empty_block_count(_storage)); |
1069 EXPECT_EQ(0u, empty_block_count(_storage)); |
1061 EXPECT_EQ(initial_active_size - 3, list_length(active_list)); |
1070 EXPECT_EQ(initial_active_size - 3, active_count(_storage)); |
1062 EXPECT_EQ(initial_active_size - 3, _storage.block_count()); |
1071 EXPECT_EQ(initial_active_size - 3, _storage.block_count()); |
1063 } |
1072 } |
1064 |
1073 |
1065 TEST_VM_F(OopStorageTestWithAllocation, allocation_status) { |
1074 TEST_VM_F(OopStorageTestWithAllocation, allocation_status) { |
1066 oop* retained = _entries[200]; |
1075 oop* retained = _entries[200]; |
1188 static const OopStorage* pseudo_owner() { |
1195 static const OopStorage* pseudo_owner() { |
1189 return reinterpret_cast<const OopStorage*>(&_pseudo_owner); |
1196 return reinterpret_cast<const OopStorage*>(&_pseudo_owner); |
1190 } |
1197 } |
1191 }; |
1198 }; |
1192 |
1199 |
1193 const size_t OopStorageBlockListTest::nvalues; |
1200 const size_t OopStorageBlockCollectionTest::nvalues; |
1194 const void* const OopStorageBlockListTest::_pseudo_owner[] = {}; |
1201 const void* const OopStorageBlockCollectionTest::_pseudo_owner[] = {}; |
|
1202 |
|
1203 class OopStorageBlockListTest : public OopStorageBlockCollectionTest {}; |
1195 |
1204 |
1196 TEST_F(OopStorageBlockListTest, empty_list) { |
1205 TEST_F(OopStorageBlockListTest, empty_list) { |
1197 TestAccess::BlockList list(&OopBlock::get_active_entry); |
1206 OopBlockList list(&OopBlock::get_allocate_entry); |
1198 |
1207 |
1199 EXPECT_TRUE(is_list_empty(list)); |
1208 EXPECT_TRUE(is_list_empty(list)); |
1200 EXPECT_EQ(NULL_BLOCK, list.head()); |
1209 EXPECT_EQ(NULL_BLOCK, list.head()); |
1201 EXPECT_EQ(NULL_BLOCK, list.chead()); |
1210 EXPECT_EQ(NULL_BLOCK, list.chead()); |
1202 EXPECT_EQ(NULL_BLOCK, list.ctail()); |
1211 EXPECT_EQ(NULL_BLOCK, list.ctail()); |
1203 } |
1212 } |
1204 |
1213 |
1205 TEST_F(OopStorageBlockListTest, push_back) { |
1214 TEST_F(OopStorageBlockListTest, push_back) { |
1206 TestAccess::BlockList list(&OopBlock::get_active_entry); |
1215 OopBlockList list(&OopBlock::get_allocate_entry); |
1207 |
1216 |
1208 for (size_t i = 0; i < nvalues; ++i) { |
1217 for (size_t i = 0; i < nvalues; ++i) { |
1209 list.push_back(*values[i]); |
1218 list.push_back(*values[i]); |
1210 EXPECT_FALSE(is_list_empty(list)); |
1219 EXPECT_FALSE(is_list_empty(list)); |
1211 EXPECT_EQ(list.ctail(), values[i]); |
1220 EXPECT_EQ(list.ctail(), values[i]); |
1349 EXPECT_EQ(NULL_BLOCK, list.prev(*values[0])); |
1358 EXPECT_EQ(NULL_BLOCK, list.prev(*values[0])); |
1350 EXPECT_EQ(NULL_BLOCK, list.chead()); |
1359 EXPECT_EQ(NULL_BLOCK, list.chead()); |
1351 EXPECT_EQ(NULL_BLOCK, list.ctail()); |
1360 EXPECT_EQ(NULL_BLOCK, list.ctail()); |
1352 } |
1361 } |
1353 |
1362 |
1354 TEST_F(OopStorageBlockListTestWithList, two_lists) { |
1363 class OopStorageBlockArrayTest : public OopStorageBlockCollectionTest {}; |
1355 TestAccess::BlockList list2(&OopBlock::get_allocate_entry); |
1364 |
1356 for (size_t i = 0; i < nvalues; ++i) { |
1365 TEST_F(OopStorageBlockArrayTest, empty_array) { |
1357 list2.push_front(*values[i]); |
1366 OopBlockArray* a = OopBlockArray::create(nvalues); |
1358 } |
1367 |
1359 |
1368 EXPECT_EQ(nvalues, a->size()); |
1360 const OopBlock* active_block = list.chead(); |
1369 EXPECT_EQ(0u, a->block_count_acquire()); |
1361 const OopBlock* allocate_block = list2.ctail(); |
1370 TestAccess::block_array_set_block_count(a, 2); |
1362 for (size_t i = 0; i < nvalues; ++i) { |
1371 EXPECT_EQ(2u, a->block_count_acquire()); |
1363 EXPECT_EQ(active_block, allocate_block); |
1372 TestAccess::block_array_set_block_count(a, 0); |
1364 active_block = list.next(*active_block); |
1373 a->increment_refcount(); |
1365 allocate_block = list2.prev(*allocate_block); |
1374 a->increment_refcount(); |
1366 } |
1375 EXPECT_FALSE(a->decrement_refcount()); |
1367 EXPECT_EQ(NULL_BLOCK, active_block); |
1376 EXPECT_TRUE(a->decrement_refcount()); |
1368 EXPECT_EQ(NULL_BLOCK, allocate_block); |
1377 |
1369 |
1378 OopBlockArray::destroy(a); |
1370 for (size_t i = 0; i < nvalues; ++i) { |
1379 } |
1371 list2.unlink(*values[i]); |
1380 |
1372 } |
1381 TEST_F(OopStorageBlockArrayTest, push) { |
1373 EXPECT_TRUE(is_list_empty(list2)); |
1382 OopBlockArray* a = OopBlockArray::create(nvalues - 1); |
1374 |
1383 |
1375 active_block = list.chead(); |
1384 for (size_t i = 0; i < nvalues - 1; ++i) { |
1376 for (size_t i = 0; i < nvalues; ++i) { |
1385 EXPECT_TRUE(a->push(values[i])); |
1377 EXPECT_EQ(active_block, values[i]); |
1386 EXPECT_EQ(i + 1, a->block_count_acquire()); |
1378 active_block = list.next(*active_block); |
1387 EXPECT_EQ(values[i], a->at(i)); |
1379 } |
1388 } |
1380 EXPECT_EQ(NULL_BLOCK, active_block); |
1389 EXPECT_FALSE(a->push(values[nvalues - 1])); |
1381 } |
1390 |
|
1391 TestAccess::block_array_set_block_count(a, 0); |
|
1392 OopBlockArray::destroy(a); |
|
1393 } |
|
1394 |
|
1395 class OopStorageBlockArrayTestWithArray : public OopStorageBlockArrayTest { |
|
1396 public: |
|
1397 OopStorageBlockArrayTestWithArray() : a(OopBlockArray::create(nvalues)) { |
|
1398 for (size_t i = 0; i < nvalues; ++i) { |
|
1399 a->push(values[i]); |
|
1400 } |
|
1401 } |
|
1402 |
|
1403 ~OopStorageBlockArrayTestWithArray() { |
|
1404 TestAccess::block_array_set_block_count(a, 0); |
|
1405 OopBlockArray::destroy(a); |
|
1406 } |
|
1407 |
|
1408 OopBlockArray* a; |
|
1409 }; |
|
1410 |
|
1411 TEST_F(OopStorageBlockArrayTestWithArray, remove0) { |
|
1412 a->remove(values[0]); |
|
1413 EXPECT_EQ(nvalues - 1, a->block_count_acquire()); |
|
1414 EXPECT_EQ(values[nvalues - 1], a->at(0)); |
|
1415 for (size_t i = 1; i < nvalues - 1; ++i) { |
|
1416 EXPECT_EQ(values[i], a->at(i)); |
|
1417 } |
|
1418 } |
|
1419 |
|
1420 TEST_F(OopStorageBlockArrayTestWithArray, remove3) { |
|
1421 a->remove(values[3]); |
|
1422 EXPECT_EQ(nvalues - 1, a->block_count_acquire()); |
|
1423 for (size_t i = 0; i < 3; ++i) { |
|
1424 EXPECT_EQ(values[i], a->at(i)); |
|
1425 } |
|
1426 EXPECT_EQ(values[nvalues - 1], a->at(3)); |
|
1427 for (size_t i = 4; i < nvalues - 1; ++i) { |
|
1428 EXPECT_EQ(values[i], a->at(i)); |
|
1429 } |
|
1430 } |
|
1431 |
|
1432 TEST_F(OopStorageBlockArrayTestWithArray, remove_last) { |
|
1433 a->remove(values[nvalues - 1]); |
|
1434 EXPECT_EQ(nvalues - 1, a->block_count_acquire()); |
|
1435 for (size_t i = 0; i < nvalues - 1; ++i) { |
|
1436 EXPECT_EQ(values[i], a->at(i)); |
|
1437 } |
|
1438 } |