src/hotspot/share/gc/shared/oopStorage.inline.hpp
changeset 49977 9f758f0bb058
parent 49392 2956d0ece7a9
child 50209 2fdce199fcb9
equal deleted inserted replaced
49976:19829b375d08 49977:9f758f0bb058
    28 #include "gc/shared/oopStorage.hpp"
    28 #include "gc/shared/oopStorage.hpp"
    29 #include "metaprogramming/conditional.hpp"
    29 #include "metaprogramming/conditional.hpp"
    30 #include "metaprogramming/isConst.hpp"
    30 #include "metaprogramming/isConst.hpp"
    31 #include "oops/oop.hpp"
    31 #include "oops/oop.hpp"
    32 #include "runtime/safepoint.hpp"
    32 #include "runtime/safepoint.hpp"
       
    33 #include "utilities/align.hpp"
    33 #include "utilities/count_trailing_zeros.hpp"
    34 #include "utilities/count_trailing_zeros.hpp"
    34 #include "utilities/debug.hpp"
    35 #include "utilities/debug.hpp"
    35 #include "utilities/globalDefinitions.hpp"
    36 #include "utilities/globalDefinitions.hpp"
    36 
    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::BlockArray {
       
    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   BlockArray(size_t size);
       
    49   ~BlockArray();
       
    50 
       
    51   // Noncopyable
       
    52   BlockArray(const BlockArray&);
       
    53   BlockArray& operator=(const BlockArray&);
       
    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 BlockArray* create(size_t size, AllocFailType alloc_fail = AllocFailStrategy::EXIT_OOM);
       
    63   static void destroy(BlockArray* 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 BlockArray* from);
       
    86 };
       
    87 
       
    88 inline size_t OopStorage::BlockArray::blocks_offset() {
       
    89   return align_up(sizeof(BlockArray), sizeof(Block*));
       
    90 }
       
    91 
       
    92 inline OopStorage::Block* const* OopStorage::BlockArray::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::BlockArray::block_ptr(size_t index) const {
       
    98   return base_ptr() + index;
       
    99 }
       
   100 
       
   101 inline OopStorage::Block** OopStorage::BlockArray::block_ptr(size_t index) {
       
   102   return const_cast<Block**>(base_ptr() + index);
       
   103 }
       
   104 
       
   105 inline OopStorage::Block* OopStorage::BlockArray::at(size_t index) const {
       
   106   assert(index < _block_count, "precondition");
       
   107   return *block_ptr(index);
       
   108 }
       
   109 
       
   110 // A Block has an embedded BlockEntry to provide the links between
       
   111 // Blocks in a BlockList.
       
   112 class OopStorage::BlockEntry {
       
   113   friend class OopStorage::BlockList;
       
   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   BlockEntry(const BlockEntry&);
       
   123   BlockEntry& operator=(const BlockEntry&);
       
   124 
       
   125 public:
       
   126   BlockEntry();
       
   127   ~BlockEntry();
       
   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 _allocate_list, linked through the
       
   133 // block's _allocate_entry.  Empty blocks are at the end of that list.
    37 class OopStorage::Block /* No base class, to avoid messing up alignment. */ {
   134 class OopStorage::Block /* No base class, to avoid messing up alignment. */ {
    38   // _data must be the first non-static data member, for alignment.
   135   // _data must be the first non-static data member, for alignment.
    39   oop _data[BitsPerWord];
   136   oop _data[BitsPerWord];
    40   static const unsigned _data_pos = 0; // Position of _data.
   137   static const unsigned _data_pos = 0; // Position of _data.
    41 
   138 
    42   volatile uintx _allocated_bitmask; // One bit per _data element.
   139   volatile uintx _allocated_bitmask; // One bit per _data element.
    43   const OopStorage* _owner;
   140   const OopStorage* _owner;
    44   void* _memory;              // Unaligned storage containing block.
   141   void* _memory;              // Unaligned storage containing block.
    45   BlockEntry _active_entry;
   142   size_t _active_index;
    46   BlockEntry _allocate_entry;
   143   BlockEntry _allocate_entry;
    47   Block* volatile _deferred_updates_next;
   144   Block* volatile _deferred_updates_next;
    48   volatile uintx _release_refcount;
   145   volatile uintx _release_refcount;
    49 
   146 
    50   Block(const OopStorage* owner, void* memory);
   147   Block(const OopStorage* owner, void* memory);
    59   // Noncopyable.
   156   // Noncopyable.
    60   Block(const Block&);
   157   Block(const Block&);
    61   Block& operator=(const Block&);
   158   Block& operator=(const Block&);
    62 
   159 
    63 public:
   160 public:
    64   static const BlockEntry& get_active_entry(const Block& block);
       
    65   static const BlockEntry& get_allocate_entry(const Block& block);
   161   static const BlockEntry& get_allocate_entry(const Block& block);
    66 
   162 
    67   static size_t allocation_size();
   163   static size_t allocation_size();
    68   static size_t allocation_alignment_shift();
   164   static size_t allocation_alignment_shift();
    69 
   165 
    82   Block* deferred_updates_next() const;
   178   Block* deferred_updates_next() const;
    83   void set_deferred_updates_next(Block* new_next);
   179   void set_deferred_updates_next(Block* new_next);
    84 
   180 
    85   bool contains(const oop* ptr) const;
   181   bool contains(const oop* ptr) const;
    86 
   182 
       
   183   size_t active_index() const;
       
   184   void set_active_index(size_t index);
       
   185   static size_t active_index_safe(const Block* block); // Returns 0 if access fails.
       
   186 
    87   // Returns NULL if ptr is not in a block or not allocated in that block.
   187   // 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);
   188   static Block* block_for_ptr(const OopStorage* owner, const oop* ptr);
    89 
   189 
    90   oop* allocate();
   190   oop* allocate();
    91   static Block* new_block(const OopStorage* owner);
   191   static Block* new_block(const OopStorage* owner);
    97   template<typename F> bool iterate(F f) const;
   197   template<typename F> bool iterate(F f) const;
    98 }; // class Block
   198 }; // class Block
    99 
   199 
   100 inline OopStorage::Block* OopStorage::BlockList::head() {
   200 inline OopStorage::Block* OopStorage::BlockList::head() {
   101   return const_cast<Block*>(_head);
   201   return const_cast<Block*>(_head);
       
   202 }
       
   203 
       
   204 inline OopStorage::Block* OopStorage::BlockList::tail() {
       
   205   return const_cast<Block*>(_tail);
   102 }
   206 }
   103 
   207 
   104 inline const OopStorage::Block* OopStorage::BlockList::chead() const {
   208 inline const OopStorage::Block* OopStorage::BlockList::chead() const {
   105   return _head;
   209   return _head;
   106 }
   210 }
   251 inline bool OopStorage::iterate_impl(F f, Storage* storage) {
   355 inline bool OopStorage::iterate_impl(F f, Storage* storage) {
   252   assert_at_safepoint();
   356   assert_at_safepoint();
   253   // Propagate const/non-const iteration to the block layer, by using
   357   // Propagate const/non-const iteration to the block layer, by using
   254   // const or non-const blocks as corresponding to Storage.
   358   // const or non-const blocks as corresponding to Storage.
   255   typedef typename Conditional<IsConst<Storage>::value, const Block*, Block*>::type BlockPtr;
   359   typedef typename Conditional<IsConst<Storage>::value, const Block*, Block*>::type BlockPtr;
   256   for (BlockPtr block = storage->_active_head;
   360   BlockArray* blocks = storage->_active_array;
   257        block != NULL;
   361   size_t limit = blocks->block_count();
   258        block = storage->_active_list.next(*block)) {
   362   for (size_t i = 0; i < limit; ++i) {
       
   363     BlockPtr block = blocks->at(i);
   259     if (!block->iterate(f)) {
   364     if (!block->iterate(f)) {
   260       return false;
   365       return false;
   261     }
   366     }
   262   }
   367   }
   263   return true;
   368   return true;