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 
  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 
  32 #include "runtime/safepoint.hpp"
  33 #include "utilities/count_trailing_zeros.hpp"
  34 #include "utilities/debug.hpp"
  35 #include "utilities/globalDefinitions.hpp"
  36 
  37 class OopStorage::Block /* No base class, to avoid messing up alignment. */ {
  38   // _data must be the first non-static data member, for alignment.
  39   oop _data[BitsPerWord];
  40   static const unsigned _data_pos = 0; // Position of _data.
  41 
  42   volatile uintx _allocated_bitmask; // One bit per _data element.
  43   const OopStorage* _owner;
  44   void* _memory;              // Unaligned storage containing block.
  45   BlockEntry _active_entry;
  46   BlockEntry _allocate_entry;
  47   Block* volatile _deferred_updates_next;
  48   volatile uintx _release_refcount;
  49 
  50   Block(const OopStorage* owner, void* memory);
  51   ~Block();
  52 
  53   void check_index(unsigned index) const;
  54   unsigned get_index(const oop* ptr) const;
  55 
  56   template<typename F, typename BlockPtr>
  57   static bool iterate_impl(F f, BlockPtr b);
  58 
  59   // Noncopyable.
  60   Block(const Block&);
  61   Block& operator=(const Block&);
  62 
  63 public:
  64   static const BlockEntry& get_active_entry(const Block& block);
  65   static const BlockEntry& get_allocate_entry(const Block& block);
  66 
  67   static size_t allocation_size();
  68   static size_t allocation_alignment_shift();
  69 
  70   oop* get_pointer(unsigned index);
  71   const oop* get_pointer(unsigned index) const;
  72 
  73   uintx bitmask_for_index(unsigned index) const;
  74   uintx bitmask_for_entry(const oop* ptr) const;
  75 
  76   // Allocation bitmask accessors are racy.
  77   bool is_full() const;
  78   bool is_empty() const;
  79   uintx allocated_bitmask() const;
  80   bool is_deletable() const;
  81 
  82   Block* deferred_updates_next() const;
  83   void set_deferred_updates_next(Block* new_next);
  84 
  85   bool contains(const oop* ptr) const;
  86 
  87   // Returns NULL if ptr is not in a block or not allocated in that block.
  88   static Block* block_for_ptr(const OopStorage* owner, const oop* ptr);
  89 
  90   oop* allocate();
  91   static Block* new_block(const OopStorage* owner);
  92   static void delete_block(const Block& block);
  93 
  94   void release_entries(uintx releasing, Block* volatile* deferred_list);
  95 
  96   template<typename F> bool iterate(F f);
  97   template<typename F> bool iterate(F f) const;
  98 }; // class Block
  99 
 100 inline OopStorage::Block* OopStorage::BlockList::head() {
 101   return const_cast<Block*>(_head);
 102 }
 103 
 104 inline const OopStorage::Block* OopStorage::BlockList::chead() const {
 105   return _head;
 106 }
 107 
 108 inline const OopStorage::Block* OopStorage::BlockList::ctail() const {
 109   return _tail;
 110 }
 111 
 112 inline OopStorage::Block* OopStorage::BlockList::prev(Block& block) {
 113   return const_cast<Block*>(_get_entry(block)._prev);
 114 }
 115 
 116 inline OopStorage::Block* OopStorage::BlockList::next(Block& block) {
 117   return const_cast<Block*>(_get_entry(block)._next);
 118 }
 119 
 120 inline const OopStorage::Block* OopStorage::BlockList::prev(const Block& block) const {
 121   return _get_entry(block)._prev;
 122 }
 123 
 124 inline const OopStorage::Block* OopStorage::BlockList::next(const Block& block) const {
 125   return _get_entry(block)._next;
 126 }
 127 
 128 template<typename Closure>
 129 class OopStorage::OopFn {
 130 public:
 131   explicit OopFn(Closure* cl) : _cl(cl) {}
 132 
 133   template<typename OopPtr>     // [const] oop*
 134   bool operator()(OopPtr ptr) const {
 135     _cl->do_oop(ptr);
 136     return true;
 137   }
 138 
 139 private:
 140   Closure* _cl;
 141 };
 142 
 143 template<typename Closure>
 144 inline OopStorage::OopFn<Closure> OopStorage::oop_fn(Closure* cl) {
 145   return OopFn<Closure>(cl);
 146 }
 147 
 148 template<typename IsAlive, typename F>
 149 class OopStorage::IfAliveFn {
 150 public:
 151   IfAliveFn(IsAlive* is_alive, F f) : _is_alive(is_alive), _f(f) {}
 152 
 153   bool operator()(oop* ptr) const {
 154     bool result = true;
 155     oop v = *ptr;
 156     if (v != NULL) {
 157       if (_is_alive->do_object_b(v)) {
 158         result = _f(ptr);
 159       } else {
 160         *ptr = NULL;            // Clear dead value.
 161       }
 162     }
 163     return result;
 164   }
 165 
 166 private:
 167   IsAlive* _is_alive;
 168   F _f;
 169 };
 170 
 171 template<typename IsAlive, typename F>
 172 inline OopStorage::IfAliveFn<IsAlive, F> OopStorage::if_alive_fn(IsAlive* is_alive, F f) {
 173   return IfAliveFn<IsAlive, F>(is_alive, f);
 174 }
 175 
 176 template<typename F>
 177 class OopStorage::SkipNullFn {
 178 public:
 179   SkipNullFn(F f) : _f(f) {}
 180 
 181   template<typename OopPtr>     // [const] oop*
 182   bool operator()(OopPtr ptr) const {
 183     return (*ptr != NULL) ? _f(ptr) : true;
 184   }
 185 
 186 private:
 187   F _f;
 188 };
 189 
 190 template<typename F>
 191 inline OopStorage::SkipNullFn<F> OopStorage::skip_null_fn(F f) {
 192   return SkipNullFn<F>(f);
 193 }
 194 
 195 // Inline Block accesses for use in iteration inner loop.
 196 
 197 inline void OopStorage::Block::check_index(unsigned index) const {
 198   assert(index < ARRAY_SIZE(_data), "Index out of bounds: %u", index);
 199 }
 200 
 201 inline oop* OopStorage::Block::get_pointer(unsigned index) {
 202   check_index(index);
 203   return &_data[index];
 204 }
 205 
 206 inline const oop* OopStorage::Block::get_pointer(unsigned index) const {
 207   check_index(index);
 208   return &_data[index];
 209 }
 210 
 211 inline uintx OopStorage::Block::allocated_bitmask() const {
 212   return _allocated_bitmask;
 213 }
 214 
 215 inline uintx OopStorage::Block::bitmask_for_index(unsigned index) const {
 216   check_index(index);
 217   return uintx(1) << index;
 218 }
 219 
 220 // Provide const or non-const iteration, depending on whether BlockPtr
 221 // is const Block* or Block*, respectively.
 222 template<typename F, typename BlockPtr> // BlockPtr := [const] Block*
 223 inline bool OopStorage::Block::iterate_impl(F f, BlockPtr block) {
 224   uintx bitmask = block->allocated_bitmask();
 225   while (bitmask != 0) {
 226     unsigned index = count_trailing_zeros(bitmask);
 227     bitmask ^= block->bitmask_for_index(index);
 228     if (!f(block->get_pointer(index))) {
 229       return false;
 230     }
 231   }
 232   return true;
 233 }
 234 
 235 template<typename F>
 236 inline bool OopStorage::Block::iterate(F f) {
 237   return iterate_impl(f, this);
 238 }
 239 
 240 template<typename F>
 241 inline bool OopStorage::Block::iterate(F f) const {
 242   return iterate_impl(f, this);
 243 }
 244 
 245 //////////////////////////////////////////////////////////////////////////////
 246 // Support for serial iteration, always at a safepoint.
 247 
 248 // Provide const or non-const iteration, depending on whether Storage is
 249 // const OopStorage* or OopStorage*, respectively.
 250 template<typename F, typename Storage> // Storage := [const] OopStorage
 251 inline bool OopStorage::iterate_impl(F f, Storage* storage) {
 252   assert_at_safepoint();
 253   // Propagate const/non-const iteration to the block layer, by using
 254   // const or non-const blocks as corresponding to Storage.
 255   typedef typename Conditional<IsConst<Storage>::value, const Block*, Block*>::type BlockPtr;
 256   for (BlockPtr block = storage->_active_head;
 257        block != NULL;
 258        block = storage->_active_list.next(*block)) {
 259     if (!block->iterate(f)) {
 260       return false;
 261     }
 262   }
 263   return true;
 264 }
 265 
 266 template<typename F>
 267 inline bool OopStorage::iterate_safepoint(F f) {
 268   return iterate_impl(f, this);
 269 }
 270 
 271 template<typename F>
 272 inline bool OopStorage::iterate_safepoint(F f) const {
 273   return iterate_impl(f, this);
 274 }
 275 
 276 template<typename Closure>
 277 inline void OopStorage::oops_do(Closure* cl) {
 278   iterate_safepoint(oop_fn(cl));
 279 }
 280 
 281 template<typename Closure>
 282 inline void OopStorage::oops_do(Closure* cl) const {
 283   iterate_safepoint(oop_fn(cl));
 284 }
 285 
 286 template<typename Closure>
 287 inline void OopStorage::weak_oops_do(Closure* cl) {
 288   iterate_safepoint(skip_null_fn(oop_fn(cl)));
 289 }
 290 
 291 template<typename IsAliveClosure, typename Closure>
 292 inline void OopStorage::weak_oops_do(IsAliveClosure* is_alive, Closure* cl) {
 293   iterate_safepoint(if_alive_fn(is_alive, oop_fn(cl)));
 294 }
 295 
 296 #endif // include guard