src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 54970 76d3d96a8bc2
child 58679 9c3209ff7550
equal deleted inserted replaced
58677:13588c901957 58678:9cf78a70fa4f
    23  */
    23  */
    24 
    24 
    25 #ifndef SHARE_GC_G1_G1DIRTYCARDQUEUE_HPP
    25 #ifndef SHARE_GC_G1_G1DIRTYCARDQUEUE_HPP
    26 #define SHARE_GC_G1_G1DIRTYCARDQUEUE_HPP
    26 #define SHARE_GC_G1_G1DIRTYCARDQUEUE_HPP
    27 
    27 
    28 #include "gc/shared/cardTable.hpp"
    28 #include "gc/g1/g1BufferNodeList.hpp"
       
    29 #include "gc/g1/g1FreeIdSet.hpp"
    29 #include "gc/shared/ptrQueue.hpp"
    30 #include "gc/shared/ptrQueue.hpp"
    30 #include "memory/allocation.hpp"
    31 #include "memory/allocation.hpp"
    31 
    32 
    32 class G1DirtyCardQueueSet;
    33 class G1DirtyCardQueueSet;
    33 class G1FreeIdSet;
    34 class G1RedirtyCardsQueueSet;
    34 class Thread;
    35 class Thread;
    35 class Monitor;
    36 class Monitor;
    36 
       
    37 // A closure class for processing card table entries.  Note that we don't
       
    38 // require these closure objects to be stack-allocated.
       
    39 class G1CardTableEntryClosure: public CHeapObj<mtGC> {
       
    40 public:
       
    41   typedef CardTable::CardValue CardValue;
       
    42 
       
    43   // Process the card whose card table entry is "card_ptr".  If returns
       
    44   // "false", terminate the iteration early.
       
    45   virtual bool do_card_ptr(CardValue* card_ptr, uint worker_i) = 0;
       
    46 };
       
    47 
    37 
    48 // A ptrQueue whose elements are "oops", pointers to object heads.
    38 // A ptrQueue whose elements are "oops", pointers to object heads.
    49 class G1DirtyCardQueue: public PtrQueue {
    39 class G1DirtyCardQueue: public PtrQueue {
    50 protected:
    40 protected:
    51   virtual void handle_completed_buffer();
    41   virtual void handle_completed_buffer();
    74   using PtrQueue::byte_width_of_buf;
    64   using PtrQueue::byte_width_of_buf;
    75 
    65 
    76 };
    66 };
    77 
    67 
    78 class G1DirtyCardQueueSet: public PtrQueueSet {
    68 class G1DirtyCardQueueSet: public PtrQueueSet {
    79   // Apply the closure to the elements of "node" from it's index to
    69   Monitor* _cbl_mon;  // Protects the list and count members.
    80   // buffer_size.  If all closure applications return true, then
    70   BufferNode* _completed_buffers_head;
    81   // returns true.  Stops processing after the first closure
    71   BufferNode* _completed_buffers_tail;
    82   // application that returns false, and returns false from this
       
    83   // function.  If "consume" is true, the node's index is updated to
       
    84   // exclude the processed elements, e.g. up to the element for which
       
    85   // the closure returned false.
       
    86   bool apply_closure_to_buffer(G1CardTableEntryClosure* cl,
       
    87                                BufferNode* node,
       
    88                                bool consume,
       
    89                                uint worker_i = 0);
       
    90 
    72 
    91   // If there are more than stop_at completed buffers, pop one, apply
    73   // Number of actual cards in the list of completed buffers.
    92   // the specified closure to its active elements, and return true.
    74   volatile size_t _num_cards;
    93   // Otherwise return false.
    75 
    94   //
    76   size_t _process_cards_threshold;
    95   // A completely processed buffer is freed.  However, if a closure
    77   volatile bool _process_completed_buffers;
    96   // invocation returns false, processing is stopped and the partially
    78 
    97   // processed buffer (with its index updated to exclude the processed
    79   void abandon_completed_buffers();
    98   // elements, e.g. up to the element for which the closure returned
    80 
    99   // false) is returned to the completed buffer set.
    81   // Refine the cards in "node" from its index to buffer_size.
   100   //
    82   // Stops processing if SuspendibleThreadSet::should_yield() is true.
   101   // If during_pause is true, stop_at must be zero, and the closure
    83   // Returns true if the entire buffer was processed, false if there
   102   // must never return false.
    84   // is a pending yield request.  The node's index is updated to exclude
   103   bool apply_closure_to_completed_buffer(G1CardTableEntryClosure* cl,
    85   // the processed elements, e.g. up to the element before processing
   104                                          uint worker_i,
    86   // stopped, or one past the last element if the entire buffer was
   105                                          size_t stop_at,
    87   // processed. Increments *total_refined_cards by the number of cards
   106                                          bool during_pause);
    88   // processed and removed from the buffer.
       
    89   bool refine_buffer(BufferNode* node, uint worker_id, size_t* total_refined_cards);
   107 
    90 
   108   bool mut_process_buffer(BufferNode* node);
    91   bool mut_process_buffer(BufferNode* node);
   109 
    92 
   110   // If the queue contains more buffers than configured here, the
    93   // If the queue contains more cards than configured here, the
   111   // mutator must start doing some of the concurrent refinement work,
    94   // mutator must start doing some of the concurrent refinement work.
   112   size_t _max_completed_buffers;
    95   size_t _max_cards;
   113   size_t _completed_buffers_padding;
    96   size_t _max_cards_padding;
   114   static const size_t MaxCompletedBuffersUnlimited = ~size_t(0);
    97   static const size_t MaxCardsUnlimited = SIZE_MAX;
   115 
    98 
   116   G1FreeIdSet* _free_ids;
    99   G1FreeIdSet _free_ids;
   117 
   100 
   118   // The number of completed buffers processed by mutator and rs thread,
   101   // Array of cumulative dirty cards refined by mutator threads.
   119   // respectively.
   102   // Array has an entry per id in _free_ids.
   120   jint _processed_buffers_mut;
   103   size_t* _mutator_refined_cards_counters;
   121   jint _processed_buffers_rs_thread;
       
   122 
       
   123   // Current buffer node used for parallel iteration.
       
   124   BufferNode* volatile _cur_par_buffer_node;
       
   125 
   104 
   126 public:
   105 public:
   127   G1DirtyCardQueueSet(bool notify_when_complete = true);
   106   G1DirtyCardQueueSet(Monitor* cbl_mon, BufferNode::Allocator* allocator);
   128   ~G1DirtyCardQueueSet();
   107   ~G1DirtyCardQueueSet();
   129 
       
   130   void initialize(Monitor* cbl_mon,
       
   131                   BufferNode::Allocator* allocator,
       
   132                   bool init_free_ids = false);
       
   133 
   108 
   134   // The number of parallel ids that can be claimed to allow collector or
   109   // The number of parallel ids that can be claimed to allow collector or
   135   // mutator threads to do card-processing work.
   110   // mutator threads to do card-processing work.
   136   static uint num_par_ids();
   111   static uint num_par_ids();
   137 
   112 
   140   // Either process the entire buffer and return true, or enqueue the
   115   // Either process the entire buffer and return true, or enqueue the
   141   // buffer and return false.  If the buffer is completely processed,
   116   // buffer and return false.  If the buffer is completely processed,
   142   // it can be reused in place.
   117   // it can be reused in place.
   143   bool process_or_enqueue_completed_buffer(BufferNode* node);
   118   bool process_or_enqueue_completed_buffer(BufferNode* node);
   144 
   119 
   145   // Apply G1RefineCardConcurrentlyClosure to completed buffers until there are stop_at
   120   virtual void enqueue_completed_buffer(BufferNode* node);
   146   // completed buffers remaining.
       
   147   bool refine_completed_buffer_concurrently(uint worker_i, size_t stop_at);
       
   148 
   121 
   149   // Apply the given closure to all completed buffers. The given closure's do_card_ptr
   122   // If the number of completed buffers is > stop_at, then remove and
   150   // must never return false. Must only be called during GC.
   123   // return a completed buffer from the list.  Otherwise, return NULL.
   151   bool apply_closure_during_gc(G1CardTableEntryClosure* cl, uint worker_i);
   124   BufferNode* get_completed_buffer(size_t stop_at = 0);
   152 
   125 
   153   void reset_for_par_iteration() { _cur_par_buffer_node = completed_buffers_head(); }
   126   // The number of cards in completed buffers. Read without synchronization.
   154   // Applies the current closure to all completed buffers, non-consumptively.
   127   size_t num_cards() const { return _num_cards; }
   155   // Can be used in parallel, all callers using the iteration state initialized
       
   156   // by reset_for_par_iteration.
       
   157   void par_apply_closure_to_all_completed_buffers(G1CardTableEntryClosure* cl);
       
   158 
   128 
   159   // If a full collection is happening, reset partial logs, and ignore
   129   // Verify that _num_cards is equal to the sum of actual cards
       
   130   // in the completed buffers.
       
   131   void verify_num_cards() const NOT_DEBUG_RETURN;
       
   132 
       
   133   bool process_completed_buffers() { return _process_completed_buffers; }
       
   134   void set_process_completed_buffers(bool x) { _process_completed_buffers = x; }
       
   135 
       
   136   // Get/Set the number of cards that triggers log processing.
       
   137   // Log processing should be done when the number of cards exceeds the
       
   138   // threshold.
       
   139   void set_process_cards_threshold(size_t sz) {
       
   140     _process_cards_threshold = sz;
       
   141   }
       
   142   size_t process_cards_threshold() const {
       
   143     return _process_cards_threshold;
       
   144   }
       
   145   static const size_t ProcessCardsThresholdNever = SIZE_MAX;
       
   146 
       
   147   // Notify the consumer if the number of buffers crossed the threshold
       
   148   void notify_if_necessary();
       
   149 
       
   150   void merge_bufferlists(G1RedirtyCardsQueueSet* src);
       
   151 
       
   152   G1BufferNodeList take_all_completed_buffers();
       
   153 
       
   154   // If there are more than stop_at cards in the completed buffers, pop
       
   155   // a buffer, refine its contents, and return true.  Otherwise return
       
   156   // false.
       
   157   //
       
   158   // Stops processing a buffer if SuspendibleThreadSet::should_yield(),
       
   159   // returning the incompletely processed buffer to the completed buffer
       
   160   // list, for later processing of the remainder.
       
   161   //
       
   162   // Increments *total_refined_cards by the number of cards processed and
       
   163   // removed from the buffer.
       
   164   bool refine_completed_buffer_concurrently(uint worker_id,
       
   165                                             size_t stop_at,
       
   166                                             size_t* total_refined_cards);
       
   167 
       
   168   // If a full collection is happening, reset partial logs, and release
   160   // completed ones: the full collection will make them all irrelevant.
   169   // completed ones: the full collection will make them all irrelevant.
   161   void abandon_logs();
   170   void abandon_logs();
   162 
   171 
   163   // If any threads have partial logs, add them to the global list of logs.
   172   // If any threads have partial logs, add them to the global list of logs.
   164   void concatenate_logs();
   173   void concatenate_logs();
   165 
   174 
   166   void set_max_completed_buffers(size_t m) {
   175   void set_max_cards(size_t m) {
   167     _max_completed_buffers = m;
   176     _max_cards = m;
   168   }
   177   }
   169   size_t max_completed_buffers() const {
   178   size_t max_cards() const {
   170     return _max_completed_buffers;
   179     return _max_cards;
   171   }
   180   }
   172 
   181 
   173   void set_completed_buffers_padding(size_t padding) {
   182   void set_max_cards_padding(size_t padding) {
   174     _completed_buffers_padding = padding;
   183     _max_cards_padding = padding;
   175   }
   184   }
   176   size_t completed_buffers_padding() const {
   185   size_t max_cards_padding() const {
   177     return _completed_buffers_padding;
   186     return _max_cards_padding;
   178   }
   187   }
   179 
   188 
   180   jint processed_buffers_mut() {
   189   // Total dirty cards refined by mutator threads.
   181     return _processed_buffers_mut;
   190   size_t total_mutator_refined_cards() const;
   182   }
       
   183   jint processed_buffers_rs_thread() {
       
   184     return _processed_buffers_rs_thread;
       
   185   }
       
   186 
       
   187 };
   191 };
   188 
   192 
   189 inline G1DirtyCardQueueSet* G1DirtyCardQueue::dirty_card_qset() const {
   193 inline G1DirtyCardQueueSet* G1DirtyCardQueue::dirty_card_qset() const {
   190   return static_cast<G1DirtyCardQueueSet*>(qset());
   194   return static_cast<G1DirtyCardQueueSet*>(qset());
   191 }
   195 }