35 #include "runtime/mutexLocker.hpp"
36 #include "runtime/thread.hpp"
37 #include "runtime/vm_operations.hpp"
38 #include "runtime/vmThread.hpp"
39 #include "utilities/align.hpp"
40 #include "utilities/ostream.hpp"
41 #include "utilities/quickSort.hpp"
42 #include "unittest.hpp"
43
44 // --- FIXME: Disable some tests on 32bit Windows, because SafeFetch
45 // (which is used by allocation_status) doesn't currently provide
46 // protection in the context where gtests are run; see JDK-8185734.
47 #ifdef _WIN32
48 #define DISABLE_GARBAGE_ALLOCATION_STATUS_TESTS
49 #endif
50
51 // Access storage internals.
52 class OopStorage::TestAccess : public AllStatic {
53 public:
54 typedef OopStorage::Block Block;
55 typedef OopStorage::AllocateList AllocateList;
56 typedef OopStorage::ActiveArray ActiveArray;
57
58 static ActiveArray& active_array(const OopStorage& storage) {
59 return *storage._active_array;
60 }
61
62 static AllocateList& allocate_list(OopStorage& storage) {
63 return storage._allocate_list;
64 }
65
66 static const AllocateList& allocate_list(const OopStorage& storage) {
67 return storage._allocate_list;
68 }
69
70 static Mutex* allocate_mutex(const OopStorage& storage) {
71 return storage._allocate_mutex;
72 }
73
74 static bool reduce_deferred_updates(OopStorage& storage) {
75 return storage.reduce_deferred_updates();
76 }
77
78 static bool block_is_empty(const Block& block) {
79 return block.is_empty();
80 }
81
82 static bool block_is_full(const Block& block) {
83 return block.is_full();
84 }
85
86 static unsigned block_allocation_count(const Block& block) {
87 uintx bitmask = block.allocated_bitmask();
88 unsigned count = 0;
89 for ( ; bitmask != 0; bitmask >>= 1) {
90 if ((bitmask & 1) != 0) {
91 ++count;
92 }
93 }
94 return count;
95 }
96
97 static size_t memory_per_block() {
98 return Block::allocation_size();
99 }
100
101 static void block_array_set_block_count(ActiveArray* blocks, size_t count) {
102 blocks->_block_count = count;
103 }
104 };
105
106 typedef OopStorage::TestAccess TestAccess;
107
108 // The "Oop" prefix is to avoid collision with similar opto names when
109 // building with precompiled headers, or for consistency with that
110 // workaround. There really should be an opto namespace.
111 typedef TestAccess::Block OopBlock;
112 typedef TestAccess::AllocateList AllocateList;
113 typedef TestAccess::ActiveArray ActiveArray;
114
115 // Using EXPECT_EQ can't use NULL directly. Otherwise AIX build breaks.
116 const OopBlock* const NULL_BLOCK = NULL;
117
118 static size_t list_length(const AllocateList& list) {
119 size_t result = 0;
120 for (const OopBlock* block = list.chead();
121 block != NULL;
122 block = list.next(*block)) {
123 ++result;
124 }
125 return result;
126 }
127
128 static void clear_list(AllocateList& list) {
129 OopBlock* next;
130 for (OopBlock* block = list.head(); block != NULL; block = next) {
131 next = list.next(*block);
132 list.unlink(*block);
133 }
134 }
135
136 static bool is_list_empty(const AllocateList& list) {
137 return list.chead() == NULL;
138 }
139
140 static bool process_deferred_updates(OopStorage& storage) {
141 MutexLockerEx ml(TestAccess::allocate_mutex(storage), Mutex::_no_safepoint_check_flag);
142 bool result = false;
143 while (TestAccess::reduce_deferred_updates(storage)) {
144 result = true;
145 }
146 return result;
147 }
148
149 static void release_entry(OopStorage& storage, oop* entry, bool process_deferred = true) {
150 *entry = NULL;
151 storage.release(entry);
152 if (process_deferred) {
153 process_deferred_updates(storage);
154 }
155 }
156
157 static size_t empty_block_count(const OopStorage& storage) {
158 const AllocateList& list = TestAccess::allocate_list(storage);
159 size_t count = 0;
160 for (const OopBlock* block = list.ctail();
161 (block != NULL) && block->is_empty();
162 ++count, block = list.prev(*block))
163 {}
164 return count;
165 }
166
167 static size_t active_count(const OopStorage& storage) {
168 return TestAccess::active_array(storage).block_count();
169 }
170
171 static OopBlock* active_head(const OopStorage& storage) {
172 ActiveArray& ba = TestAccess::active_array(storage);
173 size_t count = ba.block_count();
174 if (count == 0) {
175 return NULL;
176 } else {
177 return ba.at(count - 1);
178 }
179 }
180
181 class OopStorageTest : public ::testing::Test {
182 public:
183 OopStorageTest();
184 ~OopStorageTest();
185
186 Mutex _allocate_mutex;
187 Mutex _active_mutex;
188 OopStorage _storage;
189
190 static const int _active_rank = Mutex::leaf - 1;
191 static const int _allocate_rank = Mutex::leaf;
192
193 class CountingIterateClosure;
194 template<bool is_const> class VM_CountAtSafepoint;
195 };
196
197 OopStorageTest::OopStorageTest() :
198 _allocate_mutex(_allocate_rank,
199 "test_OopStorage_allocate",
200 false,
201 Mutex::_safepoint_check_never),
202 _active_mutex(_active_rank,
203 "test_OopStorage_active",
204 false,
205 Mutex::_safepoint_check_never),
206 _storage("Test Storage", &_allocate_mutex, &_active_mutex)
207 { }
208
209 OopStorageTest::~OopStorageTest() {
210 clear_list(TestAccess::allocate_list(_storage));
211 }
212
213 class OopStorageTestWithAllocation : public OopStorageTest {
214 public:
215 OopStorageTestWithAllocation();
216
217 static const size_t _max_entries = 1000;
218 oop* _entries[_max_entries];
219
220 class VM_DeleteBlocksAtSafepoint;
221 };
222
223 OopStorageTestWithAllocation::OopStorageTestWithAllocation() {
224 for (size_t i = 0; i < _max_entries; ++i) {
225 _entries[i] = _storage.allocate();
226 EXPECT_TRUE(_entries[i] != NULL);
227 EXPECT_EQ(i + 1, _storage.allocation_count());
228 }
229 };
230
231 const size_t OopStorageTestWithAllocation::_max_entries;
232
233 class OopStorageTestWithAllocation::VM_DeleteBlocksAtSafepoint
234 : public VM_GTestExecuteAtSafepoint {
235 public:
236 VM_DeleteBlocksAtSafepoint(OopStorage* storage) : _storage(storage) {}
237
238 void doit() {
239 _storage->delete_empty_blocks_safepoint();
240 }
241
242 private:
243 OopStorage* _storage;
244 };
245
246 static bool is_allocate_list_sorted(const OopStorage& storage) {
247 // The allocate_list isn't strictly sorted. Rather, all empty
248 // blocks are segregated to the end of the list.
249 const AllocateList& list = TestAccess::allocate_list(storage);
250 const OopBlock* block = list.ctail();
251 for ( ; (block != NULL) && block->is_empty(); block = list.prev(*block)) {}
252 for ( ; block != NULL; block = list.prev(*block)) {
253 if (block->is_empty()) {
254 return false;
255 }
256 }
257 return true;
258 }
259
260 static size_t total_allocation_count(const OopStorage& storage) {
261 size_t total_count = 0;
262 const ActiveArray& ba = TestAccess::active_array(storage);
263 size_t limit = active_count(storage);
264 for (size_t i = 0; i < limit; ++i) {
265 total_count += TestAccess::block_allocation_count(*ba.at(i));
266 }
267 return total_count;
268 }
269
270 TEST_VM_F(OopStorageTest, allocate_one) {
271 EXPECT_EQ(0u, active_count(_storage));
272 EXPECT_TRUE(is_list_empty(TestAccess::allocate_list(_storage)));
273
274 oop* ptr = _storage.allocate();
275 EXPECT_TRUE(ptr != NULL);
276 EXPECT_EQ(1u, _storage.allocation_count());
277
278 EXPECT_EQ(1u, active_count(_storage));
279 EXPECT_EQ(1u, _storage.block_count());
280 EXPECT_EQ(1u, list_length(TestAccess::allocate_list(_storage)));
281
282 EXPECT_EQ(0u, empty_block_count(_storage));
283
284 const OopBlock* block = TestAccess::allocate_list(_storage).chead();
285 EXPECT_NE(block, (OopBlock*)NULL);
286 EXPECT_EQ(block, active_head(_storage));
287 EXPECT_FALSE(TestAccess::block_is_empty(*block));
288 EXPECT_FALSE(TestAccess::block_is_full(*block));
289 EXPECT_EQ(1u, TestAccess::block_allocation_count(*block));
290
291 release_entry(_storage, ptr);
292 EXPECT_EQ(0u, _storage.allocation_count());
293
294 EXPECT_EQ(1u, active_count(_storage));
295 EXPECT_EQ(1u, _storage.block_count());
296 EXPECT_EQ(1u, list_length(TestAccess::allocate_list(_storage)));
297
298 EXPECT_EQ(1u, empty_block_count(_storage));
299
300 const OopBlock* new_block = TestAccess::allocate_list(_storage).chead();
301 EXPECT_EQ(block, new_block);
302 EXPECT_EQ(block, active_head(_storage));
303 EXPECT_TRUE(TestAccess::block_is_empty(*block));
304 EXPECT_FALSE(TestAccess::block_is_full(*block));
305 EXPECT_EQ(0u, TestAccess::block_allocation_count(*block));
306 }
307
308 TEST_VM_F(OopStorageTest, allocation_count) {
309 static const size_t max_entries = 1000;
310 oop* entries[max_entries];
311
312 AllocateList& allocate_list = TestAccess::allocate_list(_storage);
313
314 EXPECT_EQ(0u, active_count(_storage));
315 EXPECT_EQ(0u, _storage.block_count());
316 EXPECT_TRUE(is_list_empty(allocate_list));
317
318 size_t allocated = 0;
319 for ( ; allocated < max_entries; ++allocated) {
320 EXPECT_EQ(allocated, _storage.allocation_count());
321 if (active_count(_storage) != 0) {
322 EXPECT_EQ(1u, active_count(_storage));
323 EXPECT_EQ(1u, _storage.block_count());
324 const OopBlock& block = *TestAccess::active_array(_storage).at(0);
325 EXPECT_EQ(allocated, TestAccess::block_allocation_count(block));
326 if (TestAccess::block_is_full(block)) {
327 break;
328 } else {
329 EXPECT_FALSE(is_list_empty(allocate_list));
330 EXPECT_EQ(&block, allocate_list.chead());
331 }
332 }
333 entries[allocated] = _storage.allocate();
334 }
335
336 EXPECT_EQ(allocated, _storage.allocation_count());
337 EXPECT_EQ(1u, active_count(_storage));
338 EXPECT_EQ(1u, _storage.block_count());
339 EXPECT_TRUE(is_list_empty(allocate_list));
340 const OopBlock& block = *TestAccess::active_array(_storage).at(0);
341 EXPECT_TRUE(TestAccess::block_is_full(block));
342 EXPECT_EQ(allocated, TestAccess::block_allocation_count(block));
343
344 for (size_t i = 0; i < allocated; ++i) {
345 release_entry(_storage, entries[i]);
346 size_t remaining = allocated - (i + 1);
347 EXPECT_EQ(remaining, TestAccess::block_allocation_count(block));
348 EXPECT_EQ(remaining, _storage.allocation_count());
349 EXPECT_FALSE(is_list_empty(allocate_list));
350 }
351 }
352
353 TEST_VM_F(OopStorageTest, allocate_many) {
354 static const size_t max_entries = 1000;
355 oop* entries[max_entries];
356
357 AllocateList& allocate_list = TestAccess::allocate_list(_storage);
358
359 EXPECT_EQ(0u, empty_block_count(_storage));
360
361 entries[0] = _storage.allocate();
362 ASSERT_TRUE(entries[0] != NULL);
363 EXPECT_EQ(1u, active_count(_storage));
364 EXPECT_EQ(1u, _storage.block_count());
365 EXPECT_EQ(1u, list_length(allocate_list));
366 EXPECT_EQ(0u, empty_block_count(_storage));
367
368 const OopBlock* block = TestAccess::active_array(_storage).at(0);
369 EXPECT_EQ(1u, TestAccess::block_allocation_count(*block));
370 EXPECT_EQ(block, allocate_list.chead());
371
372 for (size_t i = 1; i < max_entries; ++i) {
373 entries[i] = _storage.allocate();
374 EXPECT_EQ(i + 1, _storage.allocation_count());
375 ASSERT_TRUE(entries[i] != NULL);
376 EXPECT_EQ(0u, empty_block_count(_storage));
377
378 if (block == NULL) {
379 ASSERT_FALSE(is_list_empty(allocate_list));
380 EXPECT_EQ(1u, list_length(allocate_list));
381 block = allocate_list.chead();
382 EXPECT_EQ(1u, TestAccess::block_allocation_count(*block));
383 EXPECT_EQ(block, active_head(_storage));
384 } else if (TestAccess::block_is_full(*block)) {
385 EXPECT_TRUE(is_list_empty(allocate_list));
386 block = NULL;
387 } else {
388 EXPECT_FALSE(is_list_empty(allocate_list));
389 EXPECT_EQ(block, allocate_list.chead());
390 EXPECT_EQ(block, active_head(_storage));
391 }
392 }
393
394 if (block != NULL) {
395 EXPECT_NE(0u, TestAccess::block_allocation_count(*block));
396 EXPECT_FALSE(is_list_empty(allocate_list));
397 EXPECT_EQ(block, allocate_list.chead());
398 EXPECT_EQ(block, active_head(_storage));
399 }
400
401 for (size_t i = 0; i < max_entries; ++i) {
402 release_entry(_storage, entries[i]);
403 EXPECT_TRUE(is_allocate_list_sorted(_storage));
404 EXPECT_EQ(max_entries - (i + 1), total_allocation_count(_storage));
405 }
406
407 EXPECT_EQ(active_count(_storage), list_length(allocate_list));
408 EXPECT_EQ(active_count(_storage), _storage.block_count());
409 EXPECT_EQ(active_count(_storage), empty_block_count(_storage));
410 for (const OopBlock* block = allocate_list.chead();
411 block != NULL;
412 block = allocate_list.next(*block)) {
413 EXPECT_TRUE(TestAccess::block_is_empty(*block));
414 }
415 }
416
417 TEST_VM_F(OopStorageTestWithAllocation, random_release) {
418 static const size_t step = 11;
419 ASSERT_NE(0u, _max_entries % step); // max_entries and step are mutually prime
420
421 EXPECT_EQ(0u, empty_block_count(_storage));
422
423 AllocateList& allocate_list = TestAccess::allocate_list(_storage);
424
425 EXPECT_EQ(_max_entries, total_allocation_count(_storage));
426 EXPECT_GE(1u, list_length(allocate_list));
427
428 // Release all entries in "random" order.
429 size_t released = 0;
430 for (size_t i = 0; released < _max_entries; i = (i + step) % _max_entries) {
431 if (_entries[i] != NULL) {
432 release_entry(_storage, _entries[i]);
433 _entries[i] = NULL;
434 ++released;
435 EXPECT_EQ(_max_entries - released, total_allocation_count(_storage));
436 EXPECT_TRUE(is_allocate_list_sorted(_storage));
437 }
438 }
439
440 EXPECT_EQ(active_count(_storage), list_length(allocate_list));
441 EXPECT_EQ(active_count(_storage), _storage.block_count());
442 EXPECT_EQ(0u, total_allocation_count(_storage));
443 EXPECT_EQ(list_length(allocate_list), empty_block_count(_storage));
444 }
445
446 TEST_VM_F(OopStorageTestWithAllocation, random_allocate_release) {
447 static const size_t release_step = 11;
448 static const size_t allocate_step = 5;
449 ASSERT_NE(0u, _max_entries % release_step); // max_entries and step are mutually prime
450
451 EXPECT_EQ(0u, empty_block_count(_storage));
452
453 AllocateList& allocate_list = TestAccess::allocate_list(_storage);
454
455 EXPECT_EQ(_max_entries, total_allocation_count(_storage));
456 EXPECT_GE(1u, list_length(allocate_list));
457
458 // Release all entries in "random" order, "randomly" interspersed
459 // with additional allocations.
460 size_t released = 0;
461 size_t total_released = 0;
462 for (size_t i = 0; released < _max_entries; i = (i + release_step) % _max_entries) {
463 if (_entries[i] != NULL) {
464 release_entry(_storage, _entries[i]);
465 _entries[i] = NULL;
466 ++released;
467 ++total_released;
468 EXPECT_EQ(_max_entries - released, total_allocation_count(_storage));
469 EXPECT_TRUE(is_allocate_list_sorted(_storage));
470 if (total_released % allocate_step == 0) {
471 _entries[i] = _storage.allocate();
472 --released;
473 EXPECT_EQ(_max_entries - released, total_allocation_count(_storage));
474 EXPECT_TRUE(is_allocate_list_sorted(_storage));
475 }
476 }
477 }
478
479 EXPECT_EQ(active_count(_storage), list_length(allocate_list));
480 EXPECT_EQ(active_count(_storage), _storage.block_count());
481 EXPECT_EQ(0u, total_allocation_count(_storage));
482 EXPECT_EQ(list_length(allocate_list), empty_block_count(_storage));
483 }
484
485 template<bool sorted>
486 class OopStorageTestBlockRelease : public OopStorageTestWithAllocation {
487 public:
488 void SetUp() {
489 size_t nrelease = _max_entries / 2;
490 oop** to_release = NEW_C_HEAP_ARRAY(oop*, nrelease, mtInternal);
491
492 for (size_t i = 0; i < nrelease; ++i) {
493 to_release[i] = _entries[2 * i];
494 *to_release[i] = NULL;
495 }
496 if (sorted) {
497 QuickSort::sort(to_release, nrelease, PointerCompare(), false);
498 }
499
500 _storage.release(to_release, nrelease);
501 EXPECT_EQ(_max_entries - nrelease, _storage.allocation_count());
502
1183 OopBlock::delete_block(*values[i]);
1184 }
1185 }
1186
1187 public:
1188 static const size_t nvalues = 10;
1189 OopBlock* values[nvalues];
1190
1191 private:
1192 // The only thing we actually care about is the address of the owner.
1193 static const size_t pseudo_owner_size = sizeof(OopStorage) / sizeof(void*);
1194 static const void* const _pseudo_owner[pseudo_owner_size];
1195 static const OopStorage* pseudo_owner() {
1196 return reinterpret_cast<const OopStorage*>(&_pseudo_owner);
1197 }
1198 };
1199
1200 const size_t OopStorageBlockCollectionTest::nvalues;
1201 const void* const OopStorageBlockCollectionTest::_pseudo_owner[] = {};
1202
1203 class OopStorageAllocateListTest : public OopStorageBlockCollectionTest {};
1204
1205 TEST_F(OopStorageAllocateListTest, empty_list) {
1206 AllocateList list;
1207
1208 EXPECT_TRUE(is_list_empty(list));
1209 EXPECT_EQ(NULL_BLOCK, list.head());
1210 EXPECT_EQ(NULL_BLOCK, list.chead());
1211 EXPECT_EQ(NULL_BLOCK, list.ctail());
1212 }
1213
1214 TEST_F(OopStorageAllocateListTest, push_back) {
1215 AllocateList list;
1216
1217 for (size_t i = 0; i < nvalues; ++i) {
1218 list.push_back(*values[i]);
1219 EXPECT_FALSE(is_list_empty(list));
1220 EXPECT_EQ(list.ctail(), values[i]);
1221 }
1222
1223 EXPECT_EQ(list.chead(), list.head());
1224 EXPECT_EQ(list.chead(), values[0]);
1225 EXPECT_EQ(list.ctail(), values[nvalues - 1]);
1226
1227 const OopBlock* block = list.chead();
1228 for (size_t i = 0; i < nvalues; ++i) {
1229 EXPECT_EQ(block, values[i]);
1230 block = list.next(*block);
1231 }
1232 EXPECT_EQ(NULL_BLOCK, block);
1233
1234 block = list.ctail();
1235 for (size_t i = 0; i < nvalues; ++i) {
1236 EXPECT_EQ(block, values[nvalues - i - 1]);
1237 block = list.prev(*block);
1238 }
1239 EXPECT_EQ(NULL_BLOCK, block);
1240
1241 clear_list(list);
1242 }
1243
1244 TEST_F(OopStorageAllocateListTest, push_front) {
1245 AllocateList list;
1246
1247 for (size_t i = 0; i < nvalues; ++i) {
1248 list.push_front(*values[i]);
1249 EXPECT_FALSE(is_list_empty(list));
1250 EXPECT_EQ(list.head(), values[i]);
1251 }
1252
1253 EXPECT_EQ(list.chead(), list.head());
1254 EXPECT_EQ(list.chead(), values[nvalues - 1]);
1255 EXPECT_EQ(list.ctail(), values[0]);
1256
1257 const OopBlock* block = list.chead();
1258 for (size_t i = 0; i < nvalues; ++i) {
1259 EXPECT_EQ(block, values[nvalues - i - 1]);
1260 block = list.next(*block);
1261 }
1262 EXPECT_EQ(NULL_BLOCK, block);
1263
1264 block = list.ctail();
1265 for (size_t i = 0; i < nvalues; ++i) {
1266 EXPECT_EQ(block, values[i]);
1267 block = list.prev(*block);
1268 }
1269 EXPECT_EQ(NULL_BLOCK, block);
1270
1271 clear_list(list);
1272 }
1273
1274 class OopStorageAllocateListTestWithList : public OopStorageAllocateListTest {
1275 public:
1276 OopStorageAllocateListTestWithList() : list() {
1277 for (size_t i = 0; i < nvalues; ++i) {
1278 list.push_back(*values[i]);
1279 }
1280 }
1281
1282 ~OopStorageAllocateListTestWithList() {
1283 clear_list(list);
1284 }
1285
1286 AllocateList list;
1287 };
1288
1289 TEST_F(OopStorageAllocateListTestWithList, unlink_front) {
1290 EXPECT_EQ(list.chead(), values[0]);
1291 EXPECT_EQ(list.ctail(), values[nvalues - 1]);
1292
1293 list.unlink(*values[0]);
1294 EXPECT_EQ(NULL_BLOCK, list.next(*values[0]));
1295 EXPECT_EQ(NULL_BLOCK, list.prev(*values[0]));
1296 EXPECT_EQ(list.chead(), values[1]);
1297 EXPECT_EQ(list.ctail(), values[nvalues - 1]);
1298
1299 const OopBlock* block = list.chead();
1300 for (size_t i = 1; i < nvalues; ++i) {
1301 EXPECT_EQ(block, values[i]);
1302 block = list.next(*block);
1303 }
1304 EXPECT_EQ(NULL_BLOCK, block);
1305 }
1306
1307 TEST_F(OopStorageAllocateListTestWithList, unlink_back) {
1308 EXPECT_EQ(list.chead(), values[0]);
1309
1310 list.unlink(*values[nvalues - 1]);
1311 EXPECT_EQ(NULL_BLOCK, list.next(*values[nvalues - 1]));
1312 EXPECT_EQ(NULL_BLOCK, list.prev(*values[nvalues - 1]));
1313 EXPECT_EQ(list.chead(), values[0]);
1314 EXPECT_EQ(list.ctail(), values[nvalues - 2]);
1315
1316 const OopBlock* block = list.chead();
1317 for (size_t i = 0; i < nvalues - 1; ++i) {
1318 EXPECT_EQ(block, values[i]);
1319 block = list.next(*block);
1320 }
1321 EXPECT_EQ(NULL_BLOCK, block);
1322 }
1323
1324 TEST_F(OopStorageAllocateListTestWithList, unlink_middle) {
1325 EXPECT_EQ(list.chead(), values[0]);
1326
1327 size_t index = nvalues / 2;
1328
1329 list.unlink(*values[index]);
1330 EXPECT_EQ(NULL_BLOCK, list.next(*values[index]));
1331 EXPECT_EQ(NULL_BLOCK, list.prev(*values[index]));
1332 EXPECT_EQ(list.chead(), values[0]);
1333 EXPECT_EQ(list.ctail(), values[nvalues - 1]);
1334
1335 const OopBlock* block = list.chead();
1336 for (size_t i = 0; i < index; ++i) {
1337 EXPECT_EQ(block, values[i]);
1338 block = list.next(*block);
1339 }
1340 for (size_t i = index + 1; i < nvalues; ++i) {
1341 EXPECT_EQ(block, values[i]);
1342 block = list.next(*block);
1343 }
1344 EXPECT_EQ(NULL_BLOCK, block);
1345 }
1346
1347 TEST_F(OopStorageAllocateListTest, single) {
1348 AllocateList list;
1349
1350 list.push_back(*values[0]);
1351 EXPECT_EQ(NULL_BLOCK, list.next(*values[0]));
1352 EXPECT_EQ(NULL_BLOCK, list.prev(*values[0]));
1353 EXPECT_EQ(list.chead(), values[0]);
1354 EXPECT_EQ(list.ctail(), values[0]);
1355
1356 list.unlink(*values[0]);
1357 EXPECT_EQ(NULL_BLOCK, list.next(*values[0]));
1358 EXPECT_EQ(NULL_BLOCK, list.prev(*values[0]));
1359 EXPECT_EQ(NULL_BLOCK, list.chead());
1360 EXPECT_EQ(NULL_BLOCK, list.ctail());
1361 }
1362
1363 class OopStorageActiveArrayTest : public OopStorageBlockCollectionTest {};
1364
1365 TEST_F(OopStorageActiveArrayTest, empty_array) {
1366 ActiveArray* a = ActiveArray::create(nvalues);
1367
1368 EXPECT_EQ(nvalues, a->size());
|
35 #include "runtime/mutexLocker.hpp"
36 #include "runtime/thread.hpp"
37 #include "runtime/vm_operations.hpp"
38 #include "runtime/vmThread.hpp"
39 #include "utilities/align.hpp"
40 #include "utilities/ostream.hpp"
41 #include "utilities/quickSort.hpp"
42 #include "unittest.hpp"
43
44 // --- FIXME: Disable some tests on 32bit Windows, because SafeFetch
45 // (which is used by allocation_status) doesn't currently provide
46 // protection in the context where gtests are run; see JDK-8185734.
47 #ifdef _WIN32
48 #define DISABLE_GARBAGE_ALLOCATION_STATUS_TESTS
49 #endif
50
51 // Access storage internals.
52 class OopStorage::TestAccess : public AllStatic {
53 public:
54 typedef OopStorage::Block Block;
55 typedef OopStorage::AllocationList AllocationList;
56 typedef OopStorage::ActiveArray ActiveArray;
57
58 static ActiveArray& active_array(const OopStorage& storage) {
59 return *storage._active_array;
60 }
61
62 static AllocationList& allocation_list(OopStorage& storage) {
63 return storage._allocation_list;
64 }
65
66 static const AllocationList& allocation_list(const OopStorage& storage) {
67 return storage._allocation_list;
68 }
69
70 static Mutex* allocation_mutex(const OopStorage& storage) {
71 return storage._allocation_mutex;
72 }
73
74 static bool reduce_deferred_updates(OopStorage& storage) {
75 return storage.reduce_deferred_updates();
76 }
77
78 static bool block_is_empty(const Block& block) {
79 return block.is_empty();
80 }
81
82 static bool block_is_full(const Block& block) {
83 return block.is_full();
84 }
85
86 static unsigned block_allocation_count(const Block& block) {
87 uintx bitmask = block.allocated_bitmask();
88 unsigned count = 0;
89 for ( ; bitmask != 0; bitmask >>= 1) {
90 if ((bitmask & 1) != 0) {
91 ++count;
92 }
93 }
94 return count;
95 }
96
97 static size_t memory_per_block() {
98 return Block::allocation_size();
99 }
100
101 static void block_array_set_block_count(ActiveArray* blocks, size_t count) {
102 blocks->_block_count = count;
103 }
104 };
105
106 typedef OopStorage::TestAccess TestAccess;
107
108 // The "Oop" prefix is to avoid collision with similar opto names when
109 // building with precompiled headers, or for consistency with that
110 // workaround. There really should be an opto namespace.
111 typedef TestAccess::Block OopBlock;
112 typedef TestAccess::AllocationList AllocationList;
113 typedef TestAccess::ActiveArray ActiveArray;
114
115 // Using EXPECT_EQ can't use NULL directly. Otherwise AIX build breaks.
116 const OopBlock* const NULL_BLOCK = NULL;
117
118 static size_t list_length(const AllocationList& list) {
119 size_t result = 0;
120 for (const OopBlock* block = list.chead();
121 block != NULL;
122 block = list.next(*block)) {
123 ++result;
124 }
125 return result;
126 }
127
128 static void clear_list(AllocationList& list) {
129 OopBlock* next;
130 for (OopBlock* block = list.head(); block != NULL; block = next) {
131 next = list.next(*block);
132 list.unlink(*block);
133 }
134 }
135
136 static bool is_list_empty(const AllocationList& list) {
137 return list.chead() == NULL;
138 }
139
140 static bool process_deferred_updates(OopStorage& storage) {
141 MutexLockerEx ml(TestAccess::allocation_mutex(storage), Mutex::_no_safepoint_check_flag);
142 bool result = false;
143 while (TestAccess::reduce_deferred_updates(storage)) {
144 result = true;
145 }
146 return result;
147 }
148
149 static void release_entry(OopStorage& storage, oop* entry, bool process_deferred = true) {
150 *entry = NULL;
151 storage.release(entry);
152 if (process_deferred) {
153 process_deferred_updates(storage);
154 }
155 }
156
157 static size_t empty_block_count(const OopStorage& storage) {
158 const AllocationList& list = TestAccess::allocation_list(storage);
159 size_t count = 0;
160 for (const OopBlock* block = list.ctail();
161 (block != NULL) && block->is_empty();
162 ++count, block = list.prev(*block))
163 {}
164 return count;
165 }
166
167 static size_t active_count(const OopStorage& storage) {
168 return TestAccess::active_array(storage).block_count();
169 }
170
171 static OopBlock* active_head(const OopStorage& storage) {
172 ActiveArray& ba = TestAccess::active_array(storage);
173 size_t count = ba.block_count();
174 if (count == 0) {
175 return NULL;
176 } else {
177 return ba.at(count - 1);
178 }
179 }
180
181 class OopStorageTest : public ::testing::Test {
182 public:
183 OopStorageTest();
184 ~OopStorageTest();
185
186 Mutex _allocation_mutex;
187 Mutex _active_mutex;
188 OopStorage _storage;
189
190 static const int _active_rank = Mutex::leaf - 1;
191 static const int _allocate_rank = Mutex::leaf;
192
193 class CountingIterateClosure;
194 template<bool is_const> class VM_CountAtSafepoint;
195 };
196
197 OopStorageTest::OopStorageTest() :
198 _allocation_mutex(_allocate_rank,
199 "test_OopStorage_allocation",
200 false,
201 Mutex::_safepoint_check_never),
202 _active_mutex(_active_rank,
203 "test_OopStorage_active",
204 false,
205 Mutex::_safepoint_check_never),
206 _storage("Test Storage", &_allocation_mutex, &_active_mutex)
207 { }
208
209 OopStorageTest::~OopStorageTest() {
210 clear_list(TestAccess::allocation_list(_storage));
211 }
212
213 class OopStorageTestWithAllocation : public OopStorageTest {
214 public:
215 OopStorageTestWithAllocation();
216
217 static const size_t _max_entries = 1000;
218 oop* _entries[_max_entries];
219
220 class VM_DeleteBlocksAtSafepoint;
221 };
222
223 OopStorageTestWithAllocation::OopStorageTestWithAllocation() {
224 for (size_t i = 0; i < _max_entries; ++i) {
225 _entries[i] = _storage.allocate();
226 EXPECT_TRUE(_entries[i] != NULL);
227 EXPECT_EQ(i + 1, _storage.allocation_count());
228 }
229 };
230
231 const size_t OopStorageTestWithAllocation::_max_entries;
232
233 class OopStorageTestWithAllocation::VM_DeleteBlocksAtSafepoint
234 : public VM_GTestExecuteAtSafepoint {
235 public:
236 VM_DeleteBlocksAtSafepoint(OopStorage* storage) : _storage(storage) {}
237
238 void doit() {
239 _storage->delete_empty_blocks_safepoint();
240 }
241
242 private:
243 OopStorage* _storage;
244 };
245
246 static bool is_allocation_list_sorted(const OopStorage& storage) {
247 // The allocation_list isn't strictly sorted. Rather, all empty
248 // blocks are segregated to the end of the list.
249 const AllocationList& list = TestAccess::allocation_list(storage);
250 const OopBlock* block = list.ctail();
251 for ( ; (block != NULL) && block->is_empty(); block = list.prev(*block)) {}
252 for ( ; block != NULL; block = list.prev(*block)) {
253 if (block->is_empty()) {
254 return false;
255 }
256 }
257 return true;
258 }
259
260 static size_t total_allocation_count(const OopStorage& storage) {
261 size_t total_count = 0;
262 const ActiveArray& ba = TestAccess::active_array(storage);
263 size_t limit = active_count(storage);
264 for (size_t i = 0; i < limit; ++i) {
265 total_count += TestAccess::block_allocation_count(*ba.at(i));
266 }
267 return total_count;
268 }
269
270 TEST_VM_F(OopStorageTest, allocate_one) {
271 EXPECT_EQ(0u, active_count(_storage));
272 EXPECT_TRUE(is_list_empty(TestAccess::allocation_list(_storage)));
273
274 oop* ptr = _storage.allocate();
275 EXPECT_TRUE(ptr != NULL);
276 EXPECT_EQ(1u, _storage.allocation_count());
277
278 EXPECT_EQ(1u, active_count(_storage));
279 EXPECT_EQ(1u, _storage.block_count());
280 EXPECT_EQ(1u, list_length(TestAccess::allocation_list(_storage)));
281
282 EXPECT_EQ(0u, empty_block_count(_storage));
283
284 const OopBlock* block = TestAccess::allocation_list(_storage).chead();
285 EXPECT_NE(block, (OopBlock*)NULL);
286 EXPECT_EQ(block, active_head(_storage));
287 EXPECT_FALSE(TestAccess::block_is_empty(*block));
288 EXPECT_FALSE(TestAccess::block_is_full(*block));
289 EXPECT_EQ(1u, TestAccess::block_allocation_count(*block));
290
291 release_entry(_storage, ptr);
292 EXPECT_EQ(0u, _storage.allocation_count());
293
294 EXPECT_EQ(1u, active_count(_storage));
295 EXPECT_EQ(1u, _storage.block_count());
296 EXPECT_EQ(1u, list_length(TestAccess::allocation_list(_storage)));
297
298 EXPECT_EQ(1u, empty_block_count(_storage));
299
300 const OopBlock* new_block = TestAccess::allocation_list(_storage).chead();
301 EXPECT_EQ(block, new_block);
302 EXPECT_EQ(block, active_head(_storage));
303 EXPECT_TRUE(TestAccess::block_is_empty(*block));
304 EXPECT_FALSE(TestAccess::block_is_full(*block));
305 EXPECT_EQ(0u, TestAccess::block_allocation_count(*block));
306 }
307
308 TEST_VM_F(OopStorageTest, allocation_count) {
309 static const size_t max_entries = 1000;
310 oop* entries[max_entries];
311
312 AllocationList& allocation_list = TestAccess::allocation_list(_storage);
313
314 EXPECT_EQ(0u, active_count(_storage));
315 EXPECT_EQ(0u, _storage.block_count());
316 EXPECT_TRUE(is_list_empty(allocation_list));
317
318 size_t allocated = 0;
319 for ( ; allocated < max_entries; ++allocated) {
320 EXPECT_EQ(allocated, _storage.allocation_count());
321 if (active_count(_storage) != 0) {
322 EXPECT_EQ(1u, active_count(_storage));
323 EXPECT_EQ(1u, _storage.block_count());
324 const OopBlock& block = *TestAccess::active_array(_storage).at(0);
325 EXPECT_EQ(allocated, TestAccess::block_allocation_count(block));
326 if (TestAccess::block_is_full(block)) {
327 break;
328 } else {
329 EXPECT_FALSE(is_list_empty(allocation_list));
330 EXPECT_EQ(&block, allocation_list.chead());
331 }
332 }
333 entries[allocated] = _storage.allocate();
334 }
335
336 EXPECT_EQ(allocated, _storage.allocation_count());
337 EXPECT_EQ(1u, active_count(_storage));
338 EXPECT_EQ(1u, _storage.block_count());
339 EXPECT_TRUE(is_list_empty(allocation_list));
340 const OopBlock& block = *TestAccess::active_array(_storage).at(0);
341 EXPECT_TRUE(TestAccess::block_is_full(block));
342 EXPECT_EQ(allocated, TestAccess::block_allocation_count(block));
343
344 for (size_t i = 0; i < allocated; ++i) {
345 release_entry(_storage, entries[i]);
346 size_t remaining = allocated - (i + 1);
347 EXPECT_EQ(remaining, TestAccess::block_allocation_count(block));
348 EXPECT_EQ(remaining, _storage.allocation_count());
349 EXPECT_FALSE(is_list_empty(allocation_list));
350 }
351 }
352
353 TEST_VM_F(OopStorageTest, allocate_many) {
354 static const size_t max_entries = 1000;
355 oop* entries[max_entries];
356
357 AllocationList& allocation_list = TestAccess::allocation_list(_storage);
358
359 EXPECT_EQ(0u, empty_block_count(_storage));
360
361 entries[0] = _storage.allocate();
362 ASSERT_TRUE(entries[0] != NULL);
363 EXPECT_EQ(1u, active_count(_storage));
364 EXPECT_EQ(1u, _storage.block_count());
365 EXPECT_EQ(1u, list_length(allocation_list));
366 EXPECT_EQ(0u, empty_block_count(_storage));
367
368 const OopBlock* block = TestAccess::active_array(_storage).at(0);
369 EXPECT_EQ(1u, TestAccess::block_allocation_count(*block));
370 EXPECT_EQ(block, allocation_list.chead());
371
372 for (size_t i = 1; i < max_entries; ++i) {
373 entries[i] = _storage.allocate();
374 EXPECT_EQ(i + 1, _storage.allocation_count());
375 ASSERT_TRUE(entries[i] != NULL);
376 EXPECT_EQ(0u, empty_block_count(_storage));
377
378 if (block == NULL) {
379 ASSERT_FALSE(is_list_empty(allocation_list));
380 EXPECT_EQ(1u, list_length(allocation_list));
381 block = allocation_list.chead();
382 EXPECT_EQ(1u, TestAccess::block_allocation_count(*block));
383 EXPECT_EQ(block, active_head(_storage));
384 } else if (TestAccess::block_is_full(*block)) {
385 EXPECT_TRUE(is_list_empty(allocation_list));
386 block = NULL;
387 } else {
388 EXPECT_FALSE(is_list_empty(allocation_list));
389 EXPECT_EQ(block, allocation_list.chead());
390 EXPECT_EQ(block, active_head(_storage));
391 }
392 }
393
394 if (block != NULL) {
395 EXPECT_NE(0u, TestAccess::block_allocation_count(*block));
396 EXPECT_FALSE(is_list_empty(allocation_list));
397 EXPECT_EQ(block, allocation_list.chead());
398 EXPECT_EQ(block, active_head(_storage));
399 }
400
401 for (size_t i = 0; i < max_entries; ++i) {
402 release_entry(_storage, entries[i]);
403 EXPECT_TRUE(is_allocation_list_sorted(_storage));
404 EXPECT_EQ(max_entries - (i + 1), total_allocation_count(_storage));
405 }
406
407 EXPECT_EQ(active_count(_storage), list_length(allocation_list));
408 EXPECT_EQ(active_count(_storage), _storage.block_count());
409 EXPECT_EQ(active_count(_storage), empty_block_count(_storage));
410 for (const OopBlock* block = allocation_list.chead();
411 block != NULL;
412 block = allocation_list.next(*block)) {
413 EXPECT_TRUE(TestAccess::block_is_empty(*block));
414 }
415 }
416
417 TEST_VM_F(OopStorageTestWithAllocation, random_release) {
418 static const size_t step = 11;
419 ASSERT_NE(0u, _max_entries % step); // max_entries and step are mutually prime
420
421 EXPECT_EQ(0u, empty_block_count(_storage));
422
423 AllocationList& allocation_list = TestAccess::allocation_list(_storage);
424
425 EXPECT_EQ(_max_entries, total_allocation_count(_storage));
426 EXPECT_GE(1u, list_length(allocation_list));
427
428 // Release all entries in "random" order.
429 size_t released = 0;
430 for (size_t i = 0; released < _max_entries; i = (i + step) % _max_entries) {
431 if (_entries[i] != NULL) {
432 release_entry(_storage, _entries[i]);
433 _entries[i] = NULL;
434 ++released;
435 EXPECT_EQ(_max_entries - released, total_allocation_count(_storage));
436 EXPECT_TRUE(is_allocation_list_sorted(_storage));
437 }
438 }
439
440 EXPECT_EQ(active_count(_storage), list_length(allocation_list));
441 EXPECT_EQ(active_count(_storage), _storage.block_count());
442 EXPECT_EQ(0u, total_allocation_count(_storage));
443 EXPECT_EQ(list_length(allocation_list), empty_block_count(_storage));
444 }
445
446 TEST_VM_F(OopStorageTestWithAllocation, random_allocate_release) {
447 static const size_t release_step = 11;
448 static const size_t allocate_step = 5;
449 ASSERT_NE(0u, _max_entries % release_step); // max_entries and step are mutually prime
450
451 EXPECT_EQ(0u, empty_block_count(_storage));
452
453 AllocationList& allocation_list = TestAccess::allocation_list(_storage);
454
455 EXPECT_EQ(_max_entries, total_allocation_count(_storage));
456 EXPECT_GE(1u, list_length(allocation_list));
457
458 // Release all entries in "random" order, "randomly" interspersed
459 // with additional allocations.
460 size_t released = 0;
461 size_t total_released = 0;
462 for (size_t i = 0; released < _max_entries; i = (i + release_step) % _max_entries) {
463 if (_entries[i] != NULL) {
464 release_entry(_storage, _entries[i]);
465 _entries[i] = NULL;
466 ++released;
467 ++total_released;
468 EXPECT_EQ(_max_entries - released, total_allocation_count(_storage));
469 EXPECT_TRUE(is_allocation_list_sorted(_storage));
470 if (total_released % allocate_step == 0) {
471 _entries[i] = _storage.allocate();
472 --released;
473 EXPECT_EQ(_max_entries - released, total_allocation_count(_storage));
474 EXPECT_TRUE(is_allocation_list_sorted(_storage));
475 }
476 }
477 }
478
479 EXPECT_EQ(active_count(_storage), list_length(allocation_list));
480 EXPECT_EQ(active_count(_storage), _storage.block_count());
481 EXPECT_EQ(0u, total_allocation_count(_storage));
482 EXPECT_EQ(list_length(allocation_list), empty_block_count(_storage));
483 }
484
485 template<bool sorted>
486 class OopStorageTestBlockRelease : public OopStorageTestWithAllocation {
487 public:
488 void SetUp() {
489 size_t nrelease = _max_entries / 2;
490 oop** to_release = NEW_C_HEAP_ARRAY(oop*, nrelease, mtInternal);
491
492 for (size_t i = 0; i < nrelease; ++i) {
493 to_release[i] = _entries[2 * i];
494 *to_release[i] = NULL;
495 }
496 if (sorted) {
497 QuickSort::sort(to_release, nrelease, PointerCompare(), false);
498 }
499
500 _storage.release(to_release, nrelease);
501 EXPECT_EQ(_max_entries - nrelease, _storage.allocation_count());
502
1183 OopBlock::delete_block(*values[i]);
1184 }
1185 }
1186
1187 public:
1188 static const size_t nvalues = 10;
1189 OopBlock* values[nvalues];
1190
1191 private:
1192 // The only thing we actually care about is the address of the owner.
1193 static const size_t pseudo_owner_size = sizeof(OopStorage) / sizeof(void*);
1194 static const void* const _pseudo_owner[pseudo_owner_size];
1195 static const OopStorage* pseudo_owner() {
1196 return reinterpret_cast<const OopStorage*>(&_pseudo_owner);
1197 }
1198 };
1199
1200 const size_t OopStorageBlockCollectionTest::nvalues;
1201 const void* const OopStorageBlockCollectionTest::_pseudo_owner[] = {};
1202
1203 class OopStorageAllocationListTest : public OopStorageBlockCollectionTest {};
1204
1205 TEST_F(OopStorageAllocationListTest, empty_list) {
1206 AllocationList list;
1207
1208 EXPECT_TRUE(is_list_empty(list));
1209 EXPECT_EQ(NULL_BLOCK, list.head());
1210 EXPECT_EQ(NULL_BLOCK, list.chead());
1211 EXPECT_EQ(NULL_BLOCK, list.ctail());
1212 }
1213
1214 TEST_F(OopStorageAllocationListTest, push_back) {
1215 AllocationList list;
1216
1217 for (size_t i = 0; i < nvalues; ++i) {
1218 list.push_back(*values[i]);
1219 EXPECT_FALSE(is_list_empty(list));
1220 EXPECT_EQ(list.ctail(), values[i]);
1221 }
1222
1223 EXPECT_EQ(list.chead(), list.head());
1224 EXPECT_EQ(list.chead(), values[0]);
1225 EXPECT_EQ(list.ctail(), values[nvalues - 1]);
1226
1227 const OopBlock* block = list.chead();
1228 for (size_t i = 0; i < nvalues; ++i) {
1229 EXPECT_EQ(block, values[i]);
1230 block = list.next(*block);
1231 }
1232 EXPECT_EQ(NULL_BLOCK, block);
1233
1234 block = list.ctail();
1235 for (size_t i = 0; i < nvalues; ++i) {
1236 EXPECT_EQ(block, values[nvalues - i - 1]);
1237 block = list.prev(*block);
1238 }
1239 EXPECT_EQ(NULL_BLOCK, block);
1240
1241 clear_list(list);
1242 }
1243
1244 TEST_F(OopStorageAllocationListTest, push_front) {
1245 AllocationList list;
1246
1247 for (size_t i = 0; i < nvalues; ++i) {
1248 list.push_front(*values[i]);
1249 EXPECT_FALSE(is_list_empty(list));
1250 EXPECT_EQ(list.head(), values[i]);
1251 }
1252
1253 EXPECT_EQ(list.chead(), list.head());
1254 EXPECT_EQ(list.chead(), values[nvalues - 1]);
1255 EXPECT_EQ(list.ctail(), values[0]);
1256
1257 const OopBlock* block = list.chead();
1258 for (size_t i = 0; i < nvalues; ++i) {
1259 EXPECT_EQ(block, values[nvalues - i - 1]);
1260 block = list.next(*block);
1261 }
1262 EXPECT_EQ(NULL_BLOCK, block);
1263
1264 block = list.ctail();
1265 for (size_t i = 0; i < nvalues; ++i) {
1266 EXPECT_EQ(block, values[i]);
1267 block = list.prev(*block);
1268 }
1269 EXPECT_EQ(NULL_BLOCK, block);
1270
1271 clear_list(list);
1272 }
1273
1274 class OopStorageAllocationListTestWithList : public OopStorageAllocationListTest {
1275 public:
1276 OopStorageAllocationListTestWithList() : list() {
1277 for (size_t i = 0; i < nvalues; ++i) {
1278 list.push_back(*values[i]);
1279 }
1280 }
1281
1282 ~OopStorageAllocationListTestWithList() {
1283 clear_list(list);
1284 }
1285
1286 AllocationList list;
1287 };
1288
1289 TEST_F(OopStorageAllocationListTestWithList, unlink_front) {
1290 EXPECT_EQ(list.chead(), values[0]);
1291 EXPECT_EQ(list.ctail(), values[nvalues - 1]);
1292
1293 list.unlink(*values[0]);
1294 EXPECT_EQ(NULL_BLOCK, list.next(*values[0]));
1295 EXPECT_EQ(NULL_BLOCK, list.prev(*values[0]));
1296 EXPECT_EQ(list.chead(), values[1]);
1297 EXPECT_EQ(list.ctail(), values[nvalues - 1]);
1298
1299 const OopBlock* block = list.chead();
1300 for (size_t i = 1; i < nvalues; ++i) {
1301 EXPECT_EQ(block, values[i]);
1302 block = list.next(*block);
1303 }
1304 EXPECT_EQ(NULL_BLOCK, block);
1305 }
1306
1307 TEST_F(OopStorageAllocationListTestWithList, unlink_back) {
1308 EXPECT_EQ(list.chead(), values[0]);
1309
1310 list.unlink(*values[nvalues - 1]);
1311 EXPECT_EQ(NULL_BLOCK, list.next(*values[nvalues - 1]));
1312 EXPECT_EQ(NULL_BLOCK, list.prev(*values[nvalues - 1]));
1313 EXPECT_EQ(list.chead(), values[0]);
1314 EXPECT_EQ(list.ctail(), values[nvalues - 2]);
1315
1316 const OopBlock* block = list.chead();
1317 for (size_t i = 0; i < nvalues - 1; ++i) {
1318 EXPECT_EQ(block, values[i]);
1319 block = list.next(*block);
1320 }
1321 EXPECT_EQ(NULL_BLOCK, block);
1322 }
1323
1324 TEST_F(OopStorageAllocationListTestWithList, unlink_middle) {
1325 EXPECT_EQ(list.chead(), values[0]);
1326
1327 size_t index = nvalues / 2;
1328
1329 list.unlink(*values[index]);
1330 EXPECT_EQ(NULL_BLOCK, list.next(*values[index]));
1331 EXPECT_EQ(NULL_BLOCK, list.prev(*values[index]));
1332 EXPECT_EQ(list.chead(), values[0]);
1333 EXPECT_EQ(list.ctail(), values[nvalues - 1]);
1334
1335 const OopBlock* block = list.chead();
1336 for (size_t i = 0; i < index; ++i) {
1337 EXPECT_EQ(block, values[i]);
1338 block = list.next(*block);
1339 }
1340 for (size_t i = index + 1; i < nvalues; ++i) {
1341 EXPECT_EQ(block, values[i]);
1342 block = list.next(*block);
1343 }
1344 EXPECT_EQ(NULL_BLOCK, block);
1345 }
1346
1347 TEST_F(OopStorageAllocationListTest, single) {
1348 AllocationList list;
1349
1350 list.push_back(*values[0]);
1351 EXPECT_EQ(NULL_BLOCK, list.next(*values[0]));
1352 EXPECT_EQ(NULL_BLOCK, list.prev(*values[0]));
1353 EXPECT_EQ(list.chead(), values[0]);
1354 EXPECT_EQ(list.ctail(), values[0]);
1355
1356 list.unlink(*values[0]);
1357 EXPECT_EQ(NULL_BLOCK, list.next(*values[0]));
1358 EXPECT_EQ(NULL_BLOCK, list.prev(*values[0]));
1359 EXPECT_EQ(NULL_BLOCK, list.chead());
1360 EXPECT_EQ(NULL_BLOCK, list.ctail());
1361 }
1362
1363 class OopStorageActiveArrayTest : public OopStorageBlockCollectionTest {};
1364
1365 TEST_F(OopStorageActiveArrayTest, empty_array) {
1366 ActiveArray* a = ActiveArray::create(nvalues);
1367
1368 EXPECT_EQ(nvalues, a->size());
|