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 | |
40 | class JVMFlagRange_int : public JVMFlagRange { |
41 | int _min; |
42 | int _max; |
43 | const int* _ptr; |
44 | |
45 | public: |
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 | |
71 | class JVMFlagRange_intx : public JVMFlagRange { |
72 | intx _min; |
73 | intx _max; |
74 | const intx* _ptr; |
75 | public: |
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 | |
101 | class JVMFlagRange_uint : public JVMFlagRange { |
102 | uint _min; |
103 | uint _max; |
104 | const uint* _ptr; |
105 | |
106 | public: |
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 | |
132 | class JVMFlagRange_uintx : public JVMFlagRange { |
133 | uintx _min; |
134 | uintx _max; |
135 | const uintx* _ptr; |
136 | |
137 | public: |
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 | |
163 | class JVMFlagRange_uint64_t : public JVMFlagRange { |
164 | uint64_t _min; |
165 | uint64_t _max; |
166 | const uint64_t* _ptr; |
167 | |
168 | public: |
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 | |
194 | class JVMFlagRange_size_t : public JVMFlagRange { |
195 | size_t _min; |
196 | size_t _max; |
197 | const size_t* _ptr; |
198 | |
199 | public: |
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 | |
225 | class JVMFlagRange_double : public JVMFlagRange { |
226 | double _min; |
227 | double _max; |
228 | const double* _ptr; |
229 | |
230 | public: |
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 |
257 | void emit_range_no(...) { /* NOP */ } |
258 | |
259 | // No constraint emitting if function argument is NOT provided |
260 | void emit_range_bool(const char* /*name*/, const bool* /*value*/) { /* NOP */ } |
261 | void emit_range_ccstr(const char* /*name*/, const ccstr* /*value*/) { /* NOP */ } |
262 | void emit_range_ccstrlist(const char* /*name*/, const ccstrlist* /*value*/) { /* NOP */ } |
263 | void emit_range_int(const char* /*name*/, const int* /*value*/) { /* NOP */ } |
264 | void emit_range_intx(const char* /*name*/, const intx* /*value*/) { /* NOP */ } |
265 | void emit_range_uint(const char* /*name*/, const uint* /*value*/) { /* NOP */ } |
266 | void emit_range_uintx(const char* /*name*/, const uintx* /*value*/) { /* NOP */ } |
267 | void emit_range_uint64_t(const char* /*name*/, const uint64_t* /*value*/) { /* NOP */ } |
268 | void emit_range_size_t(const char* /*name*/, const size_t* /*value*/) { /* NOP */ } |
269 | void emit_range_double(const char* /*name*/, const double* /*value*/) { /* NOP */ } |
270 | |
271 | // JVMFlagRange emitting code functions if range arguments are provided |
272 | void emit_range_int(const char* name, const int* ptr, int min, int max) { |
273 | JVMFlagRangeList::add(new JVMFlagRange_int(name, ptr, min, max)); |
274 | } |
275 | void emit_range_intx(const char* name, const intx* ptr, intx min, intx max) { |
276 | JVMFlagRangeList::add(new JVMFlagRange_intx(name, ptr, min, max)); |
277 | } |
278 | void emit_range_uint(const char* name, const uint* ptr, uint min, uint max) { |
279 | JVMFlagRangeList::add(new JVMFlagRange_uint(name, ptr, min, max)); |
280 | } |
281 | void emit_range_uintx(const char* name, const uintx* ptr, uintx min, uintx max) { |
282 | JVMFlagRangeList::add(new JVMFlagRange_uintx(name, ptr, min, max)); |
283 | } |
284 | void 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 | } |
287 | void 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 | } |
290 | void 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 |
325 | GrowableArray<JVMFlagRange*>* JVMFlagRangeList::_ranges = NULL; |
326 | |
327 | // Check the ranges of all flags that have them |
328 | void 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 | |
354 | JVMFlagRange* 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 | |
366 | void 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 | |
381 | bool 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 | |