src/share/vm/gc_implementation/g1/g1StringDedupQueue.cpp

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

author
tschatzl
date
Fri, 10 Oct 2014 15:51:58 +0200
changeset 7257
e7d0505c8a30
parent 6690
1772223a25a2
child 6876
710a3c8b516e
child 9327
f96fcd9e1e1b
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

pliden@6413 1 /*
pliden@6413 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
pliden@6413 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
pliden@6413 4 *
pliden@6413 5 * This code is free software; you can redistribute it and/or modify it
pliden@6413 6 * under the terms of the GNU General Public License version 2 only, as
pliden@6413 7 * published by the Free Software Foundation.
pliden@6413 8 *
pliden@6413 9 * This code is distributed in the hope that it will be useful, but WITHOUT
pliden@6413 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
pliden@6413 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
pliden@6413 12 * version 2 for more details (a copy is included in the LICENSE file that
pliden@6413 13 * accompanied this code).
pliden@6413 14 *
pliden@6413 15 * You should have received a copy of the GNU General Public License version
pliden@6413 16 * 2 along with this work; if not, write to the Free Software Foundation,
pliden@6413 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
pliden@6413 18 *
pliden@6413 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
pliden@6413 20 * or visit www.oracle.com if you need additional information or have any
pliden@6413 21 * questions.
pliden@6413 22 *
pliden@6413 23 */
pliden@6413 24
pliden@6413 25 #include "precompiled.hpp"
pliden@6413 26 #include "classfile/javaClasses.hpp"
pliden@6413 27 #include "gc_implementation/g1/g1StringDedupQueue.hpp"
pliden@6413 28 #include "memory/gcLocker.hpp"
pliden@6413 29 #include "runtime/mutexLocker.hpp"
pliden@6413 30 #include "utilities/stack.inline.hpp"
pliden@6413 31
pliden@6413 32 G1StringDedupQueue* G1StringDedupQueue::_queue = NULL;
pliden@6413 33 const size_t G1StringDedupQueue::_max_size = 1000000; // Max number of elements per queue
pliden@6413 34 const size_t G1StringDedupQueue::_max_cache_size = 0; // Max cache size per queue
pliden@6413 35
pliden@6413 36 G1StringDedupQueue::G1StringDedupQueue() :
pliden@6413 37 _cursor(0),
pliden@6690 38 _cancel(false),
pliden@6413 39 _empty(true),
pliden@6413 40 _dropped(0) {
pliden@6413 41 _nqueues = MAX2(ParallelGCThreads, (size_t)1);
pliden@6413 42 _queues = NEW_C_HEAP_ARRAY(G1StringDedupWorkerQueue, _nqueues, mtGC);
pliden@6413 43 for (size_t i = 0; i < _nqueues; i++) {
pliden@6413 44 new (_queues + i) G1StringDedupWorkerQueue(G1StringDedupWorkerQueue::default_segment_size(), _max_cache_size, _max_size);
pliden@6413 45 }
pliden@6413 46 }
pliden@6413 47
pliden@6413 48 G1StringDedupQueue::~G1StringDedupQueue() {
pliden@6413 49 ShouldNotReachHere();
pliden@6413 50 }
pliden@6413 51
pliden@6413 52 void G1StringDedupQueue::create() {
pliden@6413 53 assert(_queue == NULL, "One string deduplication queue allowed");
pliden@6413 54 _queue = new G1StringDedupQueue();
pliden@6413 55 }
pliden@6413 56
pliden@6413 57 void G1StringDedupQueue::wait() {
pliden@6413 58 MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
pliden@6690 59 while (_queue->_empty && !_queue->_cancel) {
pliden@6413 60 ml.wait(Mutex::_no_safepoint_check_flag);
pliden@6413 61 }
pliden@6413 62 }
pliden@6413 63
pliden@6690 64 void G1StringDedupQueue::cancel_wait() {
pliden@6690 65 MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
pliden@6690 66 _queue->_cancel = true;
pliden@6690 67 ml.notify();
pliden@6690 68 }
pliden@6690 69
pliden@6413 70 void G1StringDedupQueue::push(uint worker_id, oop java_string) {
pliden@6413 71 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint");
pliden@6413 72 assert(worker_id < _queue->_nqueues, "Invalid queue");
pliden@6413 73
pliden@6413 74 // Push and notify waiter
pliden@6413 75 G1StringDedupWorkerQueue& worker_queue = _queue->_queues[worker_id];
pliden@6413 76 if (!worker_queue.is_full()) {
pliden@6413 77 worker_queue.push(java_string);
pliden@6413 78 if (_queue->_empty) {
pliden@6413 79 MonitorLockerEx ml(StringDedupQueue_lock, Mutex::_no_safepoint_check_flag);
pliden@6413 80 if (_queue->_empty) {
pliden@6413 81 // Mark non-empty and notify waiter
pliden@6413 82 _queue->_empty = false;
pliden@6413 83 ml.notify();
pliden@6413 84 }
pliden@6413 85 }
pliden@6413 86 } else {
pliden@6413 87 // Queue is full, drop the string and update the statistics
pliden@6413 88 Atomic::inc_ptr(&_queue->_dropped);
pliden@6413 89 }
pliden@6413 90 }
pliden@6413 91
pliden@6413 92 oop G1StringDedupQueue::pop() {
pliden@6413 93 assert(!SafepointSynchronize::is_at_safepoint(), "Must not be at safepoint");
pliden@6413 94 No_Safepoint_Verifier nsv;
pliden@6413 95
pliden@6413 96 // Try all queues before giving up
pliden@6413 97 for (size_t tries = 0; tries < _queue->_nqueues; tries++) {
pliden@6413 98 // The cursor indicates where we left of last time
pliden@6413 99 G1StringDedupWorkerQueue* queue = &_queue->_queues[_queue->_cursor];
pliden@6413 100 while (!queue->is_empty()) {
pliden@6413 101 oop obj = queue->pop();
pliden@6413 102 // The oop we pop can be NULL if it was marked
pliden@6413 103 // dead. Just ignore those and pop the next oop.
pliden@6413 104 if (obj != NULL) {
pliden@6413 105 return obj;
pliden@6413 106 }
pliden@6413 107 }
pliden@6413 108
pliden@6413 109 // Try next queue
pliden@6413 110 _queue->_cursor = (_queue->_cursor + 1) % _queue->_nqueues;
pliden@6413 111 }
pliden@6413 112
pliden@6413 113 // Mark empty
pliden@6413 114 _queue->_empty = true;
pliden@6413 115
pliden@6413 116 return NULL;
pliden@6413 117 }
pliden@6413 118
pliden@6413 119 void G1StringDedupQueue::unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* cl) {
pliden@6413 120 // A worker thread first claims a queue, which ensures exclusive
pliden@6413 121 // access to that queue, then continues to process it.
pliden@6413 122 for (;;) {
pliden@6413 123 // Grab next queue to scan
pliden@6413 124 size_t queue = cl->claim_queue();
pliden@6413 125 if (queue >= _queue->_nqueues) {
pliden@6413 126 // End of queues
pliden@6413 127 break;
pliden@6413 128 }
pliden@6413 129
pliden@6413 130 // Scan the queue
pliden@6413 131 unlink_or_oops_do(cl, queue);
pliden@6413 132 }
pliden@6413 133 }
pliden@6413 134
pliden@6413 135 void G1StringDedupQueue::unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* cl, size_t queue) {
pliden@6413 136 assert(queue < _queue->_nqueues, "Invalid queue");
pliden@6413 137 StackIterator<oop, mtGC> iter(_queue->_queues[queue]);
pliden@6413 138 while (!iter.is_empty()) {
pliden@6413 139 oop* p = iter.next_addr();
pliden@6413 140 if (*p != NULL) {
pliden@6413 141 if (cl->is_alive(*p)) {
pliden@6413 142 cl->keep_alive(p);
pliden@6413 143 } else {
pliden@6413 144 // Clear dead reference
pliden@6413 145 *p = NULL;
pliden@6413 146 }
pliden@6413 147 }
pliden@6413 148 }
pliden@6413 149 }
pliden@6413 150
pliden@6413 151 void G1StringDedupQueue::print_statistics(outputStream* st) {
pliden@6413 152 st->print_cr(
pliden@6413 153 " [Queue]\n"
pliden@6413 154 " [Dropped: "UINTX_FORMAT"]", _queue->_dropped);
pliden@6413 155 }
pliden@6413 156
pliden@6413 157 void G1StringDedupQueue::verify() {
pliden@6413 158 for (size_t i = 0; i < _queue->_nqueues; i++) {
pliden@6413 159 StackIterator<oop, mtGC> iter(_queue->_queues[i]);
pliden@6413 160 while (!iter.is_empty()) {
pliden@6413 161 oop obj = iter.next();
pliden@6413 162 if (obj != NULL) {
pliden@6413 163 guarantee(Universe::heap()->is_in_reserved(obj), "Object must be on the heap");
pliden@6413 164 guarantee(!obj->is_forwarded(), "Object must not be forwarded");
pliden@6413 165 guarantee(java_lang_String::is_instance(obj), "Object must be a String");
pliden@6413 166 }
pliden@6413 167 }
pliden@6413 168 }
pliden@6413 169 }

mercurial