annotate src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp @ 1727:2d160770d2e5

6814437: G1: remove the _new_refs array Summary: The per-worker _new_refs array is used to hold references that point into the collection set. It is populated during RSet updating and subsequently processed. In the event of an evacuation failure it processed again to recreate the RSets of regions in the collection set. Remove the per-worker _new_refs array by processing the references directly. Use a DirtyCardQueue to hold the cards containing the references so that the RSets of regions in the collection set can be recreated when handling an evacuation failure. Reviewed-by: iveresov, jmasa, tonyp
author johnc
date Mon, 02 Aug 2010 12:51:43 -0700
parents c18cbe5936b8
children 6e0aac35bfa9
rev   line source
ysr@345 1 /*
johnc@1727 2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
ysr@345 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ysr@345 4 *
ysr@345 5 * This code is free software; you can redistribute it and/or modify it
ysr@345 6 * under the terms of the GNU General Public License version 2 only, as
ysr@345 7 * published by the Free Software Foundation.
ysr@345 8 *
ysr@345 9 * This code is distributed in the hope that it will be useful, but WITHOUT
ysr@345 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ysr@345 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ysr@345 12 * version 2 for more details (a copy is included in the LICENSE file that
ysr@345 13 * accompanied this code).
ysr@345 14 *
ysr@345 15 * You should have received a copy of the GNU General Public License version
ysr@345 16 * 2 along with this work; if not, write to the Free Software Foundation,
ysr@345 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ysr@345 18 *
trims@1563 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1563 20 * or visit www.oracle.com if you need additional information or have any
trims@1563 21 * questions.
ysr@345 22 *
ysr@345 23 */
ysr@345 24
ysr@345 25 class FreeIdSet;
ysr@345 26
ysr@345 27 // A closure class for processing card table entries. Note that we don't
ysr@345 28 // require these closure objects to be stack-allocated.
ysr@345 29 class CardTableEntryClosure: public CHeapObj {
ysr@345 30 public:
ysr@345 31 // Process the card whose card table entry is "card_ptr". If returns
ysr@345 32 // "false", terminate the iteration early.
ysr@345 33 virtual bool do_card_ptr(jbyte* card_ptr, int worker_i = 0) = 0;
ysr@345 34 };
ysr@345 35
ysr@345 36 // A ptrQueue whose elements are "oops", pointers to object heads.
ysr@345 37 class DirtyCardQueue: public PtrQueue {
ysr@345 38 public:
ysr@345 39 DirtyCardQueue(PtrQueueSet* qset_, bool perm = false) :
ysr@345 40 PtrQueue(qset_, perm)
ysr@345 41 {
ysr@345 42 // Dirty card queues are always active.
ysr@345 43 _active = true;
ysr@345 44 }
ysr@345 45 // Apply the closure to all elements, and reset the index to make the
ysr@345 46 // buffer empty. If a closure application returns "false", return
ysr@345 47 // "false" immediately, halting the iteration. If "consume" is true,
ysr@345 48 // deletes processed entries from logs.
ysr@345 49 bool apply_closure(CardTableEntryClosure* cl,
ysr@345 50 bool consume = true,
ysr@345 51 size_t worker_i = 0);
ysr@345 52
ysr@345 53 // Apply the closure to all elements of "buf", down to "index"
ysr@345 54 // (inclusive.) If returns "false", then a closure application returned
ysr@345 55 // "false", and we return immediately. If "consume" is true, entries are
ysr@345 56 // set to NULL as they are processed, so they will not be processed again
ysr@345 57 // later.
ysr@345 58 static bool apply_closure_to_buffer(CardTableEntryClosure* cl,
ysr@345 59 void** buf, size_t index, size_t sz,
ysr@345 60 bool consume = true,
ysr@345 61 int worker_i = 0);
ysr@345 62 void **get_buf() { return _buf;}
ysr@345 63 void set_buf(void **buf) {_buf = buf;}
ysr@345 64 size_t get_index() { return _index;}
ysr@345 65 void reinitialize() { _buf = 0; _sz = 0; _index = 0;}
ysr@345 66 };
ysr@345 67
ysr@345 68
ysr@345 69
ysr@345 70 class DirtyCardQueueSet: public PtrQueueSet {
ysr@345 71 CardTableEntryClosure* _closure;
ysr@345 72
ysr@345 73 DirtyCardQueue _shared_dirty_card_queue;
ysr@345 74
ysr@345 75 // Override.
ysr@345 76 bool mut_process_buffer(void** buf);
ysr@345 77
ysr@345 78 // Protected by the _cbl_mon.
ysr@345 79 FreeIdSet* _free_ids;
ysr@345 80
ysr@345 81 // The number of completed buffers processed by mutator and rs thread,
ysr@345 82 // respectively.
ysr@345 83 jint _processed_buffers_mut;
ysr@345 84 jint _processed_buffers_rs_thread;
ysr@345 85
ysr@345 86 public:
iveresov@1185 87 DirtyCardQueueSet(bool notify_when_complete = true);
ysr@345 88
ysr@345 89 void initialize(Monitor* cbl_mon, Mutex* fl_lock,
iveresov@1185 90 int process_completed_threshold,
iveresov@1185 91 int max_completed_queue,
iveresov@1185 92 Mutex* lock, PtrQueueSet* fl_owner = NULL);
ysr@345 93
ysr@345 94 // The number of parallel ids that can be claimed to allow collector or
ysr@345 95 // mutator threads to do card-processing work.
ysr@345 96 static size_t num_par_ids();
ysr@345 97
ysr@345 98 static void handle_zero_index_for_thread(JavaThread* t);
ysr@345 99
ysr@345 100 // Register "blk" as "the closure" for all queues. Only one such closure
ysr@345 101 // is allowed. The "apply_closure_to_completed_buffer" method will apply
ysr@345 102 // this closure to a completed buffer, and "iterate_closure_all_threads"
ysr@345 103 // applies it to partially-filled buffers (the latter should only be done
ysr@345 104 // with the world stopped).
ysr@345 105 void set_closure(CardTableEntryClosure* closure);
ysr@345 106
ysr@345 107 // If there is a registered closure for buffers, apply it to all entries
ysr@345 108 // in all currently-active buffers. This should only be applied at a
ysr@345 109 // safepoint. (Currently must not be called in parallel; this should
ysr@345 110 // change in the future.) If "consume" is true, processed entries are
ysr@345 111 // discarded.
ysr@345 112 void iterate_closure_all_threads(bool consume = true,
ysr@345 113 size_t worker_i = 0);
ysr@345 114
ysr@345 115 // If there exists some completed buffer, pop it, then apply the
ysr@345 116 // registered closure to all its elements, nulling out those elements
ysr@345 117 // processed. If all elements are processed, returns "true". If no
ysr@345 118 // completed buffers exist, returns false. If a completed buffer exists,
ysr@345 119 // but is only partially completed before a "yield" happens, the
ysr@345 120 // partially completed buffer (with its processed elements set to NULL)
ysr@345 121 // is returned to the completed buffer set, and this call returns false.
ysr@345 122 bool apply_closure_to_completed_buffer(int worker_i = 0,
ysr@345 123 int stop_at = 0,
johnc@1164 124 bool during_pause = false);
johnc@1164 125
johnc@1727 126 // If there exists some completed buffer, pop it, then apply the
johnc@1727 127 // specified closure to all its elements, nulling out those elements
johnc@1727 128 // processed. If all elements are processed, returns "true". If no
johnc@1727 129 // completed buffers exist, returns false. If a completed buffer exists,
johnc@1727 130 // but is only partially completed before a "yield" happens, the
johnc@1727 131 // partially completed buffer (with its processed elements set to NULL)
johnc@1727 132 // is returned to the completed buffer set, and this call returns false.
johnc@1727 133 bool apply_closure_to_completed_buffer(CardTableEntryClosure* cl,
johnc@1727 134 int worker_i = 0,
johnc@1727 135 int stop_at = 0,
johnc@1727 136 bool during_pause = false);
johnc@1727 137
johnc@1727 138 // Helper routine for the above.
johnc@1727 139 bool apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl,
johnc@1727 140 int worker_i,
iveresov@1185 141 BufferNode* nd);
ysr@345 142
iveresov@1185 143 BufferNode* get_completed_buffer(int stop_at);
johnc@1164 144
ysr@345 145 // Applies the current closure to all completed buffers,
ysr@345 146 // non-consumptively.
ysr@345 147 void apply_closure_to_all_completed_buffers();
ysr@345 148
ysr@345 149 DirtyCardQueue* shared_dirty_card_queue() {
ysr@345 150 return &_shared_dirty_card_queue;
ysr@345 151 }
ysr@345 152
johnc@1727 153 // Deallocate any completed log buffers
johnc@1727 154 void clear();
johnc@1727 155
ysr@345 156 // If a full collection is happening, reset partial logs, and ignore
ysr@345 157 // completed ones: the full collection will make them all irrelevant.
ysr@345 158 void abandon_logs();
ysr@345 159
ysr@345 160 // If any threads have partial logs, add them to the global list of logs.
ysr@345 161 void concatenate_logs();
ysr@345 162 void clear_n_completed_buffers() { _n_completed_buffers = 0;}
ysr@345 163
ysr@345 164 jint processed_buffers_mut() {
ysr@345 165 return _processed_buffers_mut;
ysr@345 166 }
ysr@345 167 jint processed_buffers_rs_thread() {
ysr@345 168 return _processed_buffers_rs_thread;
ysr@345 169 }
ysr@345 170
ysr@345 171 };