1 /* 2 * Copyright (c) 2018, 2019, 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 */ 24 25 #ifndef SHARE_GC_SHARED_STRINGDEDUP_STRINGDEDUPQUEUE_HPP 26 #define SHARE_GC_SHARED_STRINGDEDUP_STRINGDEDUPQUEUE_HPP 27 28 #include "memory/allocation.hpp" 29 #include "oops/oop.hpp" 30 31 class StringDedupUnlinkOrOopsDoClosure; 32 33 // 34 // The deduplication queue acts as the communication channel between mark/evacuation 35 // phase and the concurrent deduplication phase. Deduplication candidates 36 // found during mark/evacuation are placed on this queue for later processing in the 37 // deduplication thread. A queue entry is an oop pointing to a String object (as opposed 38 // to entries in the deduplication hashtable which points to character arrays). 39 // 40 // While users of the queue treat it as a single queue, it is implemented as a set of 41 // queues, one queue per GC worker thread, to allow lock-free and cache-friendly enqueue 42 // operations by the GC workers. 43 // 44 // The oops in the queue are treated as weak pointers, meaning the objects they point to 45 // can become unreachable and pruned (cleared) before being popped by the deduplication 46 // thread. 47 // 48 // Pushing to the queue is thread safe (this relies on each thread using a unique worker 49 // id). Popping from the queue is NOT thread safe and can only be done by the deduplication 50 // thread outside a safepoint. 51 // 52 53 class StringDedupQueue : public CHeapObj<mtGC> { 54 private: 55 static StringDedupQueue* _queue; 56 static volatile size_t _claimed_index; 57 58 public: 59 template <typename Q> 60 static void create(); 61 62 // Blocks and waits for the queue to become non-empty. 63 static inline void wait(); 64 65 // Wakes up any thread blocked waiting for the queue to become non-empty. 66 static inline void cancel_wait(); 67 68 // Pushes a deduplication candidate onto a specific GC worker queue. 69 static inline void push(uint worker_id, oop java_string); 70 71 // Pops a deduplication candidate from any queue, returns NULL if 72 // all queues are empty. 73 static inline oop pop(); 74 75 static void unlink_or_oops_do(StringDedupUnlinkOrOopsDoClosure* cl); 76 77 static void print_statistics(); 78 static void verify(); 79 80 // GC support 81 static void gc_prologue(); 82 static void gc_epilogue(); 83 84 protected: 85 static StringDedupQueue* const queue(); 86 87 // Queue interface. 88 89 // Blocks and waits for the queue to become non-empty. 90 virtual void wait_impl() = 0; 91 92 // Wakes up any thread blocked waiting for the queue to become non-empty. 93 virtual void cancel_wait_impl() = 0; 94 95 // Pushes a deduplication candidate onto a specific GC worker queue. 96 virtual void push_impl(uint worker_id, oop java_string) = 0; 97 98 // Pops a deduplication candidate from any queue, returns NULL if 99 // all queues are empty. 100 virtual oop pop_impl() = 0; 101 102 virtual void unlink_or_oops_do_impl(StringDedupUnlinkOrOopsDoClosure* cl, size_t queue) = 0; 103 104 virtual void print_statistics_impl() = 0; 105 virtual void verify_impl() = 0; 106 107 virtual size_t num_queues() const = 0; 108 109 static size_t claim(); 110 }; 111 112 #endif // SHARE_GC_SHARED_STRINGDEDUP_STRINGDEDUPQUEUE_HPP 113