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

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 7658
c3fcc09c9239
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 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUP_HPP
pliden@6413 26 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUP_HPP
pliden@6413 27
pliden@6413 28 //
pliden@6413 29 // String Deduplication
pliden@6413 30 //
pliden@6413 31 // String deduplication aims to reduce the heap live-set by deduplicating identical
pliden@6413 32 // instances of String so that they share the same backing character array.
pliden@6413 33 //
pliden@6413 34 // The deduplication process is divided in two main parts, 1) finding the objects to
pliden@6413 35 // deduplicate, and 2) deduplicating those objects. The first part is done as part of
pliden@6413 36 // a normal GC cycle when objects are marked or evacuated. At this time a check is
pliden@6413 37 // applied on each object to check if it is a candidate for deduplication. If so, the
pliden@6413 38 // object is placed on the deduplication queue for later processing. The second part,
pliden@6413 39 // processing the objects on the deduplication queue, is a concurrent phase which
pliden@6413 40 // starts right after the stop-the-wold marking/evacuation phase. This phase is
pliden@6413 41 // executed by the deduplication thread, which pulls deduplication candidates of the
pliden@6413 42 // deduplication queue and tries to deduplicate them.
pliden@6413 43 //
pliden@6413 44 // A deduplication hashtable is used to keep track of all unique character arrays
pliden@6413 45 // used by String objects. When deduplicating, a lookup is made in this table to see
pliden@6413 46 // if there is already an identical character array somewhere on the heap. If so, the
pliden@6413 47 // String object is adjusted to point to that character array, releasing the reference
pliden@6413 48 // to the original array allowing it to eventually be garbage collected. If the lookup
pliden@6413 49 // fails the character array is instead inserted into the hashtable so that this array
pliden@6413 50 // can be shared at some point in the future.
pliden@6413 51 //
pliden@6413 52 // Candidate selection
pliden@6413 53 //
pliden@6413 54 // An object is considered a deduplication candidate if all of the following
pliden@6413 55 // statements are true:
pliden@6413 56 //
pliden@6413 57 // - The object is an instance of java.lang.String
pliden@6413 58 //
pliden@6413 59 // - The object is being evacuated from a young heap region
pliden@6413 60 //
pliden@6413 61 // - The object is being evacuated to a young/survivor heap region and the
pliden@6413 62 // object's age is equal to the deduplication age threshold
pliden@6413 63 //
pliden@6413 64 // or
pliden@6413 65 //
pliden@6413 66 // The object is being evacuated to an old heap region and the object's age is
pliden@6413 67 // less than the deduplication age threshold
pliden@6413 68 //
pliden@6413 69 // Once an string object has been promoted to an old region, or its age is higher
pliden@6413 70 // than the deduplication age threshold, is will never become a candidate again.
pliden@6413 71 // This approach avoids making the same object a candidate more than once.
pliden@6413 72 //
pliden@6413 73 // Interned strings are a bit special. They are explicitly deduplicated just before
pliden@6413 74 // being inserted into the StringTable (to avoid counteracting C2 optimizations done
pliden@6413 75 // on string literals), then they also become deduplication candidates if they reach
pliden@6413 76 // the deduplication age threshold or are evacuated to an old heap region. The second
pliden@6413 77 // attempt to deduplicate such strings will be in vain, but we have no fast way of
pliden@6413 78 // filtering them out. This has not shown to be a problem, as the number of interned
pliden@6413 79 // strings is usually dwarfed by the number of normal (non-interned) strings.
pliden@6413 80 //
pliden@6413 81 // For additional information on string deduplication, please see JEP 192,
pliden@6413 82 // http://openjdk.java.net/jeps/192
pliden@6413 83 //
pliden@6413 84
pliden@6413 85 #include "memory/allocation.hpp"
pliden@6413 86 #include "oops/oop.hpp"
pliden@6413 87
pliden@6413 88 class OopClosure;
pliden@6413 89 class BoolObjectClosure;
pliden@6413 90 class ThreadClosure;
pliden@6413 91 class outputStream;
pliden@6413 92 class G1StringDedupTable;
pliden@6413 93
pliden@6413 94 //
pliden@6413 95 // Main interface for interacting with string deduplication.
pliden@6413 96 //
pliden@6413 97 class G1StringDedup : public AllStatic {
pliden@6413 98 private:
pliden@6413 99 // Single state for checking if both G1 and string deduplication is enabled.
pliden@6413 100 static bool _enabled;
pliden@6413 101
pliden@6413 102 // Candidate selection policies, returns true if the given object is
pliden@6413 103 // candidate for string deduplication.
pliden@6413 104 static bool is_candidate_from_mark(oop obj);
pliden@6413 105 static bool is_candidate_from_evacuation(bool from_young, bool to_young, oop obj);
pliden@6413 106
pliden@6413 107 public:
pliden@6413 108 // Returns true if both G1 and string deduplication is enabled.
pliden@6413 109 static bool is_enabled() {
pliden@6413 110 return _enabled;
pliden@6413 111 }
pliden@6413 112
pliden@6690 113 // Initialize string deduplication.
pliden@6413 114 static void initialize();
pliden@6413 115
pliden@6690 116 // Stop the deduplication thread.
pliden@6690 117 static void stop();
pliden@6690 118
pliden@6413 119 // Immediately deduplicates the given String object, bypassing the
pliden@6413 120 // the deduplication queue.
pliden@6413 121 static void deduplicate(oop java_string);
pliden@6413 122
pliden@6413 123 // Enqueues a deduplication candidate for later processing by the deduplication
pliden@6413 124 // thread. Before enqueuing, these functions apply the appropriate candidate
pliden@6413 125 // selection policy to filters out non-candidates.
pliden@6413 126 static void enqueue_from_mark(oop java_string);
pliden@6413 127 static void enqueue_from_evacuation(bool from_young, bool to_young,
pliden@6413 128 unsigned int queue, oop java_string);
pliden@6413 129
pliden@6413 130 static void oops_do(OopClosure* keep_alive);
pliden@6413 131 static void unlink(BoolObjectClosure* is_alive);
pliden@6413 132 static void unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive,
pliden@6413 133 bool allow_resize_and_rehash = true);
pliden@6413 134
pliden@6413 135 static void threads_do(ThreadClosure* tc);
pliden@6413 136 static void print_worker_threads_on(outputStream* st);
pliden@6413 137 static void verify();
pliden@6413 138 };
pliden@6413 139
pliden@6413 140 //
pliden@6413 141 // This closure encapsulates the state and the closures needed when scanning
pliden@6413 142 // the deduplication queue and table during the unlink_or_oops_do() operation.
pliden@6413 143 // A single instance of this closure is created and then shared by all worker
pliden@6413 144 // threads participating in the scan. The _next_queue and _next_bucket fields
pliden@6413 145 // provide a simple mechanism for GC workers to claim exclusive access to a
pliden@6413 146 // queue or a table partition.
pliden@6413 147 //
pliden@6413 148 class G1StringDedupUnlinkOrOopsDoClosure : public StackObj {
pliden@6413 149 private:
pliden@6413 150 BoolObjectClosure* _is_alive;
pliden@6413 151 OopClosure* _keep_alive;
pliden@6413 152 G1StringDedupTable* _resized_table;
pliden@6413 153 G1StringDedupTable* _rehashed_table;
pliden@6413 154 size_t _next_queue;
pliden@6413 155 size_t _next_bucket;
pliden@6413 156
pliden@6413 157 public:
pliden@6413 158 G1StringDedupUnlinkOrOopsDoClosure(BoolObjectClosure* is_alive,
pliden@6413 159 OopClosure* keep_alive,
pliden@6413 160 bool allow_resize_and_rehash);
pliden@6413 161 ~G1StringDedupUnlinkOrOopsDoClosure();
pliden@6413 162
pliden@6413 163 bool is_resizing() {
pliden@6413 164 return _resized_table != NULL;
pliden@6413 165 }
pliden@6413 166
pliden@6413 167 G1StringDedupTable* resized_table() {
pliden@6413 168 return _resized_table;
pliden@6413 169 }
pliden@6413 170
pliden@6413 171 bool is_rehashing() {
pliden@6413 172 return _rehashed_table != NULL;
pliden@6413 173 }
pliden@6413 174
pliden@6413 175 // Atomically claims the next available queue for exclusive access by
pliden@6413 176 // the current thread. Returns the queue number of the claimed queue.
pliden@6413 177 size_t claim_queue() {
pliden@6413 178 return (size_t)Atomic::add_ptr(1, &_next_queue) - 1;
pliden@6413 179 }
pliden@6413 180
pliden@6413 181 // Atomically claims the next available table partition for exclusive
pliden@6413 182 // access by the current thread. Returns the table bucket number where
pliden@6413 183 // the claimed partition starts.
pliden@6413 184 size_t claim_table_partition(size_t partition_size) {
pliden@6413 185 return (size_t)Atomic::add_ptr(partition_size, &_next_bucket) - partition_size;
pliden@6413 186 }
pliden@6413 187
pliden@6413 188 // Applies and returns the result from the is_alive closure, or
pliden@6413 189 // returns true if no such closure was provided.
pliden@6413 190 bool is_alive(oop o) {
pliden@6413 191 if (_is_alive != NULL) {
pliden@6413 192 return _is_alive->do_object_b(o);
pliden@6413 193 }
pliden@6413 194 return true;
pliden@6413 195 }
pliden@6413 196
pliden@6413 197 // Applies the keep_alive closure, or does nothing if no such
pliden@6413 198 // closure was provided.
pliden@6413 199 void keep_alive(oop* p) {
pliden@6413 200 if (_keep_alive != NULL) {
pliden@6413 201 _keep_alive->do_oop(p);
pliden@6413 202 }
pliden@6413 203 }
pliden@6413 204 };
pliden@6413 205
pliden@6413 206 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUP_HPP

mercurial