1 /*
2  * Copyright (c) 2017, 2019, 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_GC_SHENANDOAH_SHENANDOAHSTRDEDUPQUEUE_HPP
25 #define SHARE_GC_SHENANDOAH_SHENANDOAHSTRDEDUPQUEUE_HPP
26 
27 #include "gc/shared/stringdedup/stringDedup.hpp"
28 #include "gc/shenandoah/shenandoahHeap.hpp"
29 #include "oops/oop.hpp"
30 
31 template <uint buffer_size>
32 class ShenandoahOopBuffer : public CHeapObj<mtGC> {
33 private:
34   oop   _buf[buffer_size];
35   uint  _index;
36   ShenandoahOopBuffer<buffer_size>* _next;
37 
38 public:
39   ShenandoahOopBuffer();
40 
41   bool is_full()  const;
42   bool is_empty() const;
43   uint size()     const;
44 
45   void push(oop obj);
46   oop pop();
47 
48   void reset();
49 
50   void set_next(ShenandoahOopBuffer<buffer_size>* next);
51   ShenandoahOopBuffer<buffer_size>* next() const;
52 
53   void unlink_or_oops_do(StringDedupUnlinkOrOopsDoClosure* cl);
54   void oops_do(OopClosure* cl);
55 };
56 
57 typedef ShenandoahOopBuffer<64> ShenandoahQueueBuffer;
58 
59 // Muti-producer and single consumer queue set
60 class ShenandoahStrDedupQueue : public StringDedupQueue {
61 private:
62   ShenandoahQueueBuffer** _producer_queues;
63   ShenandoahQueueBuffer*  _consumer_queue;
64   size_t                  _num_producer_queue;
65 
66   // The queue is used for producers to publish completed buffers
67   ShenandoahQueueBuffer* _published_queues;
68 
69   // Cached free buffers
70   ShenandoahQueueBuffer* _free_list;
71   size_t                 _num_free_buffer;
72   const size_t           _max_free_buffer;
73 
74   bool                   _cancel;
75 
76   // statistics
77   size_t                 _total_buffers;
78 
79 private:
80   ~ShenandoahStrDedupQueue();
81 
82 public:
83   ShenandoahStrDedupQueue();
84 
85   void wait_impl();
86   void cancel_wait_impl();
87 
88   void push_impl(uint worker_id, oop string_oop);
89   oop  pop_impl();
90 
91   void unlink_or_oops_do_impl(StringDedupUnlinkOrOopsDoClosure* cl, size_t queue);
92 
93   void print_statistics_impl();
94   void verify_impl();
95 
96 protected:
num_queues() const97   size_t num_queues() const { return (_num_producer_queue + 2); }
98 
99 private:
100   ShenandoahQueueBuffer* new_buffer();
101 
102   void release_buffers(ShenandoahQueueBuffer* list);
103 
104   ShenandoahQueueBuffer* queue_at(size_t queue_id) const;
105 
106   bool pop_candidate(oop& obj);
107 
108   void set_producer_buffer(ShenandoahQueueBuffer* buf, size_t queue_id);
109 
110   void verify(ShenandoahQueueBuffer* head);
111 };
112 
113 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHSTRDEDUPQUEUE_HPP
114