Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/gc/z/zBarrier.cpp
40957 views
1
/*
2
* Copyright (c) 2015, 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
#include "precompiled.hpp"
25
#include "classfile/javaClasses.hpp"
26
#include "gc/z/zBarrier.inline.hpp"
27
#include "gc/z/zHeap.inline.hpp"
28
#include "gc/z/zOop.inline.hpp"
29
#include "gc/z/zThread.inline.hpp"
30
#include "memory/iterator.inline.hpp"
31
#include "oops/oop.inline.hpp"
32
#include "runtime/safepoint.hpp"
33
#include "utilities/debug.hpp"
34
35
template <bool finalizable>
36
bool ZBarrier::should_mark_through(uintptr_t addr) {
37
// Finalizable marked oops can still exists on the heap after marking
38
// has completed, in which case we just want to convert this into a
39
// good oop and not push it on the mark stack.
40
if (!during_mark()) {
41
assert(ZAddress::is_marked(addr), "Should be marked");
42
assert(ZAddress::is_finalizable(addr), "Should be finalizable");
43
return false;
44
}
45
46
// During marking, we mark through already marked oops to avoid having
47
// some large part of the object graph hidden behind a pushed, but not
48
// yet flushed, entry on a mutator mark stack. Always marking through
49
// allows the GC workers to proceed through the object graph even if a
50
// mutator touched an oop first, which in turn will reduce the risk of
51
// having to flush mark stacks multiple times to terminate marking.
52
//
53
// However, when doing finalizable marking we don't always want to mark
54
// through. First, marking through an already strongly marked oop would
55
// be wasteful, since we will then proceed to do finalizable marking on
56
// an object which is, or will be, marked strongly. Second, marking
57
// through an already finalizable marked oop would also be wasteful,
58
// since such oops can never end up on a mutator mark stack and can
59
// therefore not hide some part of the object graph from GC workers.
60
if (finalizable) {
61
return !ZAddress::is_marked(addr);
62
}
63
64
// Mark through
65
return true;
66
}
67
68
template <bool gc_thread, bool follow, bool finalizable, bool publish>
69
uintptr_t ZBarrier::mark(uintptr_t addr) {
70
uintptr_t good_addr;
71
72
if (ZAddress::is_marked(addr)) {
73
// Already marked, but try to mark though anyway
74
good_addr = ZAddress::good(addr);
75
} else if (ZAddress::is_remapped(addr)) {
76
// Already remapped, but also needs to be marked
77
good_addr = ZAddress::good(addr);
78
} else {
79
// Needs to be both remapped and marked
80
good_addr = remap(addr);
81
}
82
83
// Mark
84
if (should_mark_through<finalizable>(addr)) {
85
ZHeap::heap()->mark_object<gc_thread, follow, finalizable, publish>(good_addr);
86
}
87
88
if (finalizable) {
89
// Make the oop finalizable marked/good, instead of normal marked/good.
90
// This is needed because an object might first becomes finalizable
91
// marked by the GC, and then loaded by a mutator thread. In this case,
92
// the mutator thread must be able to tell that the object needs to be
93
// strongly marked. The finalizable bit in the oop exists to make sure
94
// that a load of a finalizable marked oop will fall into the barrier
95
// slow path so that we can mark the object as strongly reachable.
96
return ZAddress::finalizable_good(good_addr);
97
}
98
99
return good_addr;
100
}
101
102
uintptr_t ZBarrier::remap(uintptr_t addr) {
103
assert(!ZAddress::is_good(addr), "Should not be good");
104
assert(!ZAddress::is_weak_good(addr), "Should not be weak good");
105
return ZHeap::heap()->remap_object(addr);
106
}
107
108
uintptr_t ZBarrier::relocate(uintptr_t addr) {
109
assert(!ZAddress::is_good(addr), "Should not be good");
110
assert(!ZAddress::is_weak_good(addr), "Should not be weak good");
111
return ZHeap::heap()->relocate_object(addr);
112
}
113
114
uintptr_t ZBarrier::relocate_or_mark(uintptr_t addr) {
115
return during_relocate() ? relocate(addr) : mark<AnyThread, Follow, Strong, Publish>(addr);
116
}
117
118
uintptr_t ZBarrier::relocate_or_mark_no_follow(uintptr_t addr) {
119
return during_relocate() ? relocate(addr) : mark<AnyThread, DontFollow, Strong, Publish>(addr);
120
}
121
122
uintptr_t ZBarrier::relocate_or_remap(uintptr_t addr) {
123
return during_relocate() ? relocate(addr) : remap(addr);
124
}
125
126
//
127
// Load barrier
128
//
129
uintptr_t ZBarrier::load_barrier_on_oop_slow_path(uintptr_t addr) {
130
return relocate_or_mark(addr);
131
}
132
133
uintptr_t ZBarrier::load_barrier_on_invisible_root_oop_slow_path(uintptr_t addr) {
134
return relocate_or_mark_no_follow(addr);
135
}
136
137
void ZBarrier::load_barrier_on_oop_fields(oop o) {
138
assert(ZAddress::is_good(ZOop::to_address(o)), "Should be good");
139
ZLoadBarrierOopClosure cl;
140
o->oop_iterate(&cl);
141
}
142
143
//
144
// Weak load barrier
145
//
146
uintptr_t ZBarrier::weak_load_barrier_on_oop_slow_path(uintptr_t addr) {
147
return ZAddress::is_weak_good(addr) ? ZAddress::good(addr) : relocate_or_remap(addr);
148
}
149
150
uintptr_t ZBarrier::weak_load_barrier_on_weak_oop_slow_path(uintptr_t addr) {
151
const uintptr_t good_addr = weak_load_barrier_on_oop_slow_path(addr);
152
if (ZHeap::heap()->is_object_strongly_live(good_addr)) {
153
return good_addr;
154
}
155
156
// Not strongly live
157
return 0;
158
}
159
160
uintptr_t ZBarrier::weak_load_barrier_on_phantom_oop_slow_path(uintptr_t addr) {
161
const uintptr_t good_addr = weak_load_barrier_on_oop_slow_path(addr);
162
if (ZHeap::heap()->is_object_live(good_addr)) {
163
return good_addr;
164
}
165
166
// Not live
167
return 0;
168
}
169
170
//
171
// Keep alive barrier
172
//
173
uintptr_t ZBarrier::keep_alive_barrier_on_oop_slow_path(uintptr_t addr) {
174
assert(during_mark(), "Invalid phase");
175
176
// Mark
177
return mark<AnyThread, Follow, Strong, Overflow>(addr);
178
}
179
180
uintptr_t ZBarrier::keep_alive_barrier_on_weak_oop_slow_path(uintptr_t addr) {
181
const uintptr_t good_addr = weak_load_barrier_on_oop_slow_path(addr);
182
assert(ZHeap::heap()->is_object_strongly_live(good_addr), "Should be live");
183
return good_addr;
184
}
185
186
uintptr_t ZBarrier::keep_alive_barrier_on_phantom_oop_slow_path(uintptr_t addr) {
187
const uintptr_t good_addr = weak_load_barrier_on_oop_slow_path(addr);
188
assert(ZHeap::heap()->is_object_live(good_addr), "Should be live");
189
return good_addr;
190
}
191
192
//
193
// Mark barrier
194
//
195
uintptr_t ZBarrier::mark_barrier_on_oop_slow_path(uintptr_t addr) {
196
assert(during_mark(), "Invalid phase");
197
assert(ZThread::is_worker(), "Invalid thread");
198
199
// Mark
200
return mark<GCThread, Follow, Strong, Overflow>(addr);
201
}
202
203
uintptr_t ZBarrier::mark_barrier_on_finalizable_oop_slow_path(uintptr_t addr) {
204
assert(during_mark(), "Invalid phase");
205
assert(ZThread::is_worker(), "Invalid thread");
206
207
// Mark
208
return mark<GCThread, Follow, Finalizable, Overflow>(addr);
209
}
210
211
//
212
// Narrow oop variants, never used.
213
//
214
oop ZBarrier::load_barrier_on_oop_field(volatile narrowOop* p) {
215
ShouldNotReachHere();
216
return NULL;
217
}
218
219
oop ZBarrier::load_barrier_on_oop_field_preloaded(volatile narrowOop* p, oop o) {
220
ShouldNotReachHere();
221
return NULL;
222
}
223
224
void ZBarrier::load_barrier_on_oop_array(volatile narrowOop* p, size_t length) {
225
ShouldNotReachHere();
226
}
227
228
oop ZBarrier::load_barrier_on_weak_oop_field_preloaded(volatile narrowOop* p, oop o) {
229
ShouldNotReachHere();
230
return NULL;
231
}
232
233
oop ZBarrier::load_barrier_on_phantom_oop_field_preloaded(volatile narrowOop* p, oop o) {
234
ShouldNotReachHere();
235
return NULL;
236
}
237
238
oop ZBarrier::weak_load_barrier_on_oop_field_preloaded(volatile narrowOop* p, oop o) {
239
ShouldNotReachHere();
240
return NULL;
241
}
242
243
oop ZBarrier::weak_load_barrier_on_weak_oop_field_preloaded(volatile narrowOop* p, oop o) {
244
ShouldNotReachHere();
245
return NULL;
246
}
247
248
oop ZBarrier::weak_load_barrier_on_phantom_oop_field_preloaded(volatile narrowOop* p, oop o) {
249
ShouldNotReachHere();
250
return NULL;
251
}
252
253
#ifdef ASSERT
254
255
// ON_WEAK barriers should only ever be applied to j.l.r.Reference.referents.
256
void ZBarrier::verify_on_weak(volatile oop* referent_addr) {
257
if (referent_addr != NULL) {
258
uintptr_t base = (uintptr_t)referent_addr - java_lang_ref_Reference::referent_offset();
259
oop obj = cast_to_oop(base);
260
assert(oopDesc::is_oop(obj), "Verification failed for: ref " PTR_FORMAT " obj: " PTR_FORMAT, (uintptr_t)referent_addr, base);
261
assert(java_lang_ref_Reference::is_referent_field(obj, java_lang_ref_Reference::referent_offset()), "Sanity");
262
}
263
}
264
265
#endif
266
267
void ZLoadBarrierOopClosure::do_oop(oop* p) {
268
ZBarrier::load_barrier_on_oop_field(p);
269
}
270
271
void ZLoadBarrierOopClosure::do_oop(narrowOop* p) {
272
ShouldNotReachHere();
273
}
274
275