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

     1 /*
     2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUP_HPP
    26 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUP_HPP
    28 //
    29 // String Deduplication
    30 //
    31 // String deduplication aims to reduce the heap live-set by deduplicating identical
    32 // instances of String so that they share the same backing character array.
    33 //
    34 // The deduplication process is divided in two main parts, 1) finding the objects to
    35 // deduplicate, and 2) deduplicating those objects. The first part is done as part of
    36 // a normal GC cycle when objects are marked or evacuated. At this time a check is
    37 // applied on each object to check if it is a candidate for deduplication. If so, the
    38 // object is placed on the deduplication queue for later processing. The second part,
    39 // processing the objects on the deduplication queue, is a concurrent phase which
    40 // starts right after the stop-the-wold marking/evacuation phase. This phase is
    41 // executed by the deduplication thread, which pulls deduplication candidates of the
    42 // deduplication queue and tries to deduplicate them.
    43 //
    44 // A deduplication hashtable is used to keep track of all unique character arrays
    45 // used by String objects. When deduplicating, a lookup is made in this table to see
    46 // if there is already an identical character array somewhere on the heap. If so, the
    47 // String object is adjusted to point to that character array, releasing the reference
    48 // to the original array allowing it to eventually be garbage collected. If the lookup
    49 // fails the character array is instead inserted into the hashtable so that this array
    50 // can be shared at some point in the future.
    51 //
    52 // Candidate selection
    53 //
    54 // An object is considered a deduplication candidate if all of the following
    55 // statements are true:
    56 //
    57 // - The object is an instance of java.lang.String
    58 //
    59 // - The object is being evacuated from a young heap region
    60 //
    61 // - The object is being evacuated to a young/survivor heap region and the
    62 //   object's age is equal to the deduplication age threshold
    63 //
    64 //   or
    65 //
    66 //   The object is being evacuated to an old heap region and the object's age is
    67 //   less than the deduplication age threshold
    68 //
    69 // Once an string object has been promoted to an old region, or its age is higher
    70 // than the deduplication age threshold, is will never become a candidate again.
    71 // This approach avoids making the same object a candidate more than once.
    72 //
    73 // Interned strings are a bit special. They are explicitly deduplicated just before
    74 // being inserted into the StringTable (to avoid counteracting C2 optimizations done
    75 // on string literals), then they also become deduplication candidates if they reach
    76 // the deduplication age threshold or are evacuated to an old heap region. The second
    77 // attempt to deduplicate such strings will be in vain, but we have no fast way of
    78 // filtering them out. This has not shown to be a problem, as the number of interned
    79 // strings is usually dwarfed by the number of normal (non-interned) strings.
    80 //
    81 // For additional information on string deduplication, please see JEP 192,
    82 // http://openjdk.java.net/jeps/192
    83 //
    85 #include "memory/allocation.hpp"
    86 #include "oops/oop.hpp"
    88 class OopClosure;
    89 class BoolObjectClosure;
    90 class ThreadClosure;
    91 class outputStream;
    92 class G1StringDedupTable;
    94 //
    95 // Main interface for interacting with string deduplication.
    96 //
    97 class G1StringDedup : public AllStatic {
    98 private:
    99   // Single state for checking if both G1 and string deduplication is enabled.
   100   static bool _enabled;
   102   // Candidate selection policies, returns true if the given object is
   103   // candidate for string deduplication.
   104   static bool is_candidate_from_mark(oop obj);
   105   static bool is_candidate_from_evacuation(bool from_young, bool to_young, oop obj);
   107 public:
   108   // Returns true if both G1 and string deduplication is enabled.
   109   static bool is_enabled() {
   110     return _enabled;
   111   }
   113   // Initialize string deduplication.
   114   static void initialize();
   116   // Stop the deduplication thread.
   117   static void stop();
   119   // Immediately deduplicates the given String object, bypassing the
   120   // the deduplication queue.
   121   static void deduplicate(oop java_string);
   123   // Enqueues a deduplication candidate for later processing by the deduplication
   124   // thread. Before enqueuing, these functions apply the appropriate candidate
   125   // selection policy to filters out non-candidates.
   126   static void enqueue_from_mark(oop java_string);
   127   static void enqueue_from_evacuation(bool from_young, bool to_young,
   128                                       unsigned int queue, oop java_string);
   130   static void oops_do(OopClosure* keep_alive);
   131   static void unlink(BoolObjectClosure* is_alive);
   132   static void unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive,
   133                                 bool allow_resize_and_rehash = true);
   135   static void threads_do(ThreadClosure* tc);
   136   static void print_worker_threads_on(outputStream* st);
   137   static void verify();
   138 };
   140 //
   141 // This closure encapsulates the state and the closures needed when scanning
   142 // the deduplication queue and table during the unlink_or_oops_do() operation.
   143 // A single instance of this closure is created and then shared by all worker
   144 // threads participating in the scan. The _next_queue and _next_bucket fields
   145 // provide a simple mechanism for GC workers to claim exclusive access to a
   146 // queue or a table partition.
   147 //
   148 class G1StringDedupUnlinkOrOopsDoClosure : public StackObj {
   149 private:
   150   BoolObjectClosure*  _is_alive;
   151   OopClosure*         _keep_alive;
   152   G1StringDedupTable* _resized_table;
   153   G1StringDedupTable* _rehashed_table;
   154   size_t              _next_queue;
   155   size_t              _next_bucket;
   157 public:
   158   G1StringDedupUnlinkOrOopsDoClosure(BoolObjectClosure* is_alive,
   159                                      OopClosure* keep_alive,
   160                                      bool allow_resize_and_rehash);
   161   ~G1StringDedupUnlinkOrOopsDoClosure();
   163   bool is_resizing() {
   164     return _resized_table != NULL;
   165   }
   167   G1StringDedupTable* resized_table() {
   168     return _resized_table;
   169   }
   171   bool is_rehashing() {
   172     return _rehashed_table != NULL;
   173   }
   175   // Atomically claims the next available queue for exclusive access by
   176   // the current thread. Returns the queue number of the claimed queue.
   177   size_t claim_queue() {
   178     return (size_t)Atomic::add_ptr(1, &_next_queue) - 1;
   179   }
   181   // Atomically claims the next available table partition for exclusive
   182   // access by the current thread. Returns the table bucket number where
   183   // the claimed partition starts.
   184   size_t claim_table_partition(size_t partition_size) {
   185     return (size_t)Atomic::add_ptr(partition_size, &_next_bucket) - partition_size;
   186   }
   188   // Applies and returns the result from the is_alive closure, or
   189   // returns true if no such closure was provided.
   190   bool is_alive(oop o) {
   191     if (_is_alive != NULL) {
   192       return _is_alive->do_object_b(o);
   193     }
   194     return true;
   195   }
   197   // Applies the keep_alive closure, or does nothing if no such
   198   // closure was provided.
   199   void keep_alive(oop* p) {
   200     if (_keep_alive != NULL) {
   201       _keep_alive->do_oop(p);
   202     }
   203   }
   204 };
   206 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1STRINGDEDUP_HPP

mercurial