1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 #include "precompiled.hpp"
  25 #include "gc/shared/oopStorage.inline.hpp"
  26 #include "gc/shared/oopStorageParState.inline.hpp"
  27 #include "gc/shared/workgroup.hpp"
  28 #include "memory/allocation.inline.hpp"
  29 #include "memory/resourceArea.hpp"
  30 #include "metaprogramming/conditional.hpp"
  31 #include "metaprogramming/enableIf.hpp"
  32 #include "runtime/handles.inline.hpp"
  33 #include "runtime/interfaceSupport.inline.hpp"
  34 #include "runtime/mutex.hpp"
  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 
 503     for (size_t i = 0; i < nrelease; ++i) {
 504       release_entry(_storage, _entries[2 * i + 1], false);
 505       EXPECT_EQ(_max_entries - nrelease - (i + 1), _storage.allocation_count());
 506     }
 507     EXPECT_TRUE(process_deferred_updates(_storage));
 508 
 509     EXPECT_EQ(_storage.block_count(), empty_block_count(_storage));
 510 
 511     FREE_C_HEAP_ARRAY(oop*, to_release);
 512   }
 513 
 514   struct PointerCompare {
 515     int operator()(const void* p, const void* q) const {
 516       return (p < q) ? -1 : int(p != q);
 517     }
 518   };
 519 };
 520 
 521 typedef OopStorageTestBlockRelease<true> OopStorageTestBlockReleaseSorted;
 522 typedef OopStorageTestBlockRelease<false> OopStorageTestBlockReleaseUnsorted;
 523 
 524 TEST_VM_F(OopStorageTestBlockReleaseSorted, block_release) {}
 525 TEST_VM_F(OopStorageTestBlockReleaseUnsorted, block_release) {}
 526 
 527 #ifndef DISABLE_GARBAGE_ALLOCATION_STATUS_TESTS
 528 TEST_VM_F(OopStorageTest, invalid_pointer) {
 529   {
 530     char* mem = NEW_C_HEAP_ARRAY(char, 1000, mtInternal);
 531     oop* ptr = reinterpret_cast<oop*>(align_down(mem + 250, sizeof(oop)));
 532     // Predicate returns false for some malloc'ed block.
 533     EXPECT_EQ(OopStorage::INVALID_ENTRY, _storage.allocation_status(ptr));
 534     FREE_C_HEAP_ARRAY(char, mem);
 535   }
 536 
 537   {
 538     oop obj;
 539     oop* ptr = &obj;
 540     // Predicate returns false for some "random" location.
 541     EXPECT_EQ(OopStorage::INVALID_ENTRY, _storage.allocation_status(ptr));
 542   }
 543 }
 544 #endif // DISABLE_GARBAGE_ALLOCATION_STATUS_TESTS
 545 
 546 class OopStorageTest::CountingIterateClosure {
 547 public:
 548   size_t _const_count;
 549   size_t _const_non_null;
 550   size_t _non_const_count;
 551   size_t _non_const_non_null;
 552 
 553   void do_oop(const oop* ptr) {
 554     ++_const_count;
 555     if (*ptr != NULL) {
 556       ++_const_non_null;
 557     }
 558   }
 559 
 560   void do_oop(oop* ptr) {
 561     ++_non_const_count;
 562     if (*ptr != NULL) {
 563       ++_non_const_non_null;
 564     }
 565   }
 566 
 567   CountingIterateClosure() :
 568     _const_count(0),
 569     _const_non_null(0),
 570     _non_const_count(0),
 571     _non_const_non_null(0)
 572   {}
 573 };
 574 
 575 template<bool is_const>
 576 class OopStorageTest::VM_CountAtSafepoint : public VM_GTestExecuteAtSafepoint {
 577 public:
 578   typedef typename Conditional<is_const,
 579                                const OopStorage,
 580                                OopStorage>::type Storage;
 581 
 582   VM_CountAtSafepoint(Storage* storage, CountingIterateClosure* cl) :
 583     _storage(storage), _cl(cl)
 584   {}
 585 
 586   void doit() { _storage->oops_do(_cl); }
 587 
 588 private:
 589   Storage* _storage;
 590   CountingIterateClosure* _cl;
 591 };
 592 
 593 TEST_VM_F(OopStorageTest, simple_iterate) {
 594   // Dummy oop value.
 595   intptr_t dummy_oop_value = 0xbadbeaf;
 596   oop dummy_oop = reinterpret_cast<oopDesc*>(&dummy_oop_value);
 597 
 598   const size_t max_entries = 1000;
 599   oop* entries[max_entries];
 600 
 601   size_t allocated = 0;
 602   size_t entries_with_values = 0;
 603   for (size_t i = 0; i < max_entries; i += 10) {
 604     for ( ; allocated < i; ++allocated) {
 605       entries[allocated] = _storage.allocate();
 606       ASSERT_TRUE(entries[allocated] != NULL);
 607       if ((allocated % 3) != 0) {
 608         *entries[allocated] = dummy_oop;
 609         ++entries_with_values;
 610       }
 611     }
 612 
 613     {
 614       CountingIterateClosure cl;
 615       VM_CountAtSafepoint<false> op(&_storage, &cl);
 616       {
 617         ThreadInVMfromNative invm(JavaThread::current());
 618         VMThread::execute(&op);
 619       }
 620       EXPECT_EQ(allocated, cl._non_const_count);
 621       EXPECT_EQ(entries_with_values, cl._non_const_non_null);
 622       EXPECT_EQ(0u, cl._const_count);
 623       EXPECT_EQ(0u, cl._const_non_null);
 624     }
 625 
 626     {
 627       CountingIterateClosure cl;
 628       VM_CountAtSafepoint<true> op(&_storage, &cl);
 629       {
 630         ThreadInVMfromNative invm(JavaThread::current());
 631         VMThread::execute(&op);
 632       }
 633       EXPECT_EQ(allocated, cl._const_count);
 634       EXPECT_EQ(entries_with_values, cl._const_non_null);
 635       EXPECT_EQ(0u, cl._non_const_count);
 636       EXPECT_EQ(0u, cl._non_const_non_null);
 637     }
 638   }
 639 
 640   while (allocated > 0) {
 641     release_entry(_storage, entries[--allocated], false);
 642   }
 643   process_deferred_updates(_storage);
 644 }
 645 
 646 class OopStorageTestIteration : public OopStorageTestWithAllocation {
 647 public:
 648   static const size_t _max_workers = 2;
 649   unsigned char _states[_max_workers][_max_entries];
 650 
 651   static const unsigned char mark_released  = 1u << 0;
 652   static const unsigned char mark_invalid   = 1u << 1;
 653   static const unsigned char mark_const     = 1u << 2;
 654   static const unsigned char mark_non_const = 1u << 3;
 655 
 656   virtual void SetUp() {
 657     OopStorageTestWithAllocation::SetUp();
 658 
 659     memset(_states, 0, sizeof(_states));
 660 
 661     size_t initial_release = 0;
 662     for ( ; empty_block_count(_storage) < 2; ++initial_release) {
 663       ASSERT_GT(_max_entries, initial_release);
 664       release_entry(_storage, _entries[initial_release]);
 665       _states[0][initial_release] = mark_released;
 666     }
 667 
 668     for (size_t i = initial_release; i < _max_entries; i += 3) {
 669       release_entry(_storage, _entries[i], false);
 670       _states[0][i] = mark_released;
 671     }
 672     process_deferred_updates(_storage);
 673   }
 674 
 675   class VerifyState;
 676   class VerifyFn;
 677   template<bool is_const> class VM_Verify;
 678 
 679   class VerifyClosure;
 680   class VM_VerifyUsingOopsDo;
 681 };
 682 
 683 const unsigned char OopStorageTestIteration::mark_released;
 684 const unsigned char OopStorageTestIteration::mark_invalid;
 685 const unsigned char OopStorageTestIteration::mark_const;
 686 const unsigned char OopStorageTestIteration::mark_non_const;
 687 
 688 class OopStorageTestIteration::VerifyState {
 689 public:
 690   unsigned char _expected_mark;
 691   const oop* const* _entries;
 692   unsigned char (&_states)[_max_workers][_max_entries];
 693 
 694   VerifyState(unsigned char expected_mark,
 695               const oop* const* entries,
 696               unsigned char (&states)[_max_workers][_max_entries]) :
 697     _expected_mark(expected_mark),
 698     _entries(entries),
 699     _states(states)
 700   { }
 701 
 702   bool update(const oop* ptr, uint worker_id, unsigned char mark) const {
 703     size_t index = 0;
 704     bool found = find_entry(ptr, &index);
 705     EXPECT_TRUE(found);
 706     EXPECT_GT(_max_entries, index);
 707     EXPECT_GT(_max_workers, worker_id);
 708     if (!found) {
 709       return false;
 710     } else if (index >= _max_entries) {
 711       return false;
 712     } else if (worker_id >= _max_workers) {
 713       return false;
 714     } else {
 715       EXPECT_EQ(0, _states[worker_id][index]);
 716       if (_states[worker_id][index] != 0) {
 717         _states[worker_id][index] |= mark_invalid;
 718         return false;
 719       } else {
 720         _states[worker_id][index] |= mark;
 721         return true;
 722       }
 723     }
 724   }
 725 
 726   void check() const {
 727     for (size_t i = 0; i < _max_entries; ++i) {
 728       unsigned char mark = 0;
 729       for (size_t w = 0; w < _max_workers; ++w) {
 730         if (mark == 0) {
 731           mark = _states[w][i];
 732         } else {
 733           EXPECT_EQ(0u, _states[w][i]);
 734         }
 735       }
 736       if (mark == 0) {
 737         EXPECT_NE(0u, mark);
 738       } else if ((mark & mark_released) != 0) {
 739         EXPECT_EQ(mark_released, mark);
 740       } else {
 741         EXPECT_EQ(_expected_mark, mark);
 742       }
 743     }
 744   }
 745 
 746 private:
 747   bool find_entry(const oop* ptr, size_t* index) const {
 748     for (size_t i = 0; i < _max_entries; ++i) {
 749       if (ptr == _entries[i]) {
 750         *index = i;
 751         return true;
 752       }
 753     }
 754     return false;
 755   }
 756 };
 757 
 758 class OopStorageTestIteration::VerifyFn {
 759 public:
 760   VerifyFn(VerifyState* state, uint worker_id = 0) :
 761     _state(state),
 762     _worker_id(worker_id)
 763   {}
 764 
 765   bool operator()(      oop* ptr) const {
 766     return _state->update(ptr, _worker_id, mark_non_const);
 767   }
 768 
 769   bool operator()(const oop* ptr) const {
 770     return _state->update(ptr, _worker_id, mark_const);
 771   }
 772 
 773 private:
 774   VerifyState* _state;
 775   uint _worker_id;
 776 };
 777 
 778 class OopStorageTestIteration::VerifyClosure {
 779 public:
 780   VerifyClosure(VerifyState* state, uint worker_id = 0) :
 781     _state(state),
 782     _worker_id(worker_id)
 783   {}
 784 
 785   void do_oop(oop* ptr) {
 786     _state->update(ptr, _worker_id, mark_non_const);
 787   }
 788 
 789   void do_oop(const oop* ptr) {
 790     _state->update(ptr, _worker_id, mark_const);
 791   }
 792 
 793 private:
 794   VerifyState* _state;
 795   uint _worker_id;
 796 };
 797 
 798 const size_t OopStorageTestIteration::_max_workers;
 799 
 800 template<bool is_const>
 801 class OopStorageTestIteration::VM_Verify : public VM_GTestExecuteAtSafepoint {
 802 public:
 803   typedef typename Conditional<is_const,
 804                                const OopStorage,
 805                                OopStorage>::type Storage;
 806 
 807   VM_Verify(Storage* storage, VerifyState* vstate) :
 808     _storage(storage), _vstate(vstate), _result(false)
 809   {}
 810 
 811   void doit() {
 812     VerifyFn verifier(_vstate);
 813     _result = _storage->iterate_safepoint(verifier);
 814   }
 815 
 816   bool result() const { return _result; }
 817 
 818 private:
 819   Storage* _storage;
 820   VerifyState* _vstate;
 821   bool _result;
 822 };
 823 
 824 class OopStorageTestIteration::VM_VerifyUsingOopsDo : public VM_GTestExecuteAtSafepoint {
 825 public:
 826   VM_VerifyUsingOopsDo(OopStorage* storage, VerifyState* vstate) :
 827     _storage(storage), _vstate(vstate)
 828   {}
 829 
 830   void doit() {
 831     VerifyClosure verifier(_vstate);
 832     _storage->oops_do(&verifier);
 833   }
 834 
 835 private:
 836   OopStorage* _storage;
 837   VerifyState* _vstate;
 838 };
 839 
 840 TEST_VM_F(OopStorageTestIteration, iterate_safepoint) {
 841   VerifyState vstate(mark_non_const, _entries, _states);
 842   VM_Verify<false> op(&_storage, &vstate);
 843   {
 844     ThreadInVMfromNative invm(JavaThread::current());
 845     VMThread::execute(&op);
 846   }
 847   EXPECT_TRUE(op.result());
 848   vstate.check();
 849 }
 850 
 851 TEST_VM_F(OopStorageTestIteration, const_iterate_safepoint) {
 852   VerifyState vstate(mark_const, _entries, _states);
 853   VM_Verify<true> op(&_storage, &vstate);
 854   {
 855     ThreadInVMfromNative invm(JavaThread::current());
 856     VMThread::execute(&op);
 857   }
 858   EXPECT_TRUE(op.result());
 859   vstate.check();
 860 }
 861 
 862 TEST_VM_F(OopStorageTestIteration, oops_do) {
 863   VerifyState vstate(mark_non_const, _entries, _states);
 864   VM_VerifyUsingOopsDo op(&_storage, &vstate);
 865   {
 866     ThreadInVMfromNative invm(JavaThread::current());
 867     VMThread::execute(&op);
 868   }
 869   vstate.check();
 870 }
 871 
 872 class OopStorageTestParIteration : public OopStorageTestIteration {
 873 public:
 874   WorkGang* workers();
 875 
 876   class VM_ParStateVerify;
 877 
 878   template<bool concurrent, bool is_const> class Task;
 879   template<bool concurrent, bool is_const> class TaskUsingOopsDo;
 880 
 881 private:
 882   static WorkGang* _workers;
 883 };
 884 
 885 WorkGang* OopStorageTestParIteration::_workers = NULL;
 886 
 887 WorkGang* OopStorageTestParIteration::workers() {
 888   if (_workers == NULL) {
 889     _workers = new WorkGang("OopStorageTestParIteration workers",
 890                             _max_workers,
 891                             false,
 892                             false);
 893     _workers->initialize_workers();
 894     _workers->update_active_workers(_max_workers);
 895   }
 896   return _workers;
 897 }
 898 
 899 template<bool concurrent, bool is_const>
 900 class OopStorageTestParIteration::Task : public AbstractGangTask {
 901   typedef OopStorage::ParState<concurrent, is_const> StateType;
 902 
 903   typedef typename Conditional<is_const,
 904                                const OopStorage,
 905                                OopStorage>::type Storage;
 906 
 907 public:
 908   Task(const char* name, Storage* storage, VerifyState* vstate) :
 909     AbstractGangTask(name),
 910     _state(storage),
 911     _vstate(vstate)
 912   {}
 913 
 914   virtual void work(uint worker_id) {
 915     VerifyFn verifier(_vstate, worker_id);
 916     _state.iterate(verifier);
 917   }
 918 
 919 private:
 920   StateType _state;
 921   VerifyState* _vstate;
 922 };
 923 
 924 template<bool concurrent, bool is_const>
 925 class OopStorageTestParIteration::TaskUsingOopsDo : public AbstractGangTask {
 926 public:
 927   TaskUsingOopsDo(const char* name, OopStorage* storage, VerifyState* vstate) :
 928     AbstractGangTask(name),
 929     _state(storage),
 930     _vstate(vstate)
 931   {}
 932 
 933   virtual void work(uint worker_id) {
 934     VerifyClosure verifier(_vstate, worker_id);
 935     _state.oops_do(&verifier);
 936   }
 937 
 938 private:
 939   OopStorage::ParState<concurrent, is_const> _state;
 940   VerifyState* _vstate;
 941 };
 942 
 943 class OopStorageTestParIteration::VM_ParStateVerify : public VM_GTestExecuteAtSafepoint {
 944 public:
 945   VM_ParStateVerify(WorkGang* workers, AbstractGangTask* task) :
 946     _workers(workers), _task(task)
 947   {}
 948 
 949   void doit() {
 950     _workers->run_task(_task);
 951   }
 952 
 953 private:
 954   WorkGang* _workers;
 955   AbstractGangTask* _task;
 956 };
 957 
 958 TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_iterate) {
 959   VerifyState vstate(mark_non_const, _entries, _states);
 960   Task<false, false> task("test", &_storage, &vstate);
 961   VM_ParStateVerify op(workers(), &task);
 962   {
 963     ThreadInVMfromNative invm(JavaThread::current());
 964     VMThread::execute(&op);
 965   }
 966   vstate.check();
 967 }
 968 
 969 TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_const_iterate) {
 970   VerifyState vstate(mark_const, _entries, _states);
 971   Task<false, true> task("test", &_storage, &vstate);
 972   VM_ParStateVerify op(workers(), &task);
 973   {
 974     ThreadInVMfromNative invm(JavaThread::current());
 975     VMThread::execute(&op);
 976   }
 977   vstate.check();
 978 }
 979 
 980 TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_oops_do) {
 981   VerifyState vstate(mark_non_const, _entries, _states);
 982   TaskUsingOopsDo<false, false> task("test", &_storage, &vstate);
 983   VM_ParStateVerify op(workers(), &task);
 984   {
 985     ThreadInVMfromNative invm(JavaThread::current());
 986     VMThread::execute(&op);
 987   }
 988   vstate.check();
 989 }
 990 
 991 TEST_VM_F(OopStorageTestParIteration, par_state_safepoint_const_oops_do) {
 992   VerifyState vstate(mark_const, _entries, _states);
 993   TaskUsingOopsDo<false, true> task("test", &_storage, &vstate);
 994   VM_ParStateVerify op(workers(), &task);
 995   {
 996     ThreadInVMfromNative invm(JavaThread::current());
 997     VMThread::execute(&op);
 998   }
 999   vstate.check();
1000 }
1001 
1002 TEST_VM_F(OopStorageTestParIteration, par_state_concurrent_iterate) {
1003   VerifyState vstate(mark_non_const, _entries, _states);
1004   Task<true, false> task("test", &_storage, &vstate);
1005   workers()->run_task(&task);
1006   vstate.check();
1007 }
1008 
1009 TEST_VM_F(OopStorageTestParIteration, par_state_concurrent_const_iterate) {
1010   VerifyState vstate(mark_const, _entries, _states);
1011   Task<true, true> task("test", &_storage, &vstate);
1012   workers()->run_task(&task);
1013   vstate.check();
1014 }
1015 
1016 TEST_VM_F(OopStorageTestParIteration, par_state_concurrent_oops_do) {
1017   VerifyState vstate(mark_non_const, _entries, _states);
1018   TaskUsingOopsDo<true, false> task("test", &_storage, &vstate);
1019   workers()->run_task(&task);
1020   vstate.check();
1021 }
1022 
1023 TEST_VM_F(OopStorageTestParIteration, par_state_concurrent_const_oops_do) {
1024   VerifyState vstate(mark_const, _entries, _states);
1025   TaskUsingOopsDo<true, true> task("test", &_storage, &vstate);
1026   workers()->run_task(&task);
1027   vstate.check();
1028 }
1029 
1030 TEST_VM_F(OopStorageTestWithAllocation, delete_empty_blocks_safepoint) {
1031   size_t initial_active_size = active_count(_storage);
1032   EXPECT_EQ(initial_active_size, _storage.block_count());
1033   ASSERT_LE(3u, initial_active_size); // Need at least 3 blocks for test
1034 
1035   for (size_t i = 0; empty_block_count(_storage) < 3; ++i) {
1036     ASSERT_GT(_max_entries, i);
1037     release_entry(_storage, _entries[i]);
1038   }
1039 
1040   EXPECT_EQ(initial_active_size, active_count(_storage));
1041   EXPECT_EQ(initial_active_size, _storage.block_count());
1042   EXPECT_EQ(3u, empty_block_count(_storage));
1043 
1044   {
1045     ThreadInVMfromNative invm(JavaThread::current());
1046     VM_DeleteBlocksAtSafepoint op(&_storage);
1047     VMThread::execute(&op);
1048   }
1049   EXPECT_EQ(0u, empty_block_count(_storage));
1050   EXPECT_EQ(initial_active_size - 3, active_count(_storage));
1051   EXPECT_EQ(initial_active_size - 3, _storage.block_count());
1052 }
1053 
1054 TEST_VM_F(OopStorageTestWithAllocation, delete_empty_blocks_concurrent) {
1055   size_t initial_active_size = active_count(_storage);
1056   EXPECT_EQ(initial_active_size, _storage.block_count());
1057   ASSERT_LE(3u, initial_active_size); // Need at least 3 blocks for test
1058 
1059   for (size_t i = 0; empty_block_count(_storage) < 3; ++i) {
1060     ASSERT_GT(_max_entries, i);
1061     release_entry(_storage, _entries[i]);
1062   }
1063 
1064   EXPECT_EQ(initial_active_size, active_count(_storage));
1065   EXPECT_EQ(initial_active_size, _storage.block_count());
1066   EXPECT_EQ(3u, empty_block_count(_storage));
1067 
1068   _storage.delete_empty_blocks_concurrent();
1069   EXPECT_EQ(0u, empty_block_count(_storage));
1070   EXPECT_EQ(initial_active_size - 3, active_count(_storage));
1071   EXPECT_EQ(initial_active_size - 3, _storage.block_count());
1072 }
1073 
1074 TEST_VM_F(OopStorageTestWithAllocation, allocation_status) {
1075   oop* retained = _entries[200];
1076   oop* released = _entries[300];
1077   oop* garbage = reinterpret_cast<oop*>(1024 * 1024);
1078   release_entry(_storage, released);
1079 
1080   EXPECT_EQ(OopStorage::ALLOCATED_ENTRY, _storage.allocation_status(retained));
1081   EXPECT_EQ(OopStorage::UNALLOCATED_ENTRY, _storage.allocation_status(released));
1082 #ifndef DISABLE_GARBAGE_ALLOCATION_STATUS_TESTS
1083   EXPECT_EQ(OopStorage::INVALID_ENTRY, _storage.allocation_status(garbage));
1084 #endif
1085 
1086   for (size_t i = 0; i < _max_entries; ++i) {
1087     if ((_entries[i] != retained) && (_entries[i] != released)) {
1088       // Leave deferred release updates to block deletion.
1089       release_entry(_storage, _entries[i], false);
1090     }
1091   }
1092 
1093   {
1094     ThreadInVMfromNative invm(JavaThread::current());
1095     VM_DeleteBlocksAtSafepoint op(&_storage);
1096     VMThread::execute(&op);
1097   }
1098   EXPECT_EQ(OopStorage::ALLOCATED_ENTRY, _storage.allocation_status(retained));
1099 #ifndef DISABLE_GARBAGE_ALLOCATION_STATUS_TESTS
1100   EXPECT_EQ(OopStorage::INVALID_ENTRY, _storage.allocation_status(released));
1101   EXPECT_EQ(OopStorage::INVALID_ENTRY, _storage.allocation_status(garbage));
1102 #endif // DISABLE_GARBAGE_ALLOCATION_STATUS_TESTS
1103 }
1104 
1105 TEST_VM_F(OopStorageTest, usage_info) {
1106   size_t goal_blocks = 5;
1107   oop* entries[1000];
1108   size_t allocated = 0;
1109 
1110   EXPECT_EQ(0u, _storage.block_count());
1111   // There is non-block overhead, so always some usage.
1112   EXPECT_LT(0u, _storage.total_memory_usage());
1113 
1114   while (_storage.block_count() < goal_blocks) {
1115     size_t this_count = _storage.block_count();
1116     while (_storage.block_count() == this_count) {
1117       ASSERT_GT(ARRAY_SIZE(entries), allocated);
1118       entries[allocated] = _storage.allocate();
1119       ASSERT_TRUE(entries[allocated] != NULL);
1120       ++allocated;
1121     }
1122     EXPECT_NE(0u, _storage.block_count());
1123     EXPECT_NE(0u, _storage.total_memory_usage());
1124   }
1125 
1126   EXPECT_LT(TestAccess::memory_per_block() * _storage.block_count(),
1127             _storage.total_memory_usage());
1128 }
1129 
1130 #ifndef PRODUCT
1131 
1132 TEST_VM_F(OopStorageTestWithAllocation, print_storage) {
1133   // Release the first 1/2
1134   for (size_t i = 0; i < (_max_entries / 2); ++i) {
1135     // Deferred updates don't affect print output.
1136     release_entry(_storage, _entries[i], false);
1137     _entries[i] = NULL;
1138   }
1139   // Release every other remaining
1140   for (size_t i = _max_entries / 2; i < _max_entries; i += 2) {
1141     // Deferred updates don't affect print output.
1142     release_entry(_storage, _entries[i], false);
1143     _entries[i] = NULL;
1144   }
1145 
1146   size_t expected_entries = _max_entries / 4;
1147   EXPECT_EQ(expected_entries, _storage.allocation_count());
1148 
1149   size_t entries_per_block = BitsPerWord;
1150   size_t expected_blocks = (_max_entries + entries_per_block - 1) / entries_per_block;
1151   EXPECT_EQ(expected_blocks, _storage.block_count());
1152 
1153   double expected_usage = (100.0 * expected_entries) / (expected_blocks * entries_per_block);
1154 
1155   {
1156     ResourceMark rm;
1157     stringStream expected_st;
1158     expected_st.print("Test Storage: " SIZE_FORMAT
1159                       " entries in " SIZE_FORMAT
1160                       " blocks (%.F%%), " SIZE_FORMAT " bytes",
1161                       expected_entries,
1162                       expected_blocks,
1163                       expected_usage,
1164                       _storage.total_memory_usage());
1165     stringStream st;
1166     _storage.print_on(&st);
1167     EXPECT_STREQ(expected_st.as_string(), st.as_string());
1168   }
1169 }
1170 
1171 #endif // !PRODUCT
1172 
1173 class OopStorageBlockCollectionTest : public ::testing::Test {
1174 protected:
1175   OopStorageBlockCollectionTest() {
1176     for (size_t i = 0; i < nvalues; ++i) {
1177       values[i] = OopBlock::new_block(pseudo_owner());
1178     }
1179   }
1180 
1181   ~OopStorageBlockCollectionTest() {
1182     for (size_t i = 0; i < nvalues; ++i) {
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());
1369   EXPECT_EQ(0u, a->block_count_acquire());
1370   TestAccess::block_array_set_block_count(a, 2);
1371   EXPECT_EQ(2u, a->block_count_acquire());
1372   TestAccess::block_array_set_block_count(a, 0);
1373   a->increment_refcount();
1374   a->increment_refcount();
1375   EXPECT_FALSE(a->decrement_refcount());
1376   EXPECT_TRUE(a->decrement_refcount());
1377 
1378   ActiveArray::destroy(a);
1379 }
1380 
1381 TEST_F(OopStorageActiveArrayTest, push) {
1382   ActiveArray* a = ActiveArray::create(nvalues - 1);
1383 
1384   for (size_t i = 0; i < nvalues - 1; ++i) {
1385     EXPECT_TRUE(a->push(values[i]));
1386     EXPECT_EQ(i + 1, a->block_count_acquire());
1387     EXPECT_EQ(values[i], a->at(i));
1388   }
1389   EXPECT_FALSE(a->push(values[nvalues - 1]));
1390 
1391   TestAccess::block_array_set_block_count(a, 0);
1392   ActiveArray::destroy(a);
1393 }
1394 
1395 class OopStorageActiveArrayTestWithArray : public OopStorageActiveArrayTest {
1396 public:
1397   OopStorageActiveArrayTestWithArray() : a(ActiveArray::create(nvalues)) {
1398     for (size_t i = 0; i < nvalues; ++i) {
1399       a->push(values[i]);
1400     }
1401   }
1402 
1403   ~OopStorageActiveArrayTestWithArray() {
1404     TestAccess::block_array_set_block_count(a, 0);
1405     ActiveArray::destroy(a);
1406   }
1407 
1408   ActiveArray* a;
1409 };
1410 
1411 TEST_F(OopStorageActiveArrayTestWithArray, 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(OopStorageActiveArrayTestWithArray, 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(OopStorageActiveArrayTestWithArray, 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 }