< prev index next >

test/hotspot/gtest/gc/shared/test_oopStorage.cpp

Print this page
rev 50951 : imported patch rename_AllocateList
rev 50954 : imported patch rename_allocate_list
rev 50955 : imported patch rename_allocate_mutex


  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());


< prev index next >