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 #ifndef SHARE_VM_GC_SHENANDOAH_SHENANDOAHSTRINGDEDUP_HPP
  25 #define SHARE_VM_GC_SHENANDOAH_SHENANDOAHSTRINGDEDUP_HPP
  26 
  27 #include "classfile/javaClasses.hpp"
  28 #include "gc_implementation/shenandoah/shenandoahPhaseTimings.hpp"
  29 #include "memory/iterator.hpp"
  30 #include "utilities/ostream.hpp"
  31 
  32 #define STRDEDUP_TIME_FORMAT_MS         "%.3fms"
  33 #define STRDEDUP_TIME_PARAM_MS(time)    ((time) * MILLIUNITS)
  34 
  35 class ShenandoahStrDedupStats VALUE_OBJ_CLASS_SPEC {
  36 private:
  37   // Counters
  38   volatile size_t  _inspected;
  39   volatile size_t  _deduped;
  40   volatile size_t  _skipped;
  41   volatile size_t  _known;
  42 
  43   size_t  _idle;
  44   size_t  _exec;
  45   size_t  _block;
  46 
  47   // Time spent by the deduplication thread in different phases
  48   double _start_concurrent;
  49   double _end_concurrent;
  50   double _start_phase;
  51   double _idle_elapsed;
  52   double _exec_elapsed;
  53   double _block_elapsed;
  54 
  55   size_t _table_expanded_count;
  56   size_t _table_shrinked_count;
  57   size_t _table_rehashed_count;
  58 
  59 public:
  60   ShenandoahStrDedupStats();
  61 
  62   void inc_inspected() { assert_thread(); _inspected ++; }
  63   void inc_skipped()   { assert_thread(); _skipped ++; }
  64   void inc_known()     { assert_thread(); _known ++; }
  65   void inc_deduped() {
  66     assert_thread();
  67     _deduped ++;
  68   }
  69 
  70   void atomic_inc_inspected(size_t count);
  71   void atomic_inc_deduped(size_t count);
  72   void atomic_inc_skipped(size_t count);
  73   void atomic_inc_known(size_t count);
  74 
  75   void mark_idle();
  76   void mark_exec();
  77   void mark_block();
  78   void mark_unblock();
  79   void mark_done();
  80 
  81   void inc_table_expanded();
  82   void inc_table_shrinked();
  83   void inc_table_rehashed();
  84 
  85   void update(const ShenandoahStrDedupStats& sts);
  86 
  87   void print_statistics(outputStream* out) const;
  88 
  89 private:
  90   void assert_thread() PRODUCT_RETURN;
  91 };
  92 
  93 class ShenandoahStrDedupQueue;
  94 class ShenandoahStrDedupQueueSet;
  95 class ShenandoahStrDedupTable;
  96 class ShenandoahStrDedupThread;
  97 
  98 class ShenandoahStringDedup : AllStatic {
  99   friend class ShenandoahStrDedupStats;
 100 
 101 private:
 102   static ShenandoahStrDedupQueueSet* _queues;
 103   static ShenandoahStrDedupTable*    _table;
 104   static ShenandoahStrDedupThread*   _thread;
 105   static bool                        _enabled;
 106   static ShenandoahStrDedupStats     _stats;
 107 
 108 public:
 109   // Initialize string deduplication.
 110   static void initialize();
 111 
 112   static bool is_enabled() { return _enabled; }
 113 
 114   // Enqueue a string to worker's local string dedup queue
 115   static void enqueue_candidate(oop java_string, ShenandoahStrDedupQueue* q);
 116 
 117   // Get string dedup queue associated to specific worker id
 118   static ShenandoahStrDedupQueue* queue(uint worker_id);
 119 
 120   // Deduplicate a string, the call is lock-free
 121   static bool deduplicate(oop java_string, bool update_counter = true);
 122 
 123   // Parallel scan string dedup queues/table
 124   static void clear_claimed();
 125 
 126   static void parallel_oops_do(ShenandoahPhaseTimings::Phase phase, OopClosure* cl, uint worker_id);
 127 
 128   // For verification only
 129   static void oops_do_slow(OopClosure* cl);
 130 
 131   static void threads_do(ThreadClosure* tc);
 132 
 133   static void print_worker_threads_on(outputStream* out) { }
 134 
 135   static ShenandoahStrDedupStats& dedup_stats() { return _stats; }
 136 
 137   // Parallel cleanup string dedup queues/table
 138   static void parallel_cleanup();
 139 
 140   static void stop();
 141 
 142   static inline bool is_candidate(oop obj) {
 143     return java_lang_String::is_instance(obj) &&
 144            java_lang_String::value(obj) != NULL;
 145   }
 146 
 147   static void print_statistics(outputStream* out);
 148 };
 149 
 150 #endif // SHARE_VM_GC_SHENANDOAH_SHENANDOAHSTRINGDEDUP_HPP