1/*
2 * Copyright (c) 2015, 2018, 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 "jvm.h"
27#include "classfile/stringTable.hpp"
28#include "classfile/symbolTable.hpp"
29#include "gc/shared/referenceProcessor.hpp"
30#include "oops/markOop.hpp"
31#include "runtime/arguments.hpp"
32#include "runtime/flags/jvmFlag.hpp"
33#include "runtime/flags/jvmFlagConstraintList.hpp"
34#include "runtime/flags/jvmFlagRangeList.hpp"
35#include "runtime/globals.hpp"
36#include "runtime/os.hpp"
37#include "runtime/task.hpp"
38#include "utilities/macros.hpp"
39
40class JVMFlagRange_int : public JVMFlagRange {
41 int _min;
42 int _max;
43 const int* _ptr;
44
45public:
46 // the "name" argument must be a string literal
47 JVMFlagRange_int(const char* name, const int* ptr, int min, int max)
48 : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
49
50 JVMFlag::Error check(bool verbose = true) {
51 return check_int(*_ptr, verbose);
52 }
53
54 JVMFlag::Error check_int(int value, bool verbose = true) {
55 if ((value < _min) || (value > _max)) {
56 JVMFlag::printError(verbose,
57 "int %s=%d is outside the allowed range "
58 "[ %d ... %d ]\n",
59 name(), value, _min, _max);
60 return JVMFlag::OUT_OF_BOUNDS;
61 } else {
62 return JVMFlag::SUCCESS;
63 }
64 }
65
66 void print(outputStream* st) {
67 st->print("[ %-25d ... %25d ]", _min, _max);
68 }
69};
70
71class JVMFlagRange_intx : public JVMFlagRange {
72 intx _min;
73 intx _max;
74 const intx* _ptr;
75public:
76 // the "name" argument must be a string literal
77 JVMFlagRange_intx(const char* name, const intx* ptr, intx min, intx max)
78 : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
79
80 JVMFlag::Error check(bool verbose = true) {
81 return check_intx(*_ptr, verbose);
82 }
83
84 JVMFlag::Error check_intx(intx value, bool verbose = true) {
85 if ((value < _min) || (value > _max)) {
86 JVMFlag::printError(verbose,
87 "intx %s=" INTX_FORMAT " is outside the allowed range "
88 "[ " INTX_FORMAT " ... " INTX_FORMAT " ]\n",
89 name(), value, _min, _max);
90 return JVMFlag::OUT_OF_BOUNDS;
91 } else {
92 return JVMFlag::SUCCESS;
93 }
94 }
95
96 void print(outputStream* st) {
97 st->print("[ " INTX_FORMAT_W(-25) " ... " INTX_FORMAT_W(25) " ]", _min, _max);
98 }
99};
100
101class JVMFlagRange_uint : public JVMFlagRange {
102 uint _min;
103 uint _max;
104 const uint* _ptr;
105
106public:
107 // the "name" argument must be a string literal
108 JVMFlagRange_uint(const char* name, const uint* ptr, uint min, uint max)
109 : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
110
111 JVMFlag::Error check(bool verbose = true) {
112 return check_uint(*_ptr, verbose);
113 }
114
115 JVMFlag::Error check_uint(uint value, bool verbose = true) {
116 if ((value < _min) || (value > _max)) {
117 JVMFlag::printError(verbose,
118 "uint %s=%u is outside the allowed range "
119 "[ %u ... %u ]\n",
120 name(), value, _min, _max);
121 return JVMFlag::OUT_OF_BOUNDS;
122 } else {
123 return JVMFlag::SUCCESS;
124 }
125 }
126
127 void print(outputStream* st) {
128 st->print("[ %-25u ... %25u ]", _min, _max);
129 }
130};
131
132class JVMFlagRange_uintx : public JVMFlagRange {
133 uintx _min;
134 uintx _max;
135 const uintx* _ptr;
136
137public:
138 // the "name" argument must be a string literal
139 JVMFlagRange_uintx(const char* name, const uintx* ptr, uintx min, uintx max)
140 : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
141
142 JVMFlag::Error check(bool verbose = true) {
143 return check_uintx(*_ptr, verbose);
144 }
145
146 JVMFlag::Error check_uintx(uintx value, bool verbose = true) {
147 if ((value < _min) || (value > _max)) {
148 JVMFlag::printError(verbose,
149 "uintx %s=" UINTX_FORMAT " is outside the allowed range "
150 "[ " UINTX_FORMAT " ... " UINTX_FORMAT " ]\n",
151 name(), value, _min, _max);
152 return JVMFlag::OUT_OF_BOUNDS;
153 } else {
154 return JVMFlag::SUCCESS;
155 }
156 }
157
158 void print(outputStream* st) {
159 st->print("[ " UINTX_FORMAT_W(-25) " ... " UINTX_FORMAT_W(25) " ]", _min, _max);
160 }
161};
162
163class JVMFlagRange_uint64_t : public JVMFlagRange {
164 uint64_t _min;
165 uint64_t _max;
166 const uint64_t* _ptr;
167
168public:
169 // the "name" argument must be a string literal
170 JVMFlagRange_uint64_t(const char* name, const uint64_t* ptr, uint64_t min, uint64_t max)
171 : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
172
173 JVMFlag::Error check(bool verbose = true) {
174 return check_uint64_t(*_ptr, verbose);
175 }
176
177 JVMFlag::Error check_uint64_t(uint64_t value, bool verbose = true) {
178 if ((value < _min) || (value > _max)) {
179 JVMFlag::printError(verbose,
180 "uint64_t %s=" UINT64_FORMAT " is outside the allowed range "
181 "[ " UINT64_FORMAT " ... " UINT64_FORMAT " ]\n",
182 name(), value, _min, _max);
183 return JVMFlag::OUT_OF_BOUNDS;
184 } else {
185 return JVMFlag::SUCCESS;
186 }
187 }
188
189 void print(outputStream* st) {
190 st->print("[ " UINT64_FORMAT_W(-25) " ... " UINT64_FORMAT_W(25) " ]", _min, _max);
191 }
192};
193
194class JVMFlagRange_size_t : public JVMFlagRange {
195 size_t _min;
196 size_t _max;
197 const size_t* _ptr;
198
199public:
200 // the "name" argument must be a string literal
201 JVMFlagRange_size_t(const char* name, const size_t* ptr, size_t min, size_t max)
202 : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
203
204 JVMFlag::Error check(bool verbose = true) {
205 return check_size_t(*_ptr, verbose);
206 }
207
208 JVMFlag::Error check_size_t(size_t value, bool verbose = true) {
209 if ((value < _min) || (value > _max)) {
210 JVMFlag::printError(verbose,
211 "size_t %s=" SIZE_FORMAT " is outside the allowed range "
212 "[ " SIZE_FORMAT " ... " SIZE_FORMAT " ]\n",
213 name(), value, _min, _max);
214 return JVMFlag::OUT_OF_BOUNDS;
215 } else {
216 return JVMFlag::SUCCESS;
217 }
218 }
219
220 void print(outputStream* st) {
221 st->print("[ " SIZE_FORMAT_W(-25) " ... " SIZE_FORMAT_W(25) " ]", _min, _max);
222 }
223};
224
225class JVMFlagRange_double : public JVMFlagRange {
226 double _min;
227 double _max;
228 const double* _ptr;
229
230public:
231 // the "name" argument must be a string literal
232 JVMFlagRange_double(const char* name, const double* ptr, double min, double max)
233 : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
234
235 JVMFlag::Error check(bool verbose = true) {
236 return check_double(*_ptr, verbose);
237 }
238
239 JVMFlag::Error check_double(double value, bool verbose = true) {
240 if ((value < _min) || (value > _max)) {
241 JVMFlag::printError(verbose,
242 "double %s=%f is outside the allowed range "
243 "[ %f ... %f ]\n",
244 name(), value, _min, _max);
245 return JVMFlag::OUT_OF_BOUNDS;
246 } else {
247 return JVMFlag::SUCCESS;
248 }
249 }
250
251 void print(outputStream* st) {
252 st->print("[ %-25.3f ... %25.3f ]", _min, _max);
253 }
254};
255
256// No constraint emitting
257void emit_range_no(...) { /* NOP */ }
258
259// No constraint emitting if function argument is NOT provided
260void emit_range_bool(const char* /*name*/, const bool* /*value*/) { /* NOP */ }
261void emit_range_ccstr(const char* /*name*/, const ccstr* /*value*/) { /* NOP */ }
262void emit_range_ccstrlist(const char* /*name*/, const ccstrlist* /*value*/) { /* NOP */ }
263void emit_range_int(const char* /*name*/, const int* /*value*/) { /* NOP */ }
264void emit_range_intx(const char* /*name*/, const intx* /*value*/) { /* NOP */ }
265void emit_range_uint(const char* /*name*/, const uint* /*value*/) { /* NOP */ }
266void emit_range_uintx(const char* /*name*/, const uintx* /*value*/) { /* NOP */ }
267void emit_range_uint64_t(const char* /*name*/, const uint64_t* /*value*/) { /* NOP */ }
268void emit_range_size_t(const char* /*name*/, const size_t* /*value*/) { /* NOP */ }
269void emit_range_double(const char* /*name*/, const double* /*value*/) { /* NOP */ }
270
271// JVMFlagRange emitting code functions if range arguments are provided
272void emit_range_int(const char* name, const int* ptr, int min, int max) {
273 JVMFlagRangeList::add(new JVMFlagRange_int(name, ptr, min, max));
274}
275void emit_range_intx(const char* name, const intx* ptr, intx min, intx max) {
276 JVMFlagRangeList::add(new JVMFlagRange_intx(name, ptr, min, max));
277}
278void emit_range_uint(const char* name, const uint* ptr, uint min, uint max) {
279 JVMFlagRangeList::add(new JVMFlagRange_uint(name, ptr, min, max));
280}
281void emit_range_uintx(const char* name, const uintx* ptr, uintx min, uintx max) {
282 JVMFlagRangeList::add(new JVMFlagRange_uintx(name, ptr, min, max));
283}
284void emit_range_uint64_t(const char* name, const uint64_t* ptr, uint64_t min, uint64_t max) {
285 JVMFlagRangeList::add(new JVMFlagRange_uint64_t(name, ptr, min, max));
286}
287void emit_range_size_t(const char* name, const size_t* ptr, size_t min, size_t max) {
288 JVMFlagRangeList::add(new JVMFlagRange_size_t(name, ptr, min, max));
289}
290void emit_range_double(const char* name, const double* ptr, double min, double max) {
291 JVMFlagRangeList::add(new JVMFlagRange_double(name, ptr, min, max));
292}
293
294// Generate code to call emit_range_xxx function
295#define EMIT_RANGE_START (void)(0
296#define EMIT_RANGE(type, name) ); emit_range_##type(#name, &name
297#define EMIT_RANGE_NO ); emit_range_no(0
298#define EMIT_RANGE_PRODUCT_FLAG(type, name, value, doc) EMIT_RANGE(type, name)
299#define EMIT_RANGE_DIAGNOSTIC_FLAG(type, name, value, doc) EMIT_RANGE(type, name)
300#define EMIT_RANGE_EXPERIMENTAL_FLAG(type, name, value, doc) EMIT_RANGE(type, name)
301#define EMIT_RANGE_MANAGEABLE_FLAG(type, name, value, doc) EMIT_RANGE(type, name)
302#define EMIT_RANGE_PRODUCT_RW_FLAG(type, name, value, doc) EMIT_RANGE(type, name)
303#define EMIT_RANGE_PD_PRODUCT_FLAG(type, name, doc) EMIT_RANGE(type, name)
304#define EMIT_RANGE_PD_DIAGNOSTIC_FLAG(type, name, doc) EMIT_RANGE(type, name)
305#ifndef PRODUCT
306#define EMIT_RANGE_DEVELOPER_FLAG(type, name, value, doc) EMIT_RANGE(type, name)
307#define EMIT_RANGE_PD_DEVELOPER_FLAG(type, name, doc) EMIT_RANGE(type, name)
308#define EMIT_RANGE_NOTPRODUCT_FLAG(type, name, value, doc) EMIT_RANGE(type, name)
309#else
310#define EMIT_RANGE_DEVELOPER_FLAG(type, name, value, doc) EMIT_RANGE_NO
311#define EMIT_RANGE_PD_DEVELOPER_FLAG(type, name, doc) EMIT_RANGE_NO
312#define EMIT_RANGE_NOTPRODUCT_FLAG(type, name, value, doc) EMIT_RANGE_NO
313#endif
314#ifdef _LP64
315#define EMIT_RANGE_LP64_PRODUCT_FLAG(type, name, value, doc) EMIT_RANGE(type, name)
316#else
317#define EMIT_RANGE_LP64_PRODUCT_FLAG(type, name, value, doc) EMIT_RANGE_NO
318#endif
319#define EMIT_RANGE_END );
320
321// Generate func argument to pass into emit_range_xxx functions
322#define EMIT_RANGE_CHECK(a, b) , a, b
323
324#define INITIAL_RANGES_SIZE 379
325GrowableArray<JVMFlagRange*>* JVMFlagRangeList::_ranges = NULL;
326
327// Check the ranges of all flags that have them
328void JVMFlagRangeList::init(void) {
329
330 _ranges = new (ResourceObj::C_HEAP, mtArguments) GrowableArray<JVMFlagRange*>(INITIAL_RANGES_SIZE, true);
331
332 EMIT_RANGE_START
333
334 ALL_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
335 EMIT_RANGE_PD_DEVELOPER_FLAG,
336 EMIT_RANGE_PRODUCT_FLAG,
337 EMIT_RANGE_PD_PRODUCT_FLAG,
338 EMIT_RANGE_DIAGNOSTIC_FLAG,
339 EMIT_RANGE_PD_DIAGNOSTIC_FLAG,
340 EMIT_RANGE_EXPERIMENTAL_FLAG,
341 EMIT_RANGE_NOTPRODUCT_FLAG,
342 EMIT_RANGE_MANAGEABLE_FLAG,
343 EMIT_RANGE_PRODUCT_RW_FLAG,
344 EMIT_RANGE_LP64_PRODUCT_FLAG,
345 EMIT_RANGE_CHECK,
346 IGNORE_CONSTRAINT,
347 IGNORE_WRITEABLE)
348
349 EMIT_RANGES_FOR_GLOBALS_EXT
350
351 EMIT_RANGE_END
352}
353
354JVMFlagRange* JVMFlagRangeList::find(const char* name) {
355 JVMFlagRange* found = NULL;
356 for (int i=0; i<length(); i++) {
357 JVMFlagRange* range = at(i);
358 if (strcmp(range->name(), name) == 0) {
359 found = range;
360 break;
361 }
362 }
363 return found;
364}
365
366void JVMFlagRangeList::print(outputStream* st, const char* name, RangeStrFunc default_range_str_func) {
367 JVMFlagRange* range = JVMFlagRangeList::find(name);
368 if (range != NULL) {
369 range->print(st);
370 } else {
371 JVMFlagConstraint* constraint = JVMFlagConstraintList::find(name);
372 if (constraint != NULL) {
373 assert(default_range_str_func!=NULL, "default_range_str_func must be provided");
374 st->print("%s", default_range_str_func());
375 } else {
376 st->print("[ ... ]");
377 }
378 }
379}
380
381bool JVMFlagRangeList::check_ranges() {
382 bool status = true;
383 for (int i=0; i<length(); i++) {
384 JVMFlagRange* range = at(i);
385 if (range->check(true) != JVMFlag::SUCCESS) status = false;
386 }
387 return status;
388}
389