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_HPP
 26 #define SHARE_GC_SHARED_OOPSTORAGE_HPP
 27 
 28 #include "memory/allocation.hpp"
 29 #include "oops/oop.hpp"
 30 #include "utilities/globalDefinitions.hpp"
 31 #include "utilities/macros.hpp"
 32 #include "utilities/singleWriterSynchronizer.hpp"
 33 
 34 class Mutex;
 35 class outputStream;
 36 
 37 // OopStorage supports management of off-heap references to objects allocated
 38 // in the Java heap.  An OopStorage object provides a set of Java object
 39 // references (oop values), which clients refer to via oop* handles to the
 40 // associated OopStorage entries.  Clients allocate entries to create a
 41 // (possibly weak) reference to a Java object, use that reference, and release
 42 // the reference when no longer needed.
 43 //
 44 // The garbage collector must know about all OopStorage objects and their
 45 // reference strength.  OopStorage provides the garbage collector with support
 46 // for iteration over all the allocated entries.
 47 //
 48 // There are several categories of interaction with an OopStorage object.
 49 //
 50 // (1) allocation and release of entries, by the mutator or the VM.
 51 // (2) iteration by the garbage collector, possibly concurrent with mutator.
 52 // (3) iteration by other, non-GC, tools (only at safepoints).
 53 // (4) cleanup of unused internal storage, possibly concurrent with mutator.
 54 //
 55 // A goal of OopStorage is to make these interactions thread-safe, while
 56 // minimizing potential lock contention issues within and between these
 57 // categories.  In particular, support for concurrent iteration by the garbage
 58 // collector, under certain restrictions, is required.  Further, it must not
 59 // block nor be blocked by other operations for long periods.
 60 //
 61 // Internally, OopStorage is a set of Block objects, from which entries are
 62 // allocated and released.  A block contains an oop[] and a bitmask indicating
 63 // which entries are in use (have been allocated and not yet released).  New
 64 // blocks are constructed and added to the storage object when an entry
 65 // allocation request is made and there are no blocks with unused entries.
 66 // Blocks may be removed and deleted when empty.
 67 //
 68 // There are two important (and somewhat intertwined) protocols governing
 69 // concurrent access to a storage object.  These are the Concurrent Iteration
 70 // Protocol and the Allocation Protocol.  See the ParState class for a
 71 // discussion of concurrent iteration and the management of thread
 72 // interactions for this protocol.  Similarly, see the allocate() function for
 73 // a discussion of allocation.
 74 
 75 class OopStorage : public CHeapObj<mtGC> {
 76 public:
 77   // GC notification support.
 78   typedef void (*NotificationFunction)(size_t dead_count);
 79 
 80   OopStorage(const char* name, Mutex* allocation_mutex, Mutex* active_mutex, NotificationFunction f = NULL);
 81   ~OopStorage();
 82 
 83   // These count and usage accessors are racy unless at a safepoint.
 84 
 85   // The number of allocated and not yet released entries.
 86   size_t allocation_count() const;
 87 
 88   // The number of blocks of entries.  Useful for sizing parallel iteration.
 89   size_t block_count() const;
 90 
 91   // Total number of blocks * memory allocation per block, plus
 92   // bookkeeping overhead, including this storage object.
 93   size_t total_memory_usage() const;
 94 
 95   enum EntryStatus {
 96     INVALID_ENTRY,
 97     UNALLOCATED_ENTRY,
 98     ALLOCATED_ENTRY
 99   };
100 
101   // Locks _allocation_mutex.
102   // precondition: ptr != NULL.
103   EntryStatus allocation_status(const oop* ptr) const;
104 
105   // Allocates and returns a new entry.  Returns NULL if memory allocation
106   // failed.  Locks _allocation_mutex.
107   // postcondition: *result == NULL.
108   oop* allocate();
109 
110   // Deallocates ptr.  No locking.
111   // precondition: ptr is a valid allocated entry.
112   // precondition: *ptr == NULL.
113   void release(const oop* ptr);
114 
115   // Releases all the ptrs.  Possibly faster than individual calls to
116   // release(oop*).  Best if ptrs is sorted by address.  No locking.
117   // precondition: All elements of ptrs are valid allocated entries.
118   // precondition: *ptrs[i] == NULL, for i in [0,size).
119   void release(const oop* const* ptrs, size_t size);
120 
121   // Applies f to each allocated entry's location.  f must be a function or
122   // function object.  Assume p is either a const oop* or an oop*, depending
123   // on whether the associated storage is const or non-const, respectively.
124   // Then f(p) must be a valid expression.  The result of invoking f(p) must
125   // be implicitly convertible to bool.  Iteration terminates and returns
126   // false if any invocation of f returns false.  Otherwise, the result of
127   // iteration is true.
128   // precondition: at safepoint.
129   template<typename F> inline bool iterate_safepoint(F f);
130   template<typename F> inline bool iterate_safepoint(F f) const;
131 
132   // oops_do and weak_oops_do are wrappers around iterate_safepoint, providing
133   // an adaptation layer allowing the use of existing is-alive closures and
134   // OopClosures.  Assume p is either const oop* or oop*, depending on whether
135   // the associated storage is const or non-const, respectively.  Then
136   //
137   // - closure->do_oop(p) must be a valid expression whose value is ignored.
138   //
139   // - is_alive->do_object_b(*p) must be a valid expression whose value is
140   // convertible to bool.
141   //
142   // For weak_oops_do, if *p == NULL then neither is_alive nor closure will be
143   // invoked for p.  If is_alive->do_object_b(*p) is false, then closure will
144   // not be invoked on p, and *p will be set to NULL.
145 
146   template<typename Closure> inline void oops_do(Closure* closure);
147   template<typename Closure> inline void oops_do(Closure* closure) const;
148   template<typename Closure> inline void weak_oops_do(Closure* closure);
149 
150   template<typename IsAliveClosure, typename Closure>
151   inline void weak_oops_do(IsAliveClosure* is_alive, Closure* closure);
152 
153   // Parallel iteration is for the exclusive use of the GC.
154   // Other clients must use serial iteration.
155   template<bool concurrent, bool is_const> class ParState;
156 
157   // This function is called by the GC to notify the registered notification function.
158   void notify(size_t num_dead) const;
159 
160   // Checks if the given OopStorage has an associated notification function for the GC.
161   bool can_notify() const;
162 
163   // Service thread cleanup support.
164 
165   // Called by the service thread to process any pending cleanups for this
166   // storage object.  Drains the _deferred_updates list, and deletes empty
167   // blocks.  Stops deleting if there is an in-progress concurrent
168   // iteration.  Locks both the _allocation_mutex and the _active_mutex, and
169   // may safepoint.  Deletion may be throttled, with only some available
170   // work performed, in order to allow other Service thread subtasks to run.
171   // Returns true if there may be more work to do, false if nothing to do.
172   bool delete_empty_blocks();
173 
174   // Called by safepoint cleanup to notify the service thread (via
175   // Service_lock) that there may be some OopStorage objects with pending
176   // cleanups to process.
177   static void trigger_cleanup_if_needed();
178 
179   // Called by the service thread (while holding Service_lock) to to test
180   // for pending cleanup requests, and resets the request state to allow
181   // recognition of new requests.  Returns true if there was a pending
182   // request.
183   static bool has_cleanup_work_and_reset();
184 
185   // Debugging and logging support.
186   const char* name() const;
187   void print_on(outputStream* st) const PRODUCT_RETURN;
188 
189   // Provides access to storage internals, for unit testing.
190   // Declare, but not define, the public class OopStorage::TestAccess.
191   // That class is defined as part of the unit-test. It "exports" the needed
192   // private types by providing public typedefs for them.
193   class TestAccess;
194 
195 private:
196   class Block;                  // Fixed-size array of oops, plus bookkeeping.
197   class ActiveArray;            // Array of Blocks, plus bookkeeping.
198   class AllocationListEntry;    // Provides AllocationList links in a Block.
199 
200   // Doubly-linked list of Blocks.
201   class AllocationList {
202     const Block* _head;
203     const Block* _tail;
204 
205     NONCOPYABLE(AllocationList);
206 
207   public:
208     AllocationList();
209     ~AllocationList();
210 
211     Block* head();
212     Block* tail();
213     const Block* chead() const;
214     const Block* ctail() const;
215 
216     Block* prev(Block& block);
217     Block* next(Block& block);
218 
219     const Block* prev(const Block& block) const;
220     const Block* next(const Block& block) const;
221 
222     void push_front(const Block& block);
223     void push_back(const Block& block);
224     void unlink(const Block& block);
225   };
226 
227 private:
228   const char* _name;
229   ActiveArray* _active_array;
230   AllocationList _allocation_list;
231   Block* volatile _deferred_updates;
232   Mutex* _allocation_mutex;
233   Mutex* _active_mutex;
234 
235   // Volatile for racy unlocked accesses.
236   volatile size_t _allocation_count;
237 
238   // Protection for _active_array.
239   mutable SingleWriterSynchronizer _protect_active;
240 
241   // mutable because this gets set even for const iteration.
242   mutable int _concurrent_iteration_count;
243 
244   volatile bool _needs_cleanup;
245 
246   NotificationFunction _notification_function;
247 
248   bool try_add_block();
249   Block* block_for_allocation();
250 
251   Block* find_block_or_null(const oop* ptr) const;
252   void delete_empty_block(const Block& block);
253   bool reduce_deferred_updates();
254   void record_needs_cleanup();
255 
256   // Managing _active_array.
257   bool expand_active_array();
258   void replace_active_array(ActiveArray* new_array);
259   ActiveArray* obtain_active_array() const;
260   void relinquish_block_array(ActiveArray* array) const;
261   class WithActiveArray;        // RAII helper for active array access.
262 
263   template<typename F, typename Storage>
264   static bool iterate_impl(F f, Storage* storage);
265 
266   // Implementation support for parallel iteration
267   class BasicParState;
268 
269   // Wrapper for OopClosure-style function, so it can be used with
270   // iterate.  Assume p is of type oop*.  Then cl->do_oop(p) must be a
271   // valid expression whose value may be ignored.
272   template<typename Closure> class OopFn;
273   template<typename Closure> static OopFn<Closure> oop_fn(Closure* cl);
274 
275   // Wrapper for BoolObjectClosure + iteration handler pair, so they
276   // can be used with iterate.
277   template<typename IsAlive, typename F> class IfAliveFn;
278   template<typename IsAlive, typename F>
279   static IfAliveFn<IsAlive, F> if_alive_fn(IsAlive* is_alive, F f);
280 
281   // Wrapper for iteration handler, automatically skipping NULL entries.
282   template<typename F> class SkipNullFn;
283   template<typename F> static SkipNullFn<F> skip_null_fn(F f);
284 };
285 
286 #endif // SHARE_GC_SHARED_OOPSTORAGE_HPP