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

Fri, 10 Oct 2014 15:51:58 +0200

author
tschatzl
date
Fri, 10 Oct 2014 15:51:58 +0200
changeset 7257
e7d0505c8a30
parent 6930
570cb6369f17
child 7476
c2844108a708
permissions
-rw-r--r--

8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso

ysr@777 1 /*
mikael@4153 2 * Copyright (c) 2001, 2012, 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
stefank@2314 25 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_DIRTYCARDQUEUE_HPP
stefank@2314 26 #define SHARE_VM_GC_IMPLEMENTATION_G1_DIRTYCARDQUEUE_HPP
stefank@2314 27
stefank@2314 28 #include "gc_implementation/g1/ptrQueue.hpp"
stefank@2314 29 #include "memory/allocation.hpp"
stefank@2314 30
ysr@777 31 class FreeIdSet;
ysr@777 32
ysr@777 33 // A closure class for processing card table entries. Note that we don't
ysr@777 34 // require these closure objects to be stack-allocated.
zgu@3900 35 class CardTableEntryClosure: public CHeapObj<mtGC> {
ysr@777 36 public:
ysr@777 37 // Process the card whose card table entry is "card_ptr". If returns
ysr@777 38 // "false", terminate the iteration early.
vkempik@6552 39 virtual bool do_card_ptr(jbyte* card_ptr, uint worker_i = 0) = 0;
ysr@777 40 };
ysr@777 41
ysr@777 42 // A ptrQueue whose elements are "oops", pointers to object heads.
ysr@777 43 class DirtyCardQueue: public PtrQueue {
ysr@777 44 public:
ysr@777 45 DirtyCardQueue(PtrQueueSet* qset_, bool perm = false) :
tonyp@2197 46 // Dirty card queues are always active, so we create them with their
tonyp@2197 47 // active field set to true.
tonyp@2197 48 PtrQueue(qset_, perm, true /* active */) { }
tonyp@2197 49
ysr@777 50 // Apply the closure to all elements, and reset the index to make the
ysr@777 51 // buffer empty. If a closure application returns "false", return
ysr@777 52 // "false" immediately, halting the iteration. If "consume" is true,
ysr@777 53 // deletes processed entries from logs.
ysr@777 54 bool apply_closure(CardTableEntryClosure* cl,
ysr@777 55 bool consume = true,
vkempik@6552 56 uint worker_i = 0);
ysr@777 57
ysr@777 58 // Apply the closure to all elements of "buf", down to "index"
ysr@777 59 // (inclusive.) If returns "false", then a closure application returned
ysr@777 60 // "false", and we return immediately. If "consume" is true, entries are
ysr@777 61 // set to NULL as they are processed, so they will not be processed again
ysr@777 62 // later.
ysr@777 63 static bool apply_closure_to_buffer(CardTableEntryClosure* cl,
ysr@777 64 void** buf, size_t index, size_t sz,
ysr@777 65 bool consume = true,
vkempik@6552 66 uint worker_i = 0);
ysr@777 67 void **get_buf() { return _buf;}
ysr@777 68 void set_buf(void **buf) {_buf = buf;}
ysr@777 69 size_t get_index() { return _index;}
ysr@777 70 void reinitialize() { _buf = 0; _sz = 0; _index = 0;}
ysr@777 71 };
ysr@777 72
ysr@777 73
ysr@777 74
ysr@777 75 class DirtyCardQueueSet: public PtrQueueSet {
tschatzl@6930 76 // The closure used in mut_process_buffer().
tschatzl@6930 77 CardTableEntryClosure* _mut_process_closure;
ysr@777 78
ysr@777 79 DirtyCardQueue _shared_dirty_card_queue;
ysr@777 80
ysr@777 81 // Override.
ysr@777 82 bool mut_process_buffer(void** buf);
ysr@777 83
ysr@777 84 // Protected by the _cbl_mon.
ysr@777 85 FreeIdSet* _free_ids;
ysr@777 86
ysr@777 87 // The number of completed buffers processed by mutator and rs thread,
ysr@777 88 // respectively.
ysr@777 89 jint _processed_buffers_mut;
ysr@777 90 jint _processed_buffers_rs_thread;
ysr@777 91
tschatzl@6930 92 // Current buffer node used for parallel iteration.
tschatzl@6930 93 BufferNode* volatile _cur_par_buffer_node;
ysr@777 94 public:
iveresov@1546 95 DirtyCardQueueSet(bool notify_when_complete = true);
ysr@777 96
tschatzl@6930 97 void initialize(CardTableEntryClosure* cl, Monitor* cbl_mon, Mutex* fl_lock,
iveresov@1546 98 int process_completed_threshold,
iveresov@1546 99 int max_completed_queue,
iveresov@1546 100 Mutex* lock, PtrQueueSet* fl_owner = NULL);
ysr@777 101
ysr@777 102 // The number of parallel ids that can be claimed to allow collector or
ysr@777 103 // mutator threads to do card-processing work.
vkempik@6552 104 static uint num_par_ids();
ysr@777 105
ysr@777 106 static void handle_zero_index_for_thread(JavaThread* t);
ysr@777 107
tschatzl@6930 108 // Apply the given closure to all entries in all currently-active buffers.
tschatzl@6930 109 // This should only be applied at a safepoint. (Currently must not be called
tschatzl@6930 110 // in parallel; this should change in the future.) If "consume" is true,
tschatzl@6930 111 // processed entries are discarded.
tschatzl@6930 112 void iterate_closure_all_threads(CardTableEntryClosure* cl,
tschatzl@6930 113 bool consume = true,
vkempik@6552 114 uint worker_i = 0);
ysr@777 115
ysr@777 116 // If there exists some completed buffer, pop it, then apply the
johnc@2060 117 // specified closure to all its elements, nulling out those elements
johnc@2060 118 // processed. If all elements are processed, returns "true". If no
johnc@2060 119 // completed buffers exist, returns false. If a completed buffer exists,
johnc@2060 120 // but is only partially completed before a "yield" happens, the
johnc@2060 121 // partially completed buffer (with its processed elements set to NULL)
johnc@2060 122 // is returned to the completed buffer set, and this call returns false.
johnc@2060 123 bool apply_closure_to_completed_buffer(CardTableEntryClosure* cl,
vkempik@6552 124 uint worker_i = 0,
johnc@2060 125 int stop_at = 0,
johnc@2060 126 bool during_pause = false);
johnc@2060 127
johnc@2060 128 // Helper routine for the above.
johnc@2060 129 bool apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl,
vkempik@6552 130 uint worker_i,
iveresov@1546 131 BufferNode* nd);
ysr@777 132
iveresov@1546 133 BufferNode* get_completed_buffer(int stop_at);
johnc@1525 134
ysr@777 135 // Applies the current closure to all completed buffers,
ysr@777 136 // non-consumptively.
tschatzl@6930 137 void apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl);
tschatzl@6930 138
tschatzl@6930 139 void reset_for_par_iteration() { _cur_par_buffer_node = _completed_buffers_head; }
tschatzl@6930 140 // Applies the current closure to all completed buffers, non-consumptively.
tschatzl@6930 141 // Parallel version.
tschatzl@6930 142 void par_apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl);
ysr@777 143
ysr@777 144 DirtyCardQueue* shared_dirty_card_queue() {
ysr@777 145 return &_shared_dirty_card_queue;
ysr@777 146 }
ysr@777 147
johnc@2060 148 // Deallocate any completed log buffers
johnc@2060 149 void clear();
johnc@2060 150
ysr@777 151 // If a full collection is happening, reset partial logs, and ignore
ysr@777 152 // completed ones: the full collection will make them all irrelevant.
ysr@777 153 void abandon_logs();
ysr@777 154
ysr@777 155 // If any threads have partial logs, add them to the global list of logs.
ysr@777 156 void concatenate_logs();
ysr@777 157 void clear_n_completed_buffers() { _n_completed_buffers = 0;}
ysr@777 158
ysr@777 159 jint processed_buffers_mut() {
ysr@777 160 return _processed_buffers_mut;
ysr@777 161 }
ysr@777 162 jint processed_buffers_rs_thread() {
ysr@777 163 return _processed_buffers_rs_thread;
ysr@777 164 }
ysr@777 165
ysr@777 166 };
stefank@2314 167
stefank@2314 168 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_DIRTYCARDQUEUE_HPP

mercurial