src/hotspot/share/gc/shared/oopStorage.inline.hpp
changeset 50209 2fdce199fcb9
parent 49977 9f758f0bb058
child 50513 7f166e010af4
equal deleted inserted replaced
50208:a20f2b3c321f 50209:2fdce199fcb9
    35 #include "utilities/debug.hpp"
    35 #include "utilities/debug.hpp"
    36 #include "utilities/globalDefinitions.hpp"
    36 #include "utilities/globalDefinitions.hpp"
    37 
    37 
    38 // Array of all active blocks.  Refcounted for lock-free reclaim of
    38 // Array of all active blocks.  Refcounted for lock-free reclaim of
    39 // old array when a new array is allocated for expansion.
    39 // old array when a new array is allocated for expansion.
    40 class OopStorage::BlockArray {
    40 class OopStorage::ActiveArray {
    41   friend class OopStorage::TestAccess;
    41   friend class OopStorage::TestAccess;
    42 
    42 
    43   size_t _size;
    43   size_t _size;
    44   volatile size_t _block_count;
    44   volatile size_t _block_count;
    45   mutable volatile int _refcount;
    45   mutable volatile int _refcount;
    46   // Block* _blocks[1];            // Pseudo flexible array member.
    46   // Block* _blocks[1];            // Pseudo flexible array member.
    47 
    47 
    48   BlockArray(size_t size);
    48   ActiveArray(size_t size);
    49   ~BlockArray();
    49   ~ActiveArray();
    50 
    50 
    51   // Noncopyable
    51   // Noncopyable
    52   BlockArray(const BlockArray&);
    52   ActiveArray(const ActiveArray&);
    53   BlockArray& operator=(const BlockArray&);
    53   ActiveArray& operator=(const ActiveArray&);
    54 
    54 
    55   static size_t blocks_offset();
    55   static size_t blocks_offset();
    56   Block* const* base_ptr() const;
    56   Block* const* base_ptr() const;
    57 
    57 
    58   Block* const* block_ptr(size_t index) const;
    58   Block* const* block_ptr(size_t index) const;
    59   Block** block_ptr(size_t index);
    59   Block** block_ptr(size_t index);
    60 
    60 
    61 public:
    61 public:
    62   static BlockArray* create(size_t size, AllocFailType alloc_fail = AllocFailStrategy::EXIT_OOM);
    62   static ActiveArray* create(size_t size, AllocFailType alloc_fail = AllocFailStrategy::EXIT_OOM);
    63   static void destroy(BlockArray* ba);
    63   static void destroy(ActiveArray* ba);
    64 
    64 
    65   inline Block* at(size_t i) const;
    65   inline Block* at(size_t i) const;
    66 
    66 
    67   size_t size() const;
    67   size_t size() const;
    68   size_t block_count() const;
    68   size_t block_count() const;
    80   // Support OopStorage::delete_empty_blocks_xxx operations.
    80   // Support OopStorage::delete_empty_blocks_xxx operations.
    81   // Remove block from the array.
    81   // Remove block from the array.
    82   // precondition: block must be present at its active_index element.
    82   // precondition: block must be present at its active_index element.
    83   void remove(Block* block);
    83   void remove(Block* block);
    84 
    84 
    85   void copy_from(const BlockArray* from);
    85   void copy_from(const ActiveArray* from);
    86 };
    86 };
    87 
    87 
    88 inline size_t OopStorage::BlockArray::blocks_offset() {
    88 inline size_t OopStorage::ActiveArray::blocks_offset() {
    89   return align_up(sizeof(BlockArray), sizeof(Block*));
    89   return align_up(sizeof(ActiveArray), sizeof(Block*));
    90 }
    90 }
    91 
    91 
    92 inline OopStorage::Block* const* OopStorage::BlockArray::base_ptr() const {
    92 inline OopStorage::Block* const* OopStorage::ActiveArray::base_ptr() const {
    93   const void* ptr = reinterpret_cast<const char*>(this) + blocks_offset();
    93   const void* ptr = reinterpret_cast<const char*>(this) + blocks_offset();
    94   return reinterpret_cast<Block* const*>(ptr);
    94   return reinterpret_cast<Block* const*>(ptr);
    95 }
    95 }
    96 
    96 
    97 inline OopStorage::Block* const* OopStorage::BlockArray::block_ptr(size_t index) const {
    97 inline OopStorage::Block* const* OopStorage::ActiveArray::block_ptr(size_t index) const {
    98   return base_ptr() + index;
    98   return base_ptr() + index;
    99 }
    99 }
   100 
   100 
   101 inline OopStorage::Block** OopStorage::BlockArray::block_ptr(size_t index) {
   101 inline OopStorage::Block** OopStorage::ActiveArray::block_ptr(size_t index) {
   102   return const_cast<Block**>(base_ptr() + index);
   102   return const_cast<Block**>(base_ptr() + index);
   103 }
   103 }
   104 
   104 
   105 inline OopStorage::Block* OopStorage::BlockArray::at(size_t index) const {
   105 inline OopStorage::Block* OopStorage::ActiveArray::at(size_t index) const {
   106   assert(index < _block_count, "precondition");
   106   assert(index < _block_count, "precondition");
   107   return *block_ptr(index);
   107   return *block_ptr(index);
   108 }
   108 }
   109 
   109 
   110 // A Block has an embedded BlockEntry to provide the links between
   110 // A Block has an embedded AllocateEntry to provide the links between
   111 // Blocks in a BlockList.
   111 // Blocks in a AllocateList.
   112 class OopStorage::BlockEntry {
   112 class OopStorage::AllocateEntry {
   113   friend class OopStorage::BlockList;
   113   friend class OopStorage::AllocateList;
   114 
   114 
   115   // Members are mutable, and we deal exclusively with pointers to
   115   // Members are mutable, and we deal exclusively with pointers to
   116   // const, to make const blocks easier to use; a block being const
   116   // const, to make const blocks easier to use; a block being const
   117   // doesn't prevent modifying its list state.
   117   // doesn't prevent modifying its list state.
   118   mutable const Block* _prev;
   118   mutable const Block* _prev;
   119   mutable const Block* _next;
   119   mutable const Block* _next;
   120 
   120 
   121   // Noncopyable.
   121   // Noncopyable.
   122   BlockEntry(const BlockEntry&);
   122   AllocateEntry(const AllocateEntry&);
   123   BlockEntry& operator=(const BlockEntry&);
   123   AllocateEntry& operator=(const AllocateEntry&);
   124 
   124 
   125 public:
   125 public:
   126   BlockEntry();
   126   AllocateEntry();
   127   ~BlockEntry();
   127   ~AllocateEntry();
   128 };
   128 };
   129 
   129 
   130 // Fixed-sized array of oops, plus bookkeeping data.
   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.
   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
   132 // Non-full blocks are in the storage's _allocate_list, linked through the
   138 
   138 
   139   volatile uintx _allocated_bitmask; // One bit per _data element.
   139   volatile uintx _allocated_bitmask; // One bit per _data element.
   140   const OopStorage* _owner;
   140   const OopStorage* _owner;
   141   void* _memory;              // Unaligned storage containing block.
   141   void* _memory;              // Unaligned storage containing block.
   142   size_t _active_index;
   142   size_t _active_index;
   143   BlockEntry _allocate_entry;
   143   AllocateEntry _allocate_entry;
   144   Block* volatile _deferred_updates_next;
   144   Block* volatile _deferred_updates_next;
   145   volatile uintx _release_refcount;
   145   volatile uintx _release_refcount;
   146 
   146 
   147   Block(const OopStorage* owner, void* memory);
   147   Block(const OopStorage* owner, void* memory);
   148   ~Block();
   148   ~Block();
   156   // Noncopyable.
   156   // Noncopyable.
   157   Block(const Block&);
   157   Block(const Block&);
   158   Block& operator=(const Block&);
   158   Block& operator=(const Block&);
   159 
   159 
   160 public:
   160 public:
   161   static const BlockEntry& get_allocate_entry(const Block& block);
   161   static const AllocateEntry& get_allocate_entry(const Block& block);
   162 
   162 
   163   static size_t allocation_size();
   163   static size_t allocation_size();
   164   static size_t allocation_alignment_shift();
   164   static size_t allocation_alignment_shift();
   165 
   165 
   166   oop* get_pointer(unsigned index);
   166   oop* get_pointer(unsigned index);
   195 
   195 
   196   template<typename F> bool iterate(F f);
   196   template<typename F> bool iterate(F f);
   197   template<typename F> bool iterate(F f) const;
   197   template<typename F> bool iterate(F f) const;
   198 }; // class Block
   198 }; // class Block
   199 
   199 
   200 inline OopStorage::Block* OopStorage::BlockList::head() {
   200 inline OopStorage::Block* OopStorage::AllocateList::head() {
   201   return const_cast<Block*>(_head);
   201   return const_cast<Block*>(_head);
   202 }
   202 }
   203 
   203 
   204 inline OopStorage::Block* OopStorage::BlockList::tail() {
   204 inline OopStorage::Block* OopStorage::AllocateList::tail() {
   205   return const_cast<Block*>(_tail);
   205   return const_cast<Block*>(_tail);
   206 }
   206 }
   207 
   207 
   208 inline const OopStorage::Block* OopStorage::BlockList::chead() const {
   208 inline const OopStorage::Block* OopStorage::AllocateList::chead() const {
   209   return _head;
   209   return _head;
   210 }
   210 }
   211 
   211 
   212 inline const OopStorage::Block* OopStorage::BlockList::ctail() const {
   212 inline const OopStorage::Block* OopStorage::AllocateList::ctail() const {
   213   return _tail;
   213   return _tail;
   214 }
   214 }
   215 
   215 
   216 inline OopStorage::Block* OopStorage::BlockList::prev(Block& block) {
   216 inline OopStorage::Block* OopStorage::AllocateList::prev(Block& block) {
   217   return const_cast<Block*>(_get_entry(block)._prev);
   217   return const_cast<Block*>(_get_entry(block)._prev);
   218 }
   218 }
   219 
   219 
   220 inline OopStorage::Block* OopStorage::BlockList::next(Block& block) {
   220 inline OopStorage::Block* OopStorage::AllocateList::next(Block& block) {
   221   return const_cast<Block*>(_get_entry(block)._next);
   221   return const_cast<Block*>(_get_entry(block)._next);
   222 }
   222 }
   223 
   223 
   224 inline const OopStorage::Block* OopStorage::BlockList::prev(const Block& block) const {
   224 inline const OopStorage::Block* OopStorage::AllocateList::prev(const Block& block) const {
   225   return _get_entry(block)._prev;
   225   return _get_entry(block)._prev;
   226 }
   226 }
   227 
   227 
   228 inline const OopStorage::Block* OopStorage::BlockList::next(const Block& block) const {
   228 inline const OopStorage::Block* OopStorage::AllocateList::next(const Block& block) const {
   229   return _get_entry(block)._next;
   229   return _get_entry(block)._next;
   230 }
   230 }
   231 
   231 
   232 template<typename Closure>
   232 template<typename Closure>
   233 class OopStorage::OopFn {
   233 class OopStorage::OopFn {
   355 inline bool OopStorage::iterate_impl(F f, Storage* storage) {
   355 inline bool OopStorage::iterate_impl(F f, Storage* storage) {
   356   assert_at_safepoint();
   356   assert_at_safepoint();
   357   // Propagate const/non-const iteration to the block layer, by using
   357   // Propagate const/non-const iteration to the block layer, by using
   358   // const or non-const blocks as corresponding to Storage.
   358   // const or non-const blocks as corresponding to Storage.
   359   typedef typename Conditional<IsConst<Storage>::value, const Block*, Block*>::type BlockPtr;
   359   typedef typename Conditional<IsConst<Storage>::value, const Block*, Block*>::type BlockPtr;
   360   BlockArray* blocks = storage->_active_array;
   360   ActiveArray* blocks = storage->_active_array;
   361   size_t limit = blocks->block_count();
   361   size_t limit = blocks->block_count();
   362   for (size_t i = 0; i < limit; ++i) {
   362   for (size_t i = 0; i < limit; ++i) {
   363     BlockPtr block = blocks->at(i);
   363     BlockPtr block = blocks->at(i);
   364     if (!block->iterate(f)) {
   364     if (!block->iterate(f)) {
   365       return false;
   365       return false;