1 /*
   2  * Copyright (c) 2018, 2019, 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 
  25 #ifndef SHARE_GC_SHARED_OOPSTORAGE_INLINE_HPP
  26 #define SHARE_GC_SHARED_OOPSTORAGE_INLINE_HPP
  27 
  28 #include "gc/shared/oopStorage.hpp"
  29 #include "metaprogramming/conditional.hpp"
  30 #include "metaprogramming/isConst.hpp"
  31 #include "oops/oop.hpp"
  32 #include "runtime/safepoint.hpp"
  33 #include "utilities/align.hpp"
  34 #include "utilities/count_trailing_zeros.hpp"
  35 #include "utilities/debug.hpp"
  36 #include "utilities/globalDefinitions.hpp"
  37 
  38 // Array of all active blocks.  Refcounted for lock-free reclaim of
  39 // old array when a new array is allocated for expansion.
  40 class OopStorage::ActiveArray {
  41   friend class OopStorage::TestAccess;
  42 
  43   size_t _size;
  44   volatile size_t _block_count;
  45   mutable volatile int _refcount;
  46   // Block* _blocks[1];            // Pseudo flexible array member.
  47 
  48   ActiveArray(size_t size);
  49   ~ActiveArray();
  50 
  51   // Noncopyable
  52   ActiveArray(const ActiveArray&);
  53   ActiveArray& operator=(const ActiveArray&);
  54 
  55   static size_t blocks_offset();
  56   Block* const* base_ptr() const;
  57 
  58   Block* const* block_ptr(size_t index) const;
  59   Block** block_ptr(size_t index);
  60 
  61 public:
  62   static ActiveArray* create(size_t size, AllocFailType alloc_fail = AllocFailStrategy::EXIT_OOM);
  63   static void destroy(ActiveArray* ba);
  64 
  65   inline Block* at(size_t i) const;
  66 
  67   size_t size() const;
  68   size_t block_count() const;
  69   size_t block_count_acquire() const;
  70   void increment_refcount() const;
  71   bool decrement_refcount() const; // Return true if zero, otherwise false
  72 
  73   // Support for OopStorage::allocate.
  74   // Add block to the end of the array.  Updates block count at the
  75   // end of the operation, with a release_store. Returns true if the
  76   // block was added, false if there was no room available.
  77   // precondition: owner's _allocation_mutex is locked, or at safepoint.
  78   bool push(Block* block);
  79 
  80   // Support OopStorage::delete_empty_blocks_xxx operations.
  81   // Remove block from the array.
  82   // precondition: block must be present at its active_index element.
  83   void remove(Block* block);
  84 
  85   void copy_from(const ActiveArray* from);
  86 };
  87 
  88 inline size_t OopStorage::ActiveArray::blocks_offset() {
  89   return align_up(sizeof(ActiveArray), sizeof(Block*));
  90 }
  91 
  92 inline OopStorage::Block* const* OopStorage::ActiveArray::base_ptr() const {
  93   const void* ptr = reinterpret_cast<const char*>(this) + blocks_offset();
  94   return reinterpret_cast<Block* const*>(ptr);
  95 }
  96 
  97 inline OopStorage::Block* const* OopStorage::ActiveArray::block_ptr(size_t index) const {
  98   return base_ptr() + index;
  99 }
 100 
 101 inline OopStorage::Block** OopStorage::ActiveArray::block_ptr(size_t index) {
 102   return const_cast<Block**>(base_ptr() + index);
 103 }
 104 
 105 inline OopStorage::Block* OopStorage::ActiveArray::at(size_t index) const {
 106   assert(index < _block_count, "precondition");
 107   return *block_ptr(index);
 108 }
 109 
 110 // A Block has an embedded AllocationListEntry to provide the links between
 111 // Blocks in an AllocationList.
 112 class OopStorage::AllocationListEntry {
 113   friend class OopStorage::AllocationList;
 114 
 115   // Members are mutable, and we deal exclusively with pointers to
 116   // const, to make const blocks easier to use; a block being const
 117   // doesn't prevent modifying its list state.
 118   mutable const Block* _prev;
 119   mutable const Block* _next;
 120 
 121   // Noncopyable.
 122   AllocationListEntry(const AllocationListEntry&);
 123   AllocationListEntry& operator=(const AllocationListEntry&);
 124 
 125 public:
 126   AllocationListEntry();
 127   ~AllocationListEntry();
 128 };
 129 
 130 // Fixed-sized array of oops, plus bookkeeping data.
 131 // All blocks are in the storage's _active_array, at the block's _active_index.
 132 // Non-full blocks are in the storage's _allocation_list, linked through the
 133 // block's _allocation_list_entry.  Empty blocks are at the end of that list.
 134 class OopStorage::Block /* No base class, to avoid messing up alignment. */ {
 135   // _data must be the first non-static data member, for alignment.
 136   oop _data[BitsPerWord];
 137   static const unsigned _data_pos = 0; // Position of _data.
 138 
 139   volatile uintx _allocated_bitmask; // One bit per _data element.
 140   intptr_t _owner_address;
 141   void* _memory;              // Unaligned storage containing block.
 142   size_t _active_index;
 143   AllocationListEntry _allocation_list_entry;
 144   Block* volatile _deferred_updates_next;
 145   volatile uintx _release_refcount;
 146 
 147   Block(const OopStorage* owner, void* memory);
 148   ~Block();
 149 
 150   void check_index(unsigned index) const;
 151   unsigned get_index(const oop* ptr) const;
 152 
 153   template<typename F, typename BlockPtr>
 154   static bool iterate_impl(F f, BlockPtr b);
 155 
 156   // Noncopyable.
 157   Block(const Block&);
 158   Block& operator=(const Block&);
 159 
 160 public:
 161   const AllocationListEntry& allocation_list_entry() const;
 162 
 163   static size_t allocation_size();
 164   static size_t allocation_alignment_shift();
 165 
 166   oop* get_pointer(unsigned index);
 167   const oop* get_pointer(unsigned index) const;
 168 
 169   uintx bitmask_for_index(unsigned index) const;
 170   uintx bitmask_for_entry(const oop* ptr) const;
 171 
 172   // Allocation bitmask accessors are racy.
 173   bool is_full() const;
 174   bool is_empty() const;
 175   uintx allocated_bitmask() const;
 176 
 177   bool is_safe_to_delete() const;
 178 
 179   Block* deferred_updates_next() const;
 180   void set_deferred_updates_next(Block* new_next);
 181 
 182   bool contains(const oop* ptr) const;
 183 
 184   size_t active_index() const;
 185   void set_active_index(size_t index);
 186   static size_t active_index_safe(const Block* block); // Returns 0 if access fails.
 187 
 188   // Returns NULL if ptr is not in a block or not allocated in that block.
 189   static Block* block_for_ptr(const OopStorage* owner, const oop* ptr);
 190 
 191   oop* allocate();
 192   static Block* new_block(const OopStorage* owner);
 193   static void delete_block(const Block& block);
 194 
 195   void release_entries(uintx releasing, OopStorage* owner);
 196 
 197   template<typename F> bool iterate(F f);
 198   template<typename F> bool iterate(F f) const;
 199 }; // class Block
 200 
 201 inline OopStorage::Block* OopStorage::AllocationList::head() {
 202   return const_cast<Block*>(_head);
 203 }
 204 
 205 inline OopStorage::Block* OopStorage::AllocationList::tail() {
 206   return const_cast<Block*>(_tail);
 207 }
 208 
 209 inline const OopStorage::Block* OopStorage::AllocationList::chead() const {
 210   return _head;
 211 }
 212 
 213 inline const OopStorage::Block* OopStorage::AllocationList::ctail() const {
 214   return _tail;
 215 }
 216 
 217 inline OopStorage::Block* OopStorage::AllocationList::prev(Block& block) {
 218   return const_cast<Block*>(block.allocation_list_entry()._prev);
 219 }
 220 
 221 inline OopStorage::Block* OopStorage::AllocationList::next(Block& block) {
 222   return const_cast<Block*>(block.allocation_list_entry()._next);
 223 }
 224 
 225 inline const OopStorage::Block* OopStorage::AllocationList::prev(const Block& block) const {
 226   return block.allocation_list_entry()._prev;
 227 }
 228 
 229 inline const OopStorage::Block* OopStorage::AllocationList::next(const Block& block) const {
 230   return block.allocation_list_entry()._next;
 231 }
 232 
 233 template<typename Closure>
 234 class OopStorage::OopFn {
 235 public:
 236   explicit OopFn(Closure* cl) : _cl(cl) {}
 237 
 238   template<typename OopPtr>     // [const] oop*
 239   bool operator()(OopPtr ptr) const {
 240     _cl->do_oop(ptr);
 241     return true;
 242   }
 243 
 244 private:
 245   Closure* _cl;
 246 };
 247 
 248 template<typename Closure>
 249 inline OopStorage::OopFn<Closure> OopStorage::oop_fn(Closure* cl) {
 250   return OopFn<Closure>(cl);
 251 }
 252 
 253 template<typename IsAlive, typename F>
 254 class OopStorage::IfAliveFn {
 255 public:
 256   IfAliveFn(IsAlive* is_alive, F f) : _is_alive(is_alive), _f(f) {}
 257 
 258   bool operator()(oop* ptr) const {
 259     bool result = true;
 260     oop v = *ptr;
 261     if (v != NULL) {
 262       if (_is_alive->do_object_b(v)) {
 263         result = _f(ptr);
 264       } else {
 265         *ptr = NULL;            // Clear dead value.
 266       }
 267     }
 268     return result;
 269   }
 270 
 271 private:
 272   IsAlive* _is_alive;
 273   F _f;
 274 };
 275 
 276 template<typename IsAlive, typename F>
 277 inline OopStorage::IfAliveFn<IsAlive, F> OopStorage::if_alive_fn(IsAlive* is_alive, F f) {
 278   return IfAliveFn<IsAlive, F>(is_alive, f);
 279 }
 280 
 281 template<typename F>
 282 class OopStorage::SkipNullFn {
 283 public:
 284   SkipNullFn(F f) : _f(f) {}
 285 
 286   template<typename OopPtr>     // [const] oop*
 287   bool operator()(OopPtr ptr) const {
 288     return (*ptr != NULL) ? _f(ptr) : true;
 289   }
 290 
 291 private:
 292   F _f;
 293 };
 294 
 295 template<typename F>
 296 inline OopStorage::SkipNullFn<F> OopStorage::skip_null_fn(F f) {
 297   return SkipNullFn<F>(f);
 298 }
 299 
 300 // Inline Block accesses for use in iteration loops.
 301 
 302 inline const OopStorage::AllocationListEntry& OopStorage::Block::allocation_list_entry() const {
 303   return _allocation_list_entry;
 304 }
 305 
 306 inline void OopStorage::Block::check_index(unsigned index) const {
 307   assert(index < ARRAY_SIZE(_data), "Index out of bounds: %u", index);
 308 }
 309 
 310 inline oop* OopStorage::Block::get_pointer(unsigned index) {
 311   check_index(index);
 312   return &_data[index];
 313 }
 314 
 315 inline const oop* OopStorage::Block::get_pointer(unsigned index) const {
 316   check_index(index);
 317   return &_data[index];
 318 }
 319 
 320 inline uintx OopStorage::Block::allocated_bitmask() const {
 321   return _allocated_bitmask;
 322 }
 323 
 324 inline uintx OopStorage::Block::bitmask_for_index(unsigned index) const {
 325   check_index(index);
 326   return uintx(1) << index;
 327 }
 328 
 329 // Provide const or non-const iteration, depending on whether BlockPtr
 330 // is const Block* or Block*, respectively.
 331 template<typename F, typename BlockPtr> // BlockPtr := [const] Block*
 332 inline bool OopStorage::Block::iterate_impl(F f, BlockPtr block) {
 333   uintx bitmask = block->allocated_bitmask();
 334   while (bitmask != 0) {
 335     unsigned index = count_trailing_zeros(bitmask);
 336     bitmask ^= block->bitmask_for_index(index);
 337     if (!f(block->get_pointer(index))) {
 338       return false;
 339     }
 340   }
 341   return true;
 342 }
 343 
 344 template<typename F>
 345 inline bool OopStorage::Block::iterate(F f) {
 346   return iterate_impl(f, this);
 347 }
 348 
 349 template<typename F>
 350 inline bool OopStorage::Block::iterate(F f) const {
 351   return iterate_impl(f, this);
 352 }
 353 
 354 //////////////////////////////////////////////////////////////////////////////
 355 // Support for serial iteration, always at a safepoint.
 356 
 357 // Provide const or non-const iteration, depending on whether Storage is
 358 // const OopStorage* or OopStorage*, respectively.
 359 template<typename F, typename Storage> // Storage := [const] OopStorage
 360 inline bool OopStorage::iterate_impl(F f, Storage* storage) {
 361   assert_at_safepoint();
 362   // Propagate const/non-const iteration to the block layer, by using
 363   // const or non-const blocks as corresponding to Storage.
 364   typedef typename Conditional<IsConst<Storage>::value, const Block*, Block*>::type BlockPtr;
 365   ActiveArray* blocks = storage->_active_array;
 366   size_t limit = blocks->block_count();
 367   for (size_t i = 0; i < limit; ++i) {
 368     BlockPtr block = blocks->at(i);
 369     if (!block->iterate(f)) {
 370       return false;
 371     }
 372   }
 373   return true;
 374 }
 375 
 376 template<typename F>
 377 inline bool OopStorage::iterate_safepoint(F f) {
 378   return iterate_impl(f, this);
 379 }
 380 
 381 template<typename F>
 382 inline bool OopStorage::iterate_safepoint(F f) const {
 383   return iterate_impl(f, this);
 384 }
 385 
 386 template<typename Closure>
 387 inline void OopStorage::oops_do(Closure* cl) {
 388   iterate_safepoint(oop_fn(cl));
 389 }
 390 
 391 template<typename Closure>
 392 inline void OopStorage::oops_do(Closure* cl) const {
 393   iterate_safepoint(oop_fn(cl));
 394 }
 395 
 396 template<typename Closure>
 397 inline void OopStorage::weak_oops_do(Closure* cl) {
 398   iterate_safepoint(skip_null_fn(oop_fn(cl)));
 399 }
 400 
 401 template<typename IsAliveClosure, typename Closure>
 402 inline void OopStorage::weak_oops_do(IsAliveClosure* is_alive, Closure* cl) {
 403   iterate_safepoint(if_alive_fn(is_alive, oop_fn(cl)));
 404 }
 405 
 406 #endif // SHARE_GC_SHARED_OOPSTORAGE_INLINE_HPP