Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/runtime/flags/jvmFlagAccess.cpp
40957 views
1
/*
2
* Copyright (c) 2020, 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 "jfr/jfrEvents.hpp"
27
#include "memory/allocation.hpp"
28
#include "runtime/flags/jvmFlag.hpp"
29
#include "runtime/flags/jvmFlagAccess.hpp"
30
#include "runtime/flags/jvmFlagLimit.hpp"
31
#include "runtime/flags/jvmFlagConstraintsRuntime.hpp"
32
#include "runtime/os.hpp"
33
#include "utilities/macros.hpp"
34
#include "utilities/ostream.hpp"
35
36
template<typename T, typename EVENT>
37
static void trace_flag_changed(JVMFlag* flag, const T old_value, const T new_value, const JVMFlagOrigin origin) {
38
EVENT e;
39
e.set_name(flag->name());
40
e.set_oldValue(old_value);
41
e.set_newValue(new_value);
42
e.set_origin(static_cast<u8>(origin));
43
e.commit();
44
}
45
46
class FlagAccessImpl {
47
public:
48
JVMFlag::Error set(JVMFlag* flag, void* value, JVMFlagOrigin origin) const {
49
return set_impl(flag, value, origin);
50
}
51
52
virtual JVMFlag::Error set_impl(JVMFlag* flag, void* value, JVMFlagOrigin origin) const = 0;
53
virtual JVMFlag::Error check_range(const JVMFlag* flag, bool verbose) const { return JVMFlag::SUCCESS; }
54
virtual void print_range(outputStream* st, const JVMFlagLimit* range) const { ShouldNotReachHere(); }
55
virtual void print_default_range(outputStream* st) const { ShouldNotReachHere(); }
56
virtual JVMFlag::Error check_constraint(const JVMFlag* flag, void * func, bool verbose) const { return JVMFlag::SUCCESS; }
57
};
58
59
template <typename T, typename EVENT>
60
class TypedFlagAccessImpl : public FlagAccessImpl {
61
62
public:
63
JVMFlag::Error check_constraint_and_set(JVMFlag* flag, void* value_addr, JVMFlagOrigin origin, bool verbose) const {
64
T value = *((T*)value_addr);
65
const JVMTypedFlagLimit<T>* constraint = (const JVMTypedFlagLimit<T>*)JVMFlagLimit::get_constraint(flag);
66
if (constraint != NULL && constraint->phase() <= static_cast<int>(JVMFlagLimit::validating_phase())) {
67
JVMFlag::Error err = typed_check_constraint(constraint->constraint_func(), value, verbose);
68
if (err != JVMFlag::SUCCESS) {
69
return err;
70
}
71
}
72
73
T old_value = flag->read<T>();
74
trace_flag_changed<T, EVENT>(flag, old_value, value, origin);
75
flag->write<T>(value);
76
*((T*)value_addr) = old_value;
77
flag->set_origin(origin);
78
79
return JVMFlag::SUCCESS;
80
}
81
82
JVMFlag::Error check_constraint(const JVMFlag* flag, void * func, bool verbose) const {
83
return typed_check_constraint(func, flag->read<T>(), verbose);
84
}
85
86
virtual JVMFlag::Error typed_check_constraint(void * func, T value, bool verbose) const = 0;
87
};
88
89
class FlagAccessImpl_bool : public TypedFlagAccessImpl<bool, EventBooleanFlagChanged> {
90
public:
91
JVMFlag::Error set_impl(JVMFlag* flag, void* value_addr, JVMFlagOrigin origin) const {
92
bool verbose = JVMFlagLimit::verbose_checks_needed();
93
return TypedFlagAccessImpl<bool, EventBooleanFlagChanged>
94
::check_constraint_and_set(flag, value_addr, origin, verbose);
95
}
96
97
JVMFlag::Error typed_check_constraint(void* func, bool value, bool verbose) const {
98
return ((JVMFlagConstraintFunc_bool)func)(value, verbose);
99
}
100
};
101
102
template <typename T, typename EVENT>
103
class RangedFlagAccessImpl : public TypedFlagAccessImpl<T, EVENT> {
104
public:
105
virtual JVMFlag::Error set_impl(JVMFlag* flag, void* value_addr, JVMFlagOrigin origin) const {
106
T value = *((T*)value_addr);
107
bool verbose = JVMFlagLimit::verbose_checks_needed();
108
109
const JVMTypedFlagLimit<T>* range = (const JVMTypedFlagLimit<T>*)JVMFlagLimit::get_range(flag);
110
if (range != NULL) {
111
if ((value < range->min()) || (value > range->max())) {
112
range_error(flag->name(), value, range->min(), range->max(), verbose);
113
return JVMFlag::OUT_OF_BOUNDS;
114
}
115
}
116
117
return TypedFlagAccessImpl<T, EVENT>::check_constraint_and_set(flag, value_addr, origin, verbose);
118
}
119
120
virtual JVMFlag::Error check_range(const JVMFlag* flag, bool verbose) const {
121
const JVMTypedFlagLimit<T>* range = (const JVMTypedFlagLimit<T>*)JVMFlagLimit::get_range(flag);
122
if (range != NULL) {
123
T value = flag->read<T>();
124
if ((value < range->min()) || (value > range->max())) {
125
range_error(flag->name(), value, range->min(), range->max(), verbose);
126
return JVMFlag::OUT_OF_BOUNDS;
127
}
128
}
129
return JVMFlag::SUCCESS;
130
}
131
132
virtual void print_range(outputStream* st, const JVMFlagLimit* range) const {
133
const JVMTypedFlagLimit<T>* r = (const JVMTypedFlagLimit<T>*)range;
134
print_range_impl(st, r->min(), r->max());
135
}
136
137
virtual void range_error(const char* name, T value, T min, T max, bool verbose) const = 0;
138
virtual void print_range_impl(outputStream* st, T min, T max) const = 0;
139
};
140
141
class FlagAccessImpl_int : public RangedFlagAccessImpl<int, EventIntFlagChanged> {
142
public:
143
void range_error(const char* name, int value, int min, int max, bool verbose) const {
144
JVMFlag::printError(verbose,
145
"int %s=%d is outside the allowed range "
146
"[ %d ... %d ]\n",
147
name, value, min, max);
148
}
149
JVMFlag::Error typed_check_constraint(void* func, int value, bool verbose) const {
150
return ((JVMFlagConstraintFunc_int)func)(value, verbose);
151
}
152
void print_range_impl(outputStream* st, int min, int max) const {
153
st->print("[ %-25d ... %25d ]", min, max);
154
}
155
void print_default_range(outputStream* st) const {
156
st->print("[ " INT32_FORMAT_W(-25) " ... " INT32_FORMAT_W(25) " ]", INT_MIN, INT_MAX);
157
}
158
};
159
160
class FlagAccessImpl_uint : public RangedFlagAccessImpl<uint, EventUnsignedIntFlagChanged> {
161
public:
162
void range_error(const char* name, uint value, uint min, uint max, bool verbose) const {
163
JVMFlag::printError(verbose,
164
"uint %s=%u is outside the allowed range "
165
"[ %u ... %u ]\n",
166
name, value, min, max);
167
}
168
JVMFlag::Error typed_check_constraint(void* func, uint value, bool verbose) const {
169
return ((JVMFlagConstraintFunc_uint)func)(value, verbose);
170
}
171
void print_range_impl(outputStream* st, uint min, uint max) const {
172
st->print("[ %-25u ... %25u ]", min, max);
173
}
174
void print_default_range(outputStream* st) const {
175
st->print("[ " UINT32_FORMAT_W(-25) " ... " UINT32_FORMAT_W(25) " ]", 0, UINT_MAX);
176
}
177
};
178
179
class FlagAccessImpl_intx : public RangedFlagAccessImpl<intx, EventLongFlagChanged> {
180
public:
181
void range_error(const char* name, intx value, intx min, intx max, bool verbose) const {
182
JVMFlag::printError(verbose,
183
"intx %s=" INTX_FORMAT " is outside the allowed range "
184
"[ " INTX_FORMAT " ... " INTX_FORMAT " ]\n",
185
name, value, min, max);
186
}
187
JVMFlag::Error typed_check_constraint(void* func, intx value, bool verbose) const {
188
return ((JVMFlagConstraintFunc_intx)func)(value, verbose);
189
}
190
void print_range_impl(outputStream* st, intx min, intx max) const {
191
st->print("[ " INTX_FORMAT_W(-25) " ... " INTX_FORMAT_W(25) " ]", min, max);
192
}
193
void print_default_range(outputStream* st) const {
194
st->print("[ " INTX_FORMAT_W(-25) " ... " INTX_FORMAT_W(25) " ]", min_intx, max_intx);
195
}
196
};
197
198
class FlagAccessImpl_uintx : public RangedFlagAccessImpl<uintx, EventUnsignedLongFlagChanged> {
199
public:
200
void range_error(const char* name, uintx value, uintx min, uintx max, bool verbose) const {
201
JVMFlag::printError(verbose,
202
"uintx %s=" UINTX_FORMAT " is outside the allowed range "
203
"[ " UINTX_FORMAT " ... " UINTX_FORMAT " ]\n",
204
name, value, min, max);
205
}
206
JVMFlag::Error typed_check_constraint(void* func, uintx value, bool verbose) const {
207
return ((JVMFlagConstraintFunc_uintx)func)(value, verbose);
208
}
209
void print_range_impl(outputStream* st, uintx min, uintx max) const {
210
st->print("[ " UINTX_FORMAT_W(-25) " ... " UINTX_FORMAT_W(25) " ]", min, max);
211
}
212
void print_default_range(outputStream* st) const {
213
st->print("[ " UINTX_FORMAT_W(-25) " ... " UINTX_FORMAT_W(25) " ]", uintx(0), max_uintx);
214
}
215
};
216
217
class FlagAccessImpl_uint64_t : public RangedFlagAccessImpl<uint64_t, EventUnsignedLongFlagChanged> {
218
public:
219
void range_error(const char* name, uint64_t value, uint64_t min, uint64_t max, bool verbose) const {
220
JVMFlag::printError(verbose,
221
"uint64_t %s=" UINT64_FORMAT " is outside the allowed range "
222
"[ " UINT64_FORMAT " ... " UINT64_FORMAT " ]\n",
223
name, value, min, max);
224
}
225
JVMFlag::Error typed_check_constraint(void* func, uint64_t value, bool verbose) const {
226
return ((JVMFlagConstraintFunc_uint64_t)func)(value, verbose);
227
}
228
void print_range_impl(outputStream* st, uint64_t min, uint64_t max) const {
229
st->print("[ " UINT64_FORMAT_W(-25) " ... " UINT64_FORMAT_W(25) " ]", min, max);
230
}
231
void print_default_range(outputStream* st) const {
232
st->print("[ " UINT64_FORMAT_W(-25) " ... " UINT64_FORMAT_W(25) " ]", uint64_t(0), uint64_t(max_juint));
233
}
234
};
235
236
class FlagAccessImpl_size_t : public RangedFlagAccessImpl<size_t, EventUnsignedLongFlagChanged> {
237
public:
238
void range_error(const char* name, size_t value, size_t min, size_t max, bool verbose) const {
239
JVMFlag::printError(verbose,
240
"size_t %s=" SIZE_FORMAT " is outside the allowed range "
241
"[ " SIZE_FORMAT " ... " SIZE_FORMAT " ]\n",
242
name, value, min, max);
243
}
244
JVMFlag::Error typed_check_constraint(void* func, size_t value, bool verbose) const {
245
return ((JVMFlagConstraintFunc_size_t)func)(value, verbose);
246
}
247
void print_range_impl(outputStream* st, size_t min, size_t max) const {
248
st->print("[ " SIZE_FORMAT_W(-25) " ... " SIZE_FORMAT_W(25) " ]", min, max);
249
}
250
void print_default_range(outputStream* st) const {
251
st->print("[ " SIZE_FORMAT_W(-25) " ... " SIZE_FORMAT_W(25) " ]", size_t(0), size_t(SIZE_MAX));
252
}
253
};
254
255
class FlagAccessImpl_double : public RangedFlagAccessImpl<double, EventDoubleFlagChanged> {
256
public:
257
void range_error(const char* name, double value, double min, double max, bool verbose) const {
258
JVMFlag::printError(verbose,
259
"double %s=%f is outside the allowed range "
260
"[ %f ... %f ]\n",
261
name, value, min, max);
262
}
263
JVMFlag::Error typed_check_constraint(void* func, double value, bool verbose) const {
264
return ((JVMFlagConstraintFunc_double)func)(value, verbose);
265
}
266
void print_range_impl(outputStream* st, double min, double max) const {
267
st->print("[ %-25.3f ... %25.3f ]", min, max);
268
}
269
void print_default_range(outputStream* st) const {
270
st->print("[ %-25.3f ... %25.3f ]", DBL_MIN, DBL_MAX);
271
}
272
};
273
274
#define FLAG_ACCESS_IMPL_INIT(t) \
275
static FlagAccessImpl_ ## t flag_access_ ## t;
276
277
#define FLAG_ACCESS_IMPL_ADDR(t) \
278
&flag_access_ ## t,
279
280
JVM_FLAG_NON_STRING_TYPES_DO(FLAG_ACCESS_IMPL_INIT)
281
282
static const FlagAccessImpl* flag_accesss[JVMFlag::NUM_FLAG_TYPES] = {
283
JVM_FLAG_NON_STRING_TYPES_DO(FLAG_ACCESS_IMPL_ADDR)
284
// ccstr and ccstrlist have special setter
285
};
286
287
inline const FlagAccessImpl* JVMFlagAccess::access_impl(const JVMFlag* flag) {
288
int type = flag->type();
289
int max = (int)(sizeof(flag_accesss)/sizeof(flag_accesss[0]));
290
assert(type >= 0 && type < max , "sanity");
291
292
return flag_accesss[type];
293
}
294
295
JVMFlag::Error JVMFlagAccess::set_impl(JVMFlag* flag, void* value, JVMFlagOrigin origin) {
296
if (flag->is_ccstr()) {
297
return set_ccstr(flag, (ccstr*)value, origin);
298
} else {
299
return access_impl(flag)->set(flag, value, origin);
300
}
301
}
302
303
JVMFlag::Error JVMFlagAccess::set_ccstr(JVMFlag* flag, ccstr* value, JVMFlagOrigin origin) {
304
if (flag == NULL) return JVMFlag::INVALID_FLAG;
305
if (!flag->is_ccstr()) return JVMFlag::WRONG_FORMAT;
306
ccstr old_value = flag->get_ccstr();
307
trace_flag_changed<ccstr, EventStringFlagChanged>(flag, old_value, *value, origin);
308
char* new_value = NULL;
309
if (*value != NULL) {
310
new_value = os::strdup_check_oom(*value);
311
}
312
flag->set_ccstr(new_value);
313
if (!flag->is_default() && old_value != NULL) {
314
// Old value is heap allocated so free it.
315
FREE_C_HEAP_ARRAY(char, old_value);
316
}
317
// Unlike the other APIs, the old vale is NOT returned, so the caller won't need to free it.
318
// The callers typically don't care what the old value is.
319
// If the caller really wants to know the old value, read it (and make a copy if necessary)
320
// before calling this API.
321
*value = NULL;
322
flag->set_origin(origin);
323
return JVMFlag::SUCCESS;
324
}
325
326
// This is called by the FLAG_SET_XXX macros.
327
JVMFlag::Error JVMFlagAccess::set_or_assert(JVMFlagsEnum flag_enum, int type_enum, void* value, JVMFlagOrigin origin) {
328
JVMFlag* flag = JVMFlag::flag_from_enum(flag_enum);
329
if (type_enum == JVMFlag::TYPE_ccstr || type_enum == JVMFlag::TYPE_ccstrlist) {
330
assert(flag->is_ccstr(), "must be");
331
return set_ccstr(flag, (ccstr*)value, origin);
332
} else {
333
assert(flag->type() == type_enum, "wrong flag type");
334
return set_impl(flag, value, origin);
335
}
336
}
337
338
JVMFlag::Error JVMFlagAccess::check_range(const JVMFlag* flag, bool verbose) {
339
return access_impl(flag)->check_range(flag, verbose);
340
}
341
342
JVMFlag::Error JVMFlagAccess::check_constraint(const JVMFlag* flag, void * func, bool verbose) {
343
const int type_enum = flag->type();
344
if (type_enum == JVMFlag::TYPE_ccstr || type_enum == JVMFlag::TYPE_ccstrlist) {
345
// ccstr and ccstrlist are the same type.
346
return ((JVMFlagConstraintFunc_ccstr)func)(flag->get_ccstr(), verbose);
347
}
348
349
return access_impl(flag)->check_constraint(flag, func, verbose);
350
}
351
352
void JVMFlagAccess::print_range(outputStream* st, const JVMFlag* flag, const JVMFlagLimit* range) {
353
return access_impl(flag)->print_range(st, range);
354
}
355
356
void JVMFlagAccess::print_range(outputStream* st, const JVMFlag* flag) {
357
const JVMFlagLimit* range = JVMFlagLimit::get_range(flag);
358
if (range != NULL) {
359
print_range(st, flag, range);
360
} else {
361
const JVMFlagLimit* limit = JVMFlagLimit::get_constraint(flag);
362
if (limit != NULL) {
363
void* func = limit->constraint_func();
364
365
// Two special cases where the lower limit of the range is defined by an os:: function call
366
// and cannot be initialized at compile time with constexpr.
367
if (func == (void*)VMPageSizeConstraintFunc) {
368
uintx min = (uintx)os::vm_page_size();
369
uintx max = max_uintx;
370
371
JVMTypedFlagLimit<uintx> tmp(0, min, max);
372
access_impl(flag)->print_range(st, &tmp);
373
} else if (func == (void*)NUMAInterleaveGranularityConstraintFunc) {
374
size_t min = os::vm_allocation_granularity();
375
size_t max = NOT_LP64(2*G) LP64_ONLY(8192*G);
376
377
JVMTypedFlagLimit<size_t> tmp(0, min, max);
378
access_impl(flag)->print_range(st, &tmp);
379
} else {
380
access_impl(flag)->print_default_range(st);
381
}
382
} else {
383
st->print("[ ... ]");
384
}
385
}
386
}
387
388