-
Notifications
You must be signed in to change notification settings - Fork 5.3k
/
markSweep.cpp
237 lines (197 loc) · 8.57 KB
/
markSweep.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "compiler/compileBroker.hpp"
#include "gc/serial/markSweep.inline.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
#include "gc/shared/gcTimer.hpp"
#include "gc/shared/gcTrace.hpp"
#include "gc/shared/gc_globals.hpp"
#include "memory/iterator.inline.hpp"
#include "memory/universe.hpp"
#include "oops/access.inline.hpp"
#include "oops/compressedOops.inline.hpp"
#include "oops/methodData.hpp"
#include "oops/objArrayKlass.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/typeArrayOop.inline.hpp"
#include "utilities/stack.inline.hpp"
uint MarkSweep::_total_invocations = 0;
Stack<oop, mtGC> MarkSweep::_marking_stack;
Stack<ObjArrayTask, mtGC> MarkSweep::_objarray_stack;
PreservedMarksSet MarkSweep::_preserved_overflow_stack_set(false /* in_c_heap */);
size_t MarkSweep::_preserved_count = 0;
size_t MarkSweep::_preserved_count_max = 0;
PreservedMark* MarkSweep::_preserved_marks = nullptr;
STWGCTimer* MarkSweep::_gc_timer = nullptr;
SerialOldTracer* MarkSweep::_gc_tracer = nullptr;
AlwaysTrueClosure MarkSweep::_always_true_closure;
ReferenceProcessor* MarkSweep::_ref_processor;
StringDedup::Requests* MarkSweep::_string_dedup_requests = nullptr;
MarkSweep::FollowRootClosure MarkSweep::follow_root_closure;
MarkAndPushClosure MarkSweep::mark_and_push_closure(ClassLoaderData::_claim_stw_fullgc_mark);
CLDToOopClosure MarkSweep::follow_cld_closure(&mark_and_push_closure, ClassLoaderData::_claim_stw_fullgc_mark);
CLDToOopClosure MarkSweep::adjust_cld_closure(&adjust_pointer_closure, ClassLoaderData::_claim_stw_fullgc_adjust);
template <class T> void MarkSweep::KeepAliveClosure::do_oop_work(T* p) {
mark_and_push(p);
}
void MarkSweep::push_objarray(oop obj, size_t index) {
ObjArrayTask task(obj, index);
assert(task.is_valid(), "bad ObjArrayTask");
_objarray_stack.push(task);
}
void MarkSweep::follow_array(objArrayOop array) {
mark_and_push_closure.do_klass(array->klass());
// Don't push empty arrays to avoid unnecessary work.
if (array->length() > 0) {
MarkSweep::push_objarray(array, 0);
}
}
void MarkSweep::follow_object(oop obj) {
assert(obj->is_gc_marked(), "should be marked");
if (obj->is_objArray()) {
// Handle object arrays explicitly to allow them to
// be split into chunks if needed.
MarkSweep::follow_array((objArrayOop)obj);
} else {
obj->oop_iterate(&mark_and_push_closure);
}
}
void MarkSweep::follow_array_chunk(objArrayOop array, int index) {
const int len = array->length();
const int beg_index = index;
assert(beg_index < len || len == 0, "index too large");
const int stride = MIN2(len - beg_index, (int) ObjArrayMarkingStride);
const int end_index = beg_index + stride;
array->oop_iterate_range(&mark_and_push_closure, beg_index, end_index);
if (end_index < len) {
MarkSweep::push_objarray(array, end_index); // Push the continuation.
}
}
void MarkSweep::follow_stack() {
do {
while (!_marking_stack.is_empty()) {
oop obj = _marking_stack.pop();
assert (obj->is_gc_marked(), "p must be marked");
follow_object(obj);
}
// Process ObjArrays one at a time to avoid marking stack bloat.
if (!_objarray_stack.is_empty()) {
ObjArrayTask task = _objarray_stack.pop();
follow_array_chunk(objArrayOop(task.obj()), task.index());
}
} while (!_marking_stack.is_empty() || !_objarray_stack.is_empty());
}
MarkSweep::FollowStackClosure MarkSweep::follow_stack_closure;
void MarkSweep::FollowStackClosure::do_void() { follow_stack(); }
template <class T> void MarkSweep::follow_root(T* p) {
assert(!Universe::heap()->is_in(p),
"roots shouldn't be things within the heap");
T heap_oop = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(heap_oop)) {
oop obj = CompressedOops::decode_not_null(heap_oop);
if (!obj->mark().is_marked()) {
mark_object(obj);
follow_object(obj);
}
}
follow_stack();
}
void MarkSweep::FollowRootClosure::do_oop(oop* p) { follow_root(p); }
void MarkSweep::FollowRootClosure::do_oop(narrowOop* p) { follow_root(p); }
// We preserve the mark which should be replaced at the end and the location
// that it will go. Note that the object that this markWord belongs to isn't
// currently at that address but it will be after phase4
void MarkSweep::preserve_mark(oop obj, markWord mark) {
// We try to store preserved marks in the to space of the new generation since
// this is storage which should be available. Most of the time this should be
// sufficient space for the marks we need to preserve but if it isn't we fall
// back to using Stacks to keep track of the overflow.
if (_preserved_count < _preserved_count_max) {
_preserved_marks[_preserved_count++] = PreservedMark(obj, mark);
} else {
_preserved_overflow_stack_set.get()->push_always(obj, mark);
}
}
void MarkSweep::mark_object(oop obj) {
if (StringDedup::is_enabled() &&
java_lang_String::is_instance(obj) &&
SerialStringDedup::is_candidate_from_mark(obj)) {
_string_dedup_requests->add(obj);
}
// some marks may contain information we need to preserve so we store them away
// and overwrite the mark. We'll restore it at the end of markSweep.
markWord mark = obj->mark();
obj->set_mark(markWord::prototype().set_marked());
ContinuationGCSupport::transform_stack_chunk(obj);
if (obj->mark_must_be_preserved(mark)) {
preserve_mark(obj, mark);
}
}
template <class T> void MarkSweep::mark_and_push(T* p) {
T heap_oop = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(heap_oop)) {
oop obj = CompressedOops::decode_not_null(heap_oop);
if (!obj->mark().is_marked()) {
mark_object(obj);
_marking_stack.push(obj);
}
}
}
template <typename T>
void MarkAndPushClosure::do_oop_work(T* p) { MarkSweep::mark_and_push(p); }
void MarkAndPushClosure::do_oop( oop* p) { do_oop_work(p); }
void MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_work(p); }
AdjustPointerClosure MarkSweep::adjust_pointer_closure;
void MarkSweep::adjust_marks() {
// adjust the oops we saved earlier
for (size_t i = 0; i < _preserved_count; i++) {
PreservedMarks::adjust_preserved_mark(_preserved_marks + i);
}
// deal with the overflow stack
_preserved_overflow_stack_set.get()->adjust_during_full_gc();
}
void MarkSweep::restore_marks() {
log_trace(gc)("Restoring " SIZE_FORMAT " marks", _preserved_count + _preserved_overflow_stack_set.get()->size());
// restore the marks we saved earlier
for (size_t i = 0; i < _preserved_count; i++) {
_preserved_marks[i].set_mark();
}
// deal with the overflow
_preserved_overflow_stack_set.restore(nullptr);
}
MarkSweep::IsAliveClosure MarkSweep::is_alive;
bool MarkSweep::IsAliveClosure::do_object_b(oop p) { return p->is_gc_marked(); }
MarkSweep::KeepAliveClosure MarkSweep::keep_alive;
void MarkSweep::KeepAliveClosure::do_oop(oop* p) { MarkSweep::KeepAliveClosure::do_oop_work(p); }
void MarkSweep::KeepAliveClosure::do_oop(narrowOop* p) { MarkSweep::KeepAliveClosure::do_oop_work(p); }
void MarkSweep::initialize() {
MarkSweep::_gc_timer = new STWGCTimer();
MarkSweep::_gc_tracer = new SerialOldTracer();
MarkSweep::_string_dedup_requests = new StringDedup::Requests();
// The Full GC operates on the entire heap so all objects should be subject
// to discovery, hence the _always_true_closure.
MarkSweep::_ref_processor = new ReferenceProcessor(&_always_true_closure);
mark_and_push_closure.set_ref_discoverer(_ref_processor);
}