1/*
2 * Copyright (c) 2001, 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_SATBMARKQUEUE_HPP
26#define SHARE_GC_SHARED_SATBMARKQUEUE_HPP
27
28#include "gc/shared/ptrQueue.hpp"
29#include "memory/allocation.hpp"
30
31class Thread;
32class Monitor;
33class SATBMarkQueueSet;
34
35// Base class for processing the contents of a SATB buffer.
36class SATBBufferClosure : public StackObj {
37protected:
38 ~SATBBufferClosure() { }
39
40public:
41 // Process the SATB entries in the designated buffer range.
42 virtual void do_buffer(void** buffer, size_t size) = 0;
43};
44
45// A PtrQueue whose elements are (possibly stale) pointers to object heads.
46class SATBMarkQueue: public PtrQueue {
47 friend class SATBMarkQueueSet;
48
49private:
50 // Filter out unwanted entries from the buffer.
51 inline void filter();
52
53 // Removes entries from the buffer that are no longer needed.
54 template<typename Filter>
55 inline void apply_filter(Filter filter_out);
56
57protected:
58 virtual void handle_completed_buffer();
59
60public:
61 SATBMarkQueue(SATBMarkQueueSet* qset);
62
63 // Process queue entries and free resources.
64 void flush();
65
66 inline SATBMarkQueueSet* satb_qset() const;
67
68 // Apply cl to the active part of the buffer.
69 // Prerequisite: Must be at a safepoint.
70 void apply_closure_and_empty(SATBBufferClosure* cl);
71
72#ifndef PRODUCT
73 // Helpful for debugging
74 void print(const char* name);
75#endif // PRODUCT
76
77 // Compiler support.
78 static ByteSize byte_offset_of_index() {
79 return PtrQueue::byte_offset_of_index<SATBMarkQueue>();
80 }
81 using PtrQueue::byte_width_of_index;
82
83 static ByteSize byte_offset_of_buf() {
84 return PtrQueue::byte_offset_of_buf<SATBMarkQueue>();
85 }
86 using PtrQueue::byte_width_of_buf;
87
88 static ByteSize byte_offset_of_active() {
89 return PtrQueue::byte_offset_of_active<SATBMarkQueue>();
90 }
91 using PtrQueue::byte_width_of_active;
92
93};
94
95class SATBMarkQueueSet: public PtrQueueSet {
96 size_t _buffer_enqueue_threshold;
97
98#ifdef ASSERT
99 void dump_active_states(bool expected_active);
100 void verify_active_states(bool expected_active);
101#endif // ASSERT
102
103protected:
104 SATBMarkQueueSet();
105 ~SATBMarkQueueSet() {}
106
107 template<typename Filter>
108 void apply_filter(Filter filter, SATBMarkQueue* queue) {
109 queue->apply_filter(filter);
110 }
111
112 void initialize(Monitor* cbl_mon,
113 BufferNode::Allocator* allocator,
114 size_t process_completed_buffers_threshold,
115 uint buffer_enqueue_threshold_percentage);
116
117public:
118 virtual SATBMarkQueue& satb_queue_for_thread(Thread* const t) const = 0;
119
120 // Apply "set_active(active)" to all SATB queues in the set. It should be
121 // called only with the world stopped. The method will assert that the
122 // SATB queues of all threads it visits, as well as the SATB queue
123 // set itself, has an active value same as expected_active.
124 void set_active_all_threads(bool active, bool expected_active);
125
126 size_t buffer_enqueue_threshold() const { return _buffer_enqueue_threshold; }
127 virtual void filter(SATBMarkQueue* queue) = 0;
128
129 // If there exists some completed buffer, pop and process it, and
130 // return true. Otherwise return false. Processing a buffer
131 // consists of applying the closure to the active range of the
132 // buffer; the leading entries may be excluded due to filtering.
133 bool apply_closure_to_completed_buffer(SATBBufferClosure* cl);
134
135#ifndef PRODUCT
136 // Helpful for debugging
137 void print_all(const char* msg);
138#endif // PRODUCT
139
140 // If a marking is being abandoned, reset any unprocessed log buffers.
141 void abandon_partial_marking();
142};
143
144inline SATBMarkQueueSet* SATBMarkQueue::satb_qset() const {
145 return static_cast<SATBMarkQueueSet*>(qset());
146}
147
148inline void SATBMarkQueue::filter() {
149 satb_qset()->filter(this);
150}
151
152// Removes entries from the buffer that are no longer needed, as
153// determined by filter. If e is a void* entry in the buffer,
154// filter_out(e) must be a valid expression whose value is convertible
155// to bool. Entries are removed (filtered out) if the result is true,
156// retained if false.
157template<typename Filter>
158inline void SATBMarkQueue::apply_filter(Filter filter_out) {
159 void** buf = this->_buf;
160
161 if (buf == NULL) {
162 // nothing to do
163 return;
164 }
165
166 // Two-fingered compaction toward the end.
167 void** src = &buf[this->index()];
168 void** dst = &buf[this->capacity()];
169 assert(src <= dst, "invariant");
170 for ( ; src < dst; ++src) {
171 // Search low to high for an entry to keep.
172 void* entry = *src;
173 if (!filter_out(entry)) {
174 // Found keeper. Search high to low for an entry to discard.
175 while (src < --dst) {
176 if (filter_out(*dst)) {
177 *dst = entry; // Replace discard with keeper.
178 break;
179 }
180 }
181 // If discard search failed (src == dst), the outer loop will also end.
182 }
183 }
184 // dst points to the lowest retained entry, or the end of the buffer
185 // if all the entries were filtered out.
186 this->set_index(dst - buf);
187}
188
189#endif // SHARE_GC_SHARED_SATBMARKQUEUE_HPP
190