Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/gc/serial/genMarkSweep.cpp
41149 views
1
/*
2
* Copyright (c) 2001, 2021, 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
#include "precompiled.hpp"
26
#include "classfile/classLoaderDataGraph.hpp"
27
#include "classfile/javaClasses.hpp"
28
#include "classfile/stringTable.hpp"
29
#include "classfile/symbolTable.hpp"
30
#include "classfile/systemDictionary.hpp"
31
#include "classfile/vmSymbols.hpp"
32
#include "code/codeCache.hpp"
33
#include "code/icBuffer.hpp"
34
#include "compiler/oopMap.hpp"
35
#include "gc/serial/genMarkSweep.hpp"
36
#include "gc/serial/serialGcRefProcProxyTask.hpp"
37
#include "gc/shared/collectedHeap.inline.hpp"
38
#include "gc/shared/gcHeapSummary.hpp"
39
#include "gc/shared/gcTimer.hpp"
40
#include "gc/shared/gcTrace.hpp"
41
#include "gc/shared/gcTraceTime.inline.hpp"
42
#include "gc/shared/genCollectedHeap.hpp"
43
#include "gc/shared/generation.hpp"
44
#include "gc/shared/genOopClosures.inline.hpp"
45
#include "gc/shared/modRefBarrierSet.hpp"
46
#include "gc/shared/referencePolicy.hpp"
47
#include "gc/shared/referenceProcessorPhaseTimes.hpp"
48
#include "gc/shared/space.hpp"
49
#include "gc/shared/strongRootsScope.hpp"
50
#include "gc/shared/weakProcessor.hpp"
51
#include "memory/universe.hpp"
52
#include "oops/instanceRefKlass.hpp"
53
#include "oops/oop.inline.hpp"
54
#include "prims/jvmtiExport.hpp"
55
#include "runtime/handles.inline.hpp"
56
#include "runtime/synchronizer.hpp"
57
#include "runtime/thread.inline.hpp"
58
#include "runtime/vmThread.hpp"
59
#include "utilities/copy.hpp"
60
#include "utilities/events.hpp"
61
#include "utilities/stack.inline.hpp"
62
#if INCLUDE_JVMCI
63
#include "jvmci/jvmci.hpp"
64
#endif
65
66
void GenMarkSweep::invoke_at_safepoint(ReferenceProcessor* rp, bool clear_all_softrefs) {
67
assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
68
69
GenCollectedHeap* gch = GenCollectedHeap::heap();
70
#ifdef ASSERT
71
if (gch->soft_ref_policy()->should_clear_all_soft_refs()) {
72
assert(clear_all_softrefs, "Policy should have been checked earlier");
73
}
74
#endif
75
76
// hook up weak ref data so it can be used during Mark-Sweep
77
assert(ref_processor() == NULL, "no stomping");
78
assert(rp != NULL, "should be non-NULL");
79
set_ref_processor(rp);
80
rp->setup_policy(clear_all_softrefs);
81
82
gch->trace_heap_before_gc(_gc_tracer);
83
84
// Increment the invocation count
85
_total_invocations++;
86
87
// Capture used regions for each generation that will be
88
// subject to collection, so that card table adjustments can
89
// be made intelligently (see clear / invalidate further below).
90
gch->save_used_regions();
91
92
allocate_stacks();
93
94
mark_sweep_phase1(clear_all_softrefs);
95
96
mark_sweep_phase2();
97
98
// Don't add any more derived pointers during phase3
99
#if COMPILER2_OR_JVMCI
100
assert(DerivedPointerTable::is_active(), "Sanity");
101
DerivedPointerTable::set_active(false);
102
#endif
103
104
mark_sweep_phase3();
105
106
mark_sweep_phase4();
107
108
restore_marks();
109
110
// Set saved marks for allocation profiler (and other things? -- dld)
111
// (Should this be in general part?)
112
gch->save_marks();
113
114
deallocate_stacks();
115
116
// If compaction completely evacuated the young generation then we
117
// can clear the card table. Otherwise, we must invalidate
118
// it (consider all cards dirty). In the future, we might consider doing
119
// compaction within generations only, and doing card-table sliding.
120
CardTableRS* rs = gch->rem_set();
121
Generation* old_gen = gch->old_gen();
122
123
// Clear/invalidate below make use of the "prev_used_regions" saved earlier.
124
if (gch->young_gen()->used() == 0) {
125
// We've evacuated the young generation.
126
rs->clear_into_younger(old_gen);
127
} else {
128
// Invalidate the cards corresponding to the currently used
129
// region and clear those corresponding to the evacuated region.
130
rs->invalidate_or_clear(old_gen);
131
}
132
133
gch->prune_scavengable_nmethods();
134
135
// refs processing: clean slate
136
set_ref_processor(NULL);
137
138
// Update heap occupancy information which is used as
139
// input to soft ref clearing policy at the next gc.
140
Universe::heap()->update_capacity_and_used_at_gc();
141
142
// Signal that we have completed a visit to all live objects.
143
Universe::heap()->record_whole_heap_examined_timestamp();
144
145
gch->trace_heap_after_gc(_gc_tracer);
146
}
147
148
void GenMarkSweep::allocate_stacks() {
149
GenCollectedHeap* gch = GenCollectedHeap::heap();
150
// Scratch request on behalf of old generation; will do no allocation.
151
ScratchBlock* scratch = gch->gather_scratch(gch->old_gen(), 0);
152
153
// $$$ To cut a corner, we'll only use the first scratch block, and then
154
// revert to malloc.
155
if (scratch != NULL) {
156
_preserved_count_max =
157
scratch->num_words * HeapWordSize / sizeof(PreservedMark);
158
} else {
159
_preserved_count_max = 0;
160
}
161
162
_preserved_marks = (PreservedMark*)scratch;
163
_preserved_count = 0;
164
}
165
166
167
void GenMarkSweep::deallocate_stacks() {
168
GenCollectedHeap* gch = GenCollectedHeap::heap();
169
gch->release_scratch();
170
171
_preserved_mark_stack.clear(true);
172
_preserved_oop_stack.clear(true);
173
_marking_stack.clear();
174
_objarray_stack.clear(true);
175
}
176
177
void GenMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
178
// Recursively traverse all live objects and mark them
179
GCTraceTime(Info, gc, phases) tm("Phase 1: Mark live objects", _gc_timer);
180
181
GenCollectedHeap* gch = GenCollectedHeap::heap();
182
183
// Need new claim bits before marking starts.
184
ClassLoaderDataGraph::clear_claimed_marks();
185
186
{
187
StrongRootsScope srs(0);
188
189
gch->full_process_roots(false, // not the adjust phase
190
GenCollectedHeap::SO_None,
191
ClassUnloading, // only strong roots if ClassUnloading
192
// is enabled
193
&follow_root_closure,
194
&follow_cld_closure);
195
}
196
197
// Process reference objects found during marking
198
{
199
GCTraceTime(Debug, gc, phases) tm_m("Reference Processing", gc_timer());
200
201
ref_processor()->setup_policy(clear_all_softrefs);
202
ReferenceProcessorPhaseTimes pt(_gc_timer, ref_processor()->max_num_queues());
203
SerialGCRefProcProxyTask task(is_alive, keep_alive, follow_stack_closure);
204
const ReferenceProcessorStats& stats = ref_processor()->process_discovered_references(task, pt);
205
pt.print_all_references();
206
gc_tracer()->report_gc_reference_stats(stats);
207
}
208
209
// This is the point where the entire marking should have completed.
210
assert(_marking_stack.is_empty(), "Marking should have completed");
211
212
{
213
GCTraceTime(Debug, gc, phases) tm_m("Weak Processing", gc_timer());
214
WeakProcessor::weak_oops_do(&is_alive, &do_nothing_cl);
215
}
216
217
{
218
GCTraceTime(Debug, gc, phases) tm_m("Class Unloading", gc_timer());
219
220
// Unload classes and purge the SystemDictionary.
221
bool purged_class = SystemDictionary::do_unloading(gc_timer());
222
223
// Unload nmethods.
224
CodeCache::do_unloading(&is_alive, purged_class);
225
226
// Prune dead klasses from subklass/sibling/implementor lists.
227
Klass::clean_weak_klass_links(purged_class);
228
229
// Clean JVMCI metadata handles.
230
JVMCI_ONLY(JVMCI::do_unloading(purged_class));
231
}
232
233
gc_tracer()->report_object_count_after_gc(&is_alive);
234
}
235
236
237
void GenMarkSweep::mark_sweep_phase2() {
238
// Now all live objects are marked, compute the new object addresses.
239
240
// It is imperative that we traverse perm_gen LAST. If dead space is
241
// allowed a range of dead object may get overwritten by a dead int
242
// array. If perm_gen is not traversed last a Klass* may get
243
// overwritten. This is fine since it is dead, but if the class has dead
244
// instances we have to skip them, and in order to find their size we
245
// need the Klass*!
246
//
247
// It is not required that we traverse spaces in the same order in
248
// phase2, phase3 and phase4, but the ValidateMarkSweep live oops
249
// tracking expects us to do so. See comment under phase4.
250
251
GenCollectedHeap* gch = GenCollectedHeap::heap();
252
253
GCTraceTime(Info, gc, phases) tm("Phase 2: Compute new object addresses", _gc_timer);
254
255
gch->prepare_for_compaction();
256
}
257
258
class GenAdjustPointersClosure: public GenCollectedHeap::GenClosure {
259
public:
260
void do_generation(Generation* gen) {
261
gen->adjust_pointers();
262
}
263
};
264
265
void GenMarkSweep::mark_sweep_phase3() {
266
GenCollectedHeap* gch = GenCollectedHeap::heap();
267
268
// Adjust the pointers to reflect the new locations
269
GCTraceTime(Info, gc, phases) tm("Phase 3: Adjust pointers", gc_timer());
270
271
// Need new claim bits for the pointer adjustment tracing.
272
ClassLoaderDataGraph::clear_claimed_marks();
273
274
{
275
StrongRootsScope srs(0);
276
277
gch->full_process_roots(true, // this is the adjust phase
278
GenCollectedHeap::SO_AllCodeCache,
279
false, // all roots
280
&adjust_pointer_closure,
281
&adjust_cld_closure);
282
}
283
284
gch->gen_process_weak_roots(&adjust_pointer_closure);
285
286
adjust_marks();
287
GenAdjustPointersClosure blk;
288
gch->generation_iterate(&blk, true);
289
}
290
291
class GenCompactClosure: public GenCollectedHeap::GenClosure {
292
public:
293
void do_generation(Generation* gen) {
294
gen->compact();
295
}
296
};
297
298
void GenMarkSweep::mark_sweep_phase4() {
299
// All pointers are now adjusted, move objects accordingly
300
301
// It is imperative that we traverse perm_gen first in phase4. All
302
// classes must be allocated earlier than their instances, and traversing
303
// perm_gen first makes sure that all Klass*s have moved to their new
304
// location before any instance does a dispatch through it's klass!
305
306
// The ValidateMarkSweep live oops tracking expects us to traverse spaces
307
// in the same order in phase2, phase3 and phase4. We don't quite do that
308
// here (perm_gen first rather than last), so we tell the validate code
309
// to use a higher index (saved from phase2) when verifying perm_gen.
310
GenCollectedHeap* gch = GenCollectedHeap::heap();
311
312
GCTraceTime(Info, gc, phases) tm("Phase 4: Move objects", _gc_timer);
313
314
GenCompactClosure blk;
315
gch->generation_iterate(&blk, true);
316
}
317
318