src/hotspot/share/gc/shenandoah/shenandoahStringDedup.cpp
changeset 52925 9c18c9d839d3
child 53276 72fdf46a274e
equal deleted inserted replaced
52924:420ff459906f 52925:9c18c9d839d3
       
     1 /*
       
     2  * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved.
       
     3  *
       
     4  * This code is free software; you can redistribute it and/or modify it
       
     5  * under the terms of the GNU General Public License version 2 only, as
       
     6  * published by the Free Software Foundation.
       
     7  *
       
     8  * This code is distributed in the hope that it will be useful, but WITHOUT
       
     9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    11  * version 2 for more details (a copy is included in the LICENSE file that
       
    12  * accompanied this code).
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License version
       
    15  * 2 along with this work; if not, write to the Free Software Foundation,
       
    16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    17  *
       
    18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    19  * or visit www.oracle.com if you need additional information or have any
       
    20  * questions.
       
    21  *
       
    22  */
       
    23 
       
    24 #include "precompiled.hpp"
       
    25 
       
    26 #include "gc/shared/stringdedup/stringDedup.hpp"
       
    27 #include "gc/shared/stringdedup/stringDedup.inline.hpp"
       
    28 #include "gc/shared/workgroup.hpp"
       
    29 #include "gc/shenandoah/shenandoahCollectionSet.hpp"
       
    30 #include "gc/shenandoah/shenandoahCollectionSet.inline.hpp"
       
    31 #include "gc/shenandoah/shenandoahHeap.hpp"
       
    32 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
       
    33 #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp"
       
    34 #include "gc/shenandoah/shenandoahStringDedup.hpp"
       
    35 #include "gc/shenandoah/shenandoahStrDedupQueue.hpp"
       
    36 #include "gc/shenandoah/shenandoahTimingTracker.hpp"
       
    37 #include "gc/shenandoah/shenandoahUtils.hpp"
       
    38 #include "runtime/thread.hpp"
       
    39 
       
    40 void ShenandoahStringDedup::initialize() {
       
    41   assert(UseShenandoahGC, "String deduplication available with Shenandoah GC");
       
    42   StringDedup::initialize_impl<ShenandoahStrDedupQueue, StringDedupStat>();
       
    43 }
       
    44 
       
    45 /* Enqueue candidates for deduplication.
       
    46  * The method should only be called by GC worker threads during marking phases.
       
    47  */
       
    48 void ShenandoahStringDedup::enqueue_candidate(oop java_string) {
       
    49   assert(Thread::current()->is_Worker_thread(),
       
    50         "Only from a GC worker thread");
       
    51 
       
    52   if (java_string->age() <= StringDeduplicationAgeThreshold) {
       
    53     const markOop mark = java_string->mark();
       
    54 
       
    55     // Having/had displaced header, too risk to deal with them, skip
       
    56     if (mark == markOopDesc::INFLATING() || mark->has_displaced_mark_helper()) {
       
    57       return;
       
    58     }
       
    59 
       
    60     // Increase string age and enqueue it when it rearches age threshold
       
    61     markOop new_mark = mark->incr_age();
       
    62     if (mark == java_string->cas_set_mark(new_mark, mark)) {
       
    63       if (mark->age() == StringDeduplicationAgeThreshold) {
       
    64         StringDedupQueue::push(ShenandoahWorkerSession::worker_id(), java_string);
       
    65       }
       
    66     }
       
    67   }
       
    68 }
       
    69 
       
    70 // Deduplicate a string, return true if it is deduplicated.
       
    71 void ShenandoahStringDedup::deduplicate(oop java_string) {
       
    72   assert(is_enabled(), "String deduplication not enabled");
       
    73   StringDedupStat dummy; // Statistics from this path is never used
       
    74   StringDedupTable::deduplicate(java_string, &dummy);
       
    75 }
       
    76 
       
    77 void ShenandoahStringDedup::parallel_oops_do(OopClosure* cl, uint worker_id) {
       
    78   assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
       
    79   assert(is_enabled(), "String deduplication not enabled");
       
    80 
       
    81   ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
       
    82 
       
    83   StringDedupUnlinkOrOopsDoClosure sd_cl(NULL, cl);
       
    84 
       
    85   {
       
    86     ShenandoahWorkerTimingsTracker x(worker_times, ShenandoahPhaseTimings::StringDedupQueueRoots, worker_id);
       
    87     StringDedupQueue::unlink_or_oops_do(&sd_cl);
       
    88   }
       
    89   {
       
    90     ShenandoahWorkerTimingsTracker x(worker_times, ShenandoahPhaseTimings::StringDedupTableRoots, worker_id);
       
    91     StringDedupTable::unlink_or_oops_do(&sd_cl, worker_id);
       
    92   }
       
    93 }
       
    94 
       
    95 void ShenandoahStringDedup::oops_do_slow(OopClosure* cl) {
       
    96   assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
       
    97   assert(is_enabled(), "String deduplication not enabled");
       
    98   ShenandoahAlwaysTrueClosure always_true;
       
    99   StringDedupUnlinkOrOopsDoClosure sd_cl(&always_true, cl);
       
   100   StringDedupQueue::unlink_or_oops_do(&sd_cl);
       
   101   StringDedupTable::unlink_or_oops_do(&sd_cl, 0);
       
   102 }
       
   103 
       
   104 class ShenandoahIsMarkedNextClosure : public BoolObjectClosure {
       
   105 private:
       
   106   ShenandoahMarkingContext* const _mark_context;
       
   107 
       
   108 public:
       
   109   ShenandoahIsMarkedNextClosure() : _mark_context(ShenandoahHeap::heap()->marking_context()) { }
       
   110 
       
   111   bool do_object_b(oop obj) {
       
   112     return _mark_context->is_marked(obj);
       
   113   }
       
   114 };
       
   115 
       
   116 void ShenandoahStringDedup::parallel_cleanup() {
       
   117   assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
       
   118   log_debug(gc, stringdedup)("String dedup cleanup");
       
   119   ShenandoahIsMarkedNextClosure cl;
       
   120 
       
   121   unlink_or_oops_do(&cl, NULL, true);
       
   122 }
       
   123 
       
   124 //
       
   125 // Task for parallel unlink_or_oops_do() operation on the deduplication queue
       
   126 // and table.
       
   127 //
       
   128 class ShenandoahStringDedupUnlinkOrOopsDoTask : public AbstractGangTask {
       
   129 private:
       
   130   StringDedupUnlinkOrOopsDoClosure _cl;
       
   131 
       
   132 public:
       
   133   ShenandoahStringDedupUnlinkOrOopsDoTask(BoolObjectClosure* is_alive,
       
   134                                   OopClosure* keep_alive,
       
   135                                   bool allow_resize_and_rehash) :
       
   136     AbstractGangTask("StringDedupUnlinkOrOopsDoTask"),
       
   137     _cl(is_alive, keep_alive) {
       
   138       StringDedup::gc_prologue(allow_resize_and_rehash);
       
   139   }
       
   140 
       
   141   ~ShenandoahStringDedupUnlinkOrOopsDoTask() {
       
   142     StringDedup::gc_epilogue();
       
   143   }
       
   144 
       
   145   virtual void work(uint worker_id) {
       
   146     StringDedupQueue::unlink_or_oops_do(&_cl);
       
   147     StringDedupTable::unlink_or_oops_do(&_cl, worker_id);
       
   148   }
       
   149 };
       
   150 
       
   151 void ShenandoahStringDedup::unlink_or_oops_do(BoolObjectClosure* is_alive,
       
   152                                       OopClosure* keep_alive,
       
   153                                       bool allow_resize_and_rehash) {
       
   154   assert(is_enabled(), "String deduplication not enabled");
       
   155 
       
   156   ShenandoahStringDedupUnlinkOrOopsDoTask task(is_alive, keep_alive, allow_resize_and_rehash);
       
   157   ShenandoahHeap* heap = ShenandoahHeap::heap();
       
   158   heap->workers()->run_task(&task);
       
   159 }