src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp

Mon, 02 Aug 2010 12:51:43 -0700

author
johnc
date
Mon, 02 Aug 2010 12:51:43 -0700
changeset 2060
2d160770d2e5
parent 1907
c18cbe5936b8
child 2197
6e0aac35bfa9
permissions
-rw-r--r--

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

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

mercurial