1 /*
2 * Copyright (c) 1997, 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 "jfr/jfrEvents.hpp"
27 #include "memory/allocation.inline.hpp"
28 #include "runtime/arguments.hpp"
29 #include "runtime/flags/jvmFlag.hpp"
30 #include "runtime/flags/jvmFlagConstraintList.hpp"
31 #include "runtime/flags/jvmFlagWriteableList.hpp"
32 #include "runtime/flags/jvmFlagRangeList.hpp"
33 #include "runtime/globals_extension.hpp"
34 #include "utilities/defaultStream.hpp"
35 #include "utilities/stringUtils.hpp"
36
37 #define DEFAULT_RANGE_STR_CHUNK_SIZE 64
create_range_str(const char * fmt,...)38 static char* create_range_str(const char *fmt, ...) {
39 static size_t string_length = DEFAULT_RANGE_STR_CHUNK_SIZE;
40 static char* range_string = NEW_C_HEAP_ARRAY(char, string_length, mtLogging);
41
42 int size_needed = 0;
43 do {
44 va_list args;
45 va_start(args, fmt);
46 size_needed = jio_vsnprintf(range_string, string_length, fmt, args);
47 va_end(args);
48
49 if (size_needed < 0) {
50 string_length += DEFAULT_RANGE_STR_CHUNK_SIZE;
51 range_string = REALLOC_C_HEAP_ARRAY(char, range_string, string_length, mtLogging);
52 guarantee(range_string != NULL, "create_range_str string should not be NULL");
53 }
54 } while (size_needed < 0);
55
56 return range_string;
57 }
58
get_int_default_range_str()59 const char* JVMFlag::get_int_default_range_str() {
60 return create_range_str("[ " INT32_FORMAT_W(-25) " ... " INT32_FORMAT_W(25) " ]", INT_MIN, INT_MAX);
61 }
62
get_uint_default_range_str()63 const char* JVMFlag::get_uint_default_range_str() {
64 return create_range_str("[ " UINT32_FORMAT_W(-25) " ... " UINT32_FORMAT_W(25) " ]", 0, UINT_MAX);
65 }
66
get_intx_default_range_str()67 const char* JVMFlag::get_intx_default_range_str() {
68 return create_range_str("[ " INTX_FORMAT_W(-25) " ... " INTX_FORMAT_W(25) " ]", min_intx, max_intx);
69 }
70
get_uintx_default_range_str()71 const char* JVMFlag::get_uintx_default_range_str() {
72 return create_range_str("[ " UINTX_FORMAT_W(-25) " ... " UINTX_FORMAT_W(25) " ]", 0, max_uintx);
73 }
74
get_uint64_t_default_range_str()75 const char* JVMFlag::get_uint64_t_default_range_str() {
76 return create_range_str("[ " UINT64_FORMAT_W(-25) " ... " UINT64_FORMAT_W(25) " ]", 0, uint64_t(max_juint));
77 }
78
get_size_t_default_range_str()79 const char* JVMFlag::get_size_t_default_range_str() {
80 return create_range_str("[ " SIZE_FORMAT_W(-25) " ... " SIZE_FORMAT_W(25) " ]", 0, SIZE_MAX);
81 }
82
get_double_default_range_str()83 const char* JVMFlag::get_double_default_range_str() {
84 return create_range_str("[ %-25.3f ... %25.3f ]", DBL_MIN, DBL_MAX);
85 }
86
is_product_build()87 static bool is_product_build() {
88 #ifdef PRODUCT
89 return true;
90 #else
91 return false;
92 #endif
93 }
94
check_writable(bool changed)95 JVMFlag::Error JVMFlag::check_writable(bool changed) {
96 if (is_constant_in_binary()) {
97 fatal("flag is constant: %s", _name);
98 }
99
100 JVMFlag::Error error = JVMFlag::SUCCESS;
101 if (changed) {
102 JVMFlagWriteable* writeable = JVMFlagWriteableList::find(_name);
103 if (writeable) {
104 if (writeable->is_writeable() == false) {
105 switch (writeable->type())
106 {
107 case JVMFlagWriteable::Once:
108 error = JVMFlag::SET_ONLY_ONCE;
109 jio_fprintf(defaultStream::error_stream(), "Error: %s may not be set more than once\n", _name);
110 break;
111 case JVMFlagWriteable::CommandLineOnly:
112 error = JVMFlag::COMMAND_LINE_ONLY;
113 jio_fprintf(defaultStream::error_stream(), "Error: %s may be modified only from commad line\n", _name);
114 break;
115 default:
116 ShouldNotReachHere();
117 break;
118 }
119 }
120 writeable->mark_once();
121 }
122 }
123 return error;
124 }
125
is_bool() const126 bool JVMFlag::is_bool() const {
127 return strcmp(_type, "bool") == 0;
128 }
129
get_bool() const130 bool JVMFlag::get_bool() const {
131 return *((bool*) _addr);
132 }
133
set_bool(bool value)134 JVMFlag::Error JVMFlag::set_bool(bool value) {
135 JVMFlag::Error error = check_writable(value!=get_bool());
136 if (error == JVMFlag::SUCCESS) {
137 *((bool*) _addr) = value;
138 }
139 return error;
140 }
141
is_int() const142 bool JVMFlag::is_int() const {
143 return strcmp(_type, "int") == 0;
144 }
145
get_int() const146 int JVMFlag::get_int() const {
147 return *((int*) _addr);
148 }
149
set_int(int value)150 JVMFlag::Error JVMFlag::set_int(int value) {
151 JVMFlag::Error error = check_writable(value!=get_int());
152 if (error == JVMFlag::SUCCESS) {
153 *((int*) _addr) = value;
154 }
155 return error;
156 }
157
is_uint() const158 bool JVMFlag::is_uint() const {
159 return strcmp(_type, "uint") == 0;
160 }
161
get_uint() const162 uint JVMFlag::get_uint() const {
163 return *((uint*) _addr);
164 }
165
set_uint(uint value)166 JVMFlag::Error JVMFlag::set_uint(uint value) {
167 JVMFlag::Error error = check_writable(value!=get_uint());
168 if (error == JVMFlag::SUCCESS) {
169 *((uint*) _addr) = value;
170 }
171 return error;
172 }
173
is_intx() const174 bool JVMFlag::is_intx() const {
175 return strcmp(_type, "intx") == 0;
176 }
177
get_intx() const178 intx JVMFlag::get_intx() const {
179 return *((intx*) _addr);
180 }
181
set_intx(intx value)182 JVMFlag::Error JVMFlag::set_intx(intx value) {
183 JVMFlag::Error error = check_writable(value!=get_intx());
184 if (error == JVMFlag::SUCCESS) {
185 *((intx*) _addr) = value;
186 }
187 return error;
188 }
189
is_uintx() const190 bool JVMFlag::is_uintx() const {
191 return strcmp(_type, "uintx") == 0;
192 }
193
get_uintx() const194 uintx JVMFlag::get_uintx() const {
195 return *((uintx*) _addr);
196 }
197
set_uintx(uintx value)198 JVMFlag::Error JVMFlag::set_uintx(uintx value) {
199 JVMFlag::Error error = check_writable(value!=get_uintx());
200 if (error == JVMFlag::SUCCESS) {
201 *((uintx*) _addr) = value;
202 }
203 return error;
204 }
205
is_uint64_t() const206 bool JVMFlag::is_uint64_t() const {
207 return strcmp(_type, "uint64_t") == 0;
208 }
209
get_uint64_t() const210 uint64_t JVMFlag::get_uint64_t() const {
211 return *((uint64_t*) _addr);
212 }
213
set_uint64_t(uint64_t value)214 JVMFlag::Error JVMFlag::set_uint64_t(uint64_t value) {
215 JVMFlag::Error error = check_writable(value!=get_uint64_t());
216 if (error == JVMFlag::SUCCESS) {
217 *((uint64_t*) _addr) = value;
218 }
219 return error;
220 }
221
is_size_t() const222 bool JVMFlag::is_size_t() const {
223 return strcmp(_type, "size_t") == 0;
224 }
225
get_size_t() const226 size_t JVMFlag::get_size_t() const {
227 return *((size_t*) _addr);
228 }
229
set_size_t(size_t value)230 JVMFlag::Error JVMFlag::set_size_t(size_t value) {
231 JVMFlag::Error error = check_writable(value!=get_size_t());
232 if (error == JVMFlag::SUCCESS) {
233 *((size_t*) _addr) = value;
234 }
235 return error;
236 }
237
is_double() const238 bool JVMFlag::is_double() const {
239 return strcmp(_type, "double") == 0;
240 }
241
get_double() const242 double JVMFlag::get_double() const {
243 return *((double*) _addr);
244 }
245
set_double(double value)246 JVMFlag::Error JVMFlag::set_double(double value) {
247 JVMFlag::Error error = check_writable(value!=get_double());
248 if (error == JVMFlag::SUCCESS) {
249 *((double*) _addr) = value;
250 }
251 return error;
252 }
253
is_ccstr() const254 bool JVMFlag::is_ccstr() const {
255 return strcmp(_type, "ccstr") == 0 || strcmp(_type, "ccstrlist") == 0;
256 }
257
ccstr_accumulates() const258 bool JVMFlag::ccstr_accumulates() const {
259 return strcmp(_type, "ccstrlist") == 0;
260 }
261
get_ccstr() const262 ccstr JVMFlag::get_ccstr() const {
263 return *((ccstr*) _addr);
264 }
265
set_ccstr(ccstr value)266 JVMFlag::Error JVMFlag::set_ccstr(ccstr value) {
267 JVMFlag::Error error = check_writable(value!=get_ccstr());
268 if (error == JVMFlag::SUCCESS) {
269 *((ccstr*) _addr) = value;
270 }
271 return error;
272 }
273
274
get_origin()275 JVMFlag::Flags JVMFlag::get_origin() {
276 return Flags(_flags & VALUE_ORIGIN_MASK);
277 }
278
set_origin(Flags origin)279 void JVMFlag::set_origin(Flags origin) {
280 assert((origin & VALUE_ORIGIN_MASK) == origin, "sanity");
281 Flags new_origin = Flags((origin == COMMAND_LINE) ? Flags(origin | ORIG_COMMAND_LINE) : origin);
282 _flags = Flags((_flags & ~VALUE_ORIGIN_MASK) | new_origin);
283 }
284
is_default()285 bool JVMFlag::is_default() {
286 return (get_origin() == DEFAULT);
287 }
288
is_ergonomic()289 bool JVMFlag::is_ergonomic() {
290 return (get_origin() == ERGONOMIC);
291 }
292
is_command_line()293 bool JVMFlag::is_command_line() {
294 return (_flags & ORIG_COMMAND_LINE) != 0;
295 }
296
is_jimage_resource()297 bool JVMFlag::is_jimage_resource() {
298 return (get_origin() == JIMAGE_RESOURCE);
299 }
300
set_command_line()301 void JVMFlag::set_command_line() {
302 _flags = Flags(_flags | ORIG_COMMAND_LINE);
303 }
304
is_product() const305 bool JVMFlag::is_product() const {
306 return (_flags & KIND_PRODUCT) != 0;
307 }
308
is_manageable() const309 bool JVMFlag::is_manageable() const {
310 return (_flags & KIND_MANAGEABLE) != 0;
311 }
312
is_diagnostic() const313 bool JVMFlag::is_diagnostic() const {
314 return (_flags & KIND_DIAGNOSTIC) != 0;
315 }
316
is_experimental() const317 bool JVMFlag::is_experimental() const {
318 return (_flags & KIND_EXPERIMENTAL) != 0;
319 }
320
is_notproduct() const321 bool JVMFlag::is_notproduct() const {
322 return (_flags & KIND_NOT_PRODUCT) != 0;
323 }
324
is_develop() const325 bool JVMFlag::is_develop() const {
326 return (_flags & KIND_DEVELOP) != 0;
327 }
328
is_read_write() const329 bool JVMFlag::is_read_write() const {
330 return (_flags & KIND_READ_WRITE) != 0;
331 }
332
333 /**
334 * Returns if this flag is a constant in the binary. Right now this is
335 * true for notproduct and develop flags in product builds.
336 */
is_constant_in_binary() const337 bool JVMFlag::is_constant_in_binary() const {
338 #ifdef PRODUCT
339 return is_notproduct() || is_develop();
340 #else
341 return false;
342 #endif
343 }
344
is_unlocker() const345 bool JVMFlag::is_unlocker() const {
346 return strcmp(_name, "UnlockDiagnosticVMOptions") == 0 ||
347 strcmp(_name, "UnlockExperimentalVMOptions") == 0 ||
348 is_unlocker_ext();
349 }
350
is_unlocked() const351 bool JVMFlag::is_unlocked() const {
352 if (is_diagnostic()) {
353 return UnlockDiagnosticVMOptions;
354 }
355 if (is_experimental()) {
356 return UnlockExperimentalVMOptions;
357 }
358 return is_unlocked_ext();
359 }
360
clear_diagnostic()361 void JVMFlag::clear_diagnostic() {
362 assert(is_diagnostic(), "sanity");
363 _flags = Flags(_flags & ~KIND_DIAGNOSTIC);
364 assert(!is_diagnostic(), "sanity");
365 }
366
367 // Get custom message for this locked flag, or NULL if
368 // none is available. Returns message type produced.
get_locked_message(char * buf,int buflen) const369 JVMFlag::MsgType JVMFlag::get_locked_message(char* buf, int buflen) const {
370 buf[0] = '\0';
371 if (is_diagnostic() && !is_unlocked()) {
372 jio_snprintf(buf, buflen,
373 "Error: VM option '%s' is diagnostic and must be enabled via -XX:+UnlockDiagnosticVMOptions.\n"
374 "Error: The unlock option must precede '%s'.\n",
375 _name, _name);
376 return JVMFlag::DIAGNOSTIC_FLAG_BUT_LOCKED;
377 }
378 if (is_experimental() && !is_unlocked()) {
379 jio_snprintf(buf, buflen,
380 "Error: VM option '%s' is experimental and must be enabled via -XX:+UnlockExperimentalVMOptions.\n"
381 "Error: The unlock option must precede '%s'.\n",
382 _name, _name);
383 return JVMFlag::EXPERIMENTAL_FLAG_BUT_LOCKED;
384 }
385 if (is_develop() && is_product_build()) {
386 jio_snprintf(buf, buflen, "Error: VM option '%s' is develop and is available only in debug version of VM.\n",
387 _name);
388 return JVMFlag::DEVELOPER_FLAG_BUT_PRODUCT_BUILD;
389 }
390 if (is_notproduct() && is_product_build()) {
391 jio_snprintf(buf, buflen, "Error: VM option '%s' is notproduct and is available only in debug version of VM.\n",
392 _name);
393 return JVMFlag::NOTPRODUCT_FLAG_BUT_PRODUCT_BUILD;
394 }
395 return get_locked_message_ext(buf, buflen);
396 }
397
is_writeable() const398 bool JVMFlag::is_writeable() const {
399 return is_manageable() || (is_product() && is_read_write()) || is_writeable_ext();
400 }
401
402 // All flags except "manageable" are assumed to be internal flags.
403 // Long term, we need to define a mechanism to specify which flags
404 // are external/stable and change this function accordingly.
is_external() const405 bool JVMFlag::is_external() const {
406 return is_manageable() || is_external_ext();
407 }
408
409 // Helper function for JVMFlag::print_on().
410 // Fills current line up to requested position.
411 // Should the current position already be past the requested position,
412 // one separator blank is enforced.
fill_to_pos(outputStream * st,unsigned int req_pos)413 void fill_to_pos(outputStream* st, unsigned int req_pos) {
414 if ((unsigned int)st->position() < req_pos) {
415 st->fill_to(req_pos); // need to fill with blanks to reach req_pos
416 } else {
417 st->print(" "); // enforce blank separation. Previous field too long.
418 }
419 }
420
print_on(outputStream * st,bool withComments,bool printRanges)421 void JVMFlag::print_on(outputStream* st, bool withComments, bool printRanges) {
422 // Don't print notproduct and develop flags in a product build.
423 if (is_constant_in_binary()) {
424 return;
425 }
426
427 if (!printRanges) {
428 // The command line options -XX:+PrintFlags* cause this function to be called
429 // for each existing flag to print information pertinent to this flag. The data
430 // is displayed in columnar form, with the following layout:
431 // col1 - data type, right-justified
432 // col2 - name, left-justified
433 // col3 - ' =' double-char, leading space to align with possible '+='
434 // col4 - value left-justified
435 // col5 - kind right-justified
436 // col6 - origin left-justified
437 // col7 - comments left-justified
438 //
439 // The column widths are fixed. They are defined such that, for most cases,
440 // an eye-pleasing tabular output is created.
441 //
442 // Sample output:
443 // bool CMSScavengeBeforeRemark = false {product} {default}
444 // uintx CMSScheduleRemarkEdenPenetration = 50 {product} {default}
445 // size_t CMSScheduleRemarkEdenSizeThreshold = 2097152 {product} {default}
446 // uintx CMSScheduleRemarkSamplingRatio = 5 {product} {default}
447 // double CMSSmallCoalSurplusPercent = 1.050000 {product} {default}
448 // ccstr CompileCommandFile = MyFile.cmd {product} {command line}
449 // ccstrlist CompileOnly = Method1
450 // CompileOnly += Method2 {product} {command line}
451 // | | | | | | |
452 // | | | | | | +-- col7
453 // | | | | | +-- col6
454 // | | | | +-- col5
455 // | | | +-- col4
456 // | | +-- col3
457 // | +-- col2
458 // +-- col1
459
460 const unsigned int col_spacing = 1;
461 const unsigned int col1_pos = 0;
462 const unsigned int col1_width = 9;
463 const unsigned int col2_pos = col1_pos + col1_width + col_spacing;
464 const unsigned int col2_width = 39;
465 const unsigned int col3_pos = col2_pos + col2_width + col_spacing;
466 const unsigned int col3_width = 2;
467 const unsigned int col4_pos = col3_pos + col3_width + col_spacing;
468 const unsigned int col4_width = 30;
469 const unsigned int col5_pos = col4_pos + col4_width + col_spacing;
470 const unsigned int col5_width = 20;
471 const unsigned int col6_pos = col5_pos + col5_width + col_spacing;
472 const unsigned int col6_width = 15;
473 const unsigned int col7_pos = col6_pos + col6_width + col_spacing;
474 const unsigned int col7_width = 1;
475
476 st->fill_to(col1_pos);
477 st->print("%*s", col1_width, _type); // right-justified, therefore width is required.
478
479 fill_to_pos(st, col2_pos);
480 st->print("%s", _name);
481
482 fill_to_pos(st, col3_pos);
483 st->print(" ="); // use " =" for proper alignment with multiline ccstr output.
484
485 fill_to_pos(st, col4_pos);
486 if (is_bool()) {
487 st->print("%s", get_bool() ? "true" : "false");
488 } else if (is_int()) {
489 st->print("%d", get_int());
490 } else if (is_uint()) {
491 st->print("%u", get_uint());
492 } else if (is_intx()) {
493 st->print(INTX_FORMAT, get_intx());
494 } else if (is_uintx()) {
495 st->print(UINTX_FORMAT, get_uintx());
496 } else if (is_uint64_t()) {
497 st->print(UINT64_FORMAT, get_uint64_t());
498 } else if (is_size_t()) {
499 st->print(SIZE_FORMAT, get_size_t());
500 } else if (is_double()) {
501 st->print("%f", get_double());
502 } else if (is_ccstr()) {
503 // Honor <newline> characters in ccstr: print multiple lines.
504 const char* cp = get_ccstr();
505 if (cp != NULL) {
506 const char* eol;
507 while ((eol = strchr(cp, '\n')) != NULL) {
508 size_t llen = pointer_delta(eol, cp, sizeof(char));
509 st->print("%.*s", (int)llen, cp);
510 st->cr();
511 cp = eol+1;
512 fill_to_pos(st, col2_pos);
513 st->print("%s", _name);
514 fill_to_pos(st, col3_pos);
515 st->print("+=");
516 fill_to_pos(st, col4_pos);
517 }
518 st->print("%s", cp);
519 }
520 } else {
521 st->print("unhandled type %s", _type);
522 st->cr();
523 return;
524 }
525
526 fill_to_pos(st, col5_pos);
527 print_kind(st, col5_width);
528
529 fill_to_pos(st, col6_pos);
530 print_origin(st, col6_width);
531
532 #ifndef PRODUCT
533 if (withComments) {
534 fill_to_pos(st, col7_pos);
535 st->print("%s", _doc);
536 }
537 #endif
538 st->cr();
539 } else if (!is_bool() && !is_ccstr()) {
540 // The command line options -XX:+PrintFlags* cause this function to be called
541 // for each existing flag to print information pertinent to this flag. The data
542 // is displayed in columnar form, with the following layout:
543 // col1 - data type, right-justified
544 // col2 - name, left-justified
545 // col4 - range [ min ... max]
546 // col5 - kind right-justified
547 // col6 - origin left-justified
548 // col7 - comments left-justified
549 //
550 // The column widths are fixed. They are defined such that, for most cases,
551 // an eye-pleasing tabular output is created.
552 //
553 // Sample output:
554 // intx MinPassesBeforeFlush [ 0 ... 9223372036854775807 ] {diagnostic} {default}
555 // uintx MinRAMFraction [ 1 ... 18446744073709551615 ] {product} {default}
556 // double MinRAMPercentage [ 0.000 ... 100.000 ] {product} {default}
557 // uintx MinSurvivorRatio [ 3 ... 18446744073709551615 ] {product} {default}
558 // size_t MinTLABSize [ 1 ... 9223372036854775807 ] {product} {default}
559 // intx MonitorBound [ 0 ... 2147483647 ] {product} {default}
560 // | | | | | |
561 // | | | | | +-- col7
562 // | | | | +-- col6
563 // | | | +-- col5
564 // | | +-- col4
565 // | +-- col2
566 // +-- col1
567
568 const unsigned int col_spacing = 1;
569 const unsigned int col1_pos = 0;
570 const unsigned int col1_width = 9;
571 const unsigned int col2_pos = col1_pos + col1_width + col_spacing;
572 const unsigned int col2_width = 49;
573 const unsigned int col3_pos = col2_pos + col2_width + col_spacing;
574 const unsigned int col3_width = 0;
575 const unsigned int col4_pos = col3_pos + col3_width + col_spacing;
576 const unsigned int col4_width = 60;
577 const unsigned int col5_pos = col4_pos + col4_width + col_spacing;
578 const unsigned int col5_width = 35;
579 const unsigned int col6_pos = col5_pos + col5_width + col_spacing;
580 const unsigned int col6_width = 15;
581 const unsigned int col7_pos = col6_pos + col6_width + col_spacing;
582 const unsigned int col7_width = 1;
583
584 st->fill_to(col1_pos);
585 st->print("%*s", col1_width, _type); // right-justified, therefore width is required.
586
587 fill_to_pos(st, col2_pos);
588 st->print("%s", _name);
589
590 fill_to_pos(st, col4_pos);
591 RangeStrFunc func = NULL;
592 if (is_int()) {
593 func = JVMFlag::get_int_default_range_str;
594 } else if (is_uint()) {
595 func = JVMFlag::get_uint_default_range_str;
596 } else if (is_intx()) {
597 func = JVMFlag::get_intx_default_range_str;
598 } else if (is_uintx()) {
599 func = JVMFlag::get_uintx_default_range_str;
600 } else if (is_uint64_t()) {
601 func = JVMFlag::get_uint64_t_default_range_str;
602 } else if (is_size_t()) {
603 func = JVMFlag::get_size_t_default_range_str;
604 } else if (is_double()) {
605 func = JVMFlag::get_double_default_range_str;
606 } else {
607 st->print("unhandled type %s", _type);
608 st->cr();
609 return;
610 }
611 JVMFlagRangeList::print(st, _name, func);
612
613 fill_to_pos(st, col5_pos);
614 print_kind(st, col5_width);
615
616 fill_to_pos(st, col6_pos);
617 print_origin(st, col6_width);
618
619 #ifndef PRODUCT
620 if (withComments) {
621 fill_to_pos(st, col7_pos);
622 st->print("%s", _doc);
623 }
624 #endif
625 st->cr();
626 }
627 }
628
print_kind(outputStream * st,unsigned int width)629 void JVMFlag::print_kind(outputStream* st, unsigned int width) {
630 struct Data {
631 int flag;
632 const char* name;
633 };
634
635 Data data[] = {
636 { KIND_JVMCI, "JVMCI" },
637 { KIND_C1, "C1" },
638 { KIND_C2, "C2" },
639 { KIND_ARCH, "ARCH" },
640 { KIND_PLATFORM_DEPENDENT, "pd" },
641 { KIND_PRODUCT, "product" },
642 { KIND_MANAGEABLE, "manageable" },
643 { KIND_DIAGNOSTIC, "diagnostic" },
644 { KIND_EXPERIMENTAL, "experimental" },
645 { KIND_NOT_PRODUCT, "notproduct" },
646 { KIND_DEVELOP, "develop" },
647 { KIND_LP64_PRODUCT, "lp64_product" },
648 { KIND_READ_WRITE, "rw" },
649 { -1, "" }
650 };
651
652 if ((_flags & KIND_MASK) != 0) {
653 bool is_first = true;
654 const size_t buffer_size = 64;
655 size_t buffer_used = 0;
656 char kind[buffer_size];
657
658 jio_snprintf(kind, buffer_size, "{");
659 buffer_used++;
660 for (int i = 0; data[i].flag != -1; i++) {
661 Data d = data[i];
662 if ((_flags & d.flag) != 0) {
663 if (is_first) {
664 is_first = false;
665 } else {
666 assert(buffer_used + 1 < buffer_size, "Too small buffer");
667 jio_snprintf(kind + buffer_used, buffer_size - buffer_used, " ");
668 buffer_used++;
669 }
670 size_t length = strlen(d.name);
671 assert(buffer_used + length < buffer_size, "Too small buffer");
672 jio_snprintf(kind + buffer_used, buffer_size - buffer_used, "%s", d.name);
673 buffer_used += length;
674 }
675 }
676 assert(buffer_used + 2 <= buffer_size, "Too small buffer");
677 jio_snprintf(kind + buffer_used, buffer_size - buffer_used, "}");
678 st->print("%*s", width, kind);
679 }
680 }
681
print_origin(outputStream * st,unsigned int width)682 void JVMFlag::print_origin(outputStream* st, unsigned int width) {
683 int origin = _flags & VALUE_ORIGIN_MASK;
684 st->print("{");
685 switch(origin) {
686 case DEFAULT:
687 st->print("default"); break;
688 case COMMAND_LINE:
689 st->print("command line"); break;
690 case ENVIRON_VAR:
691 st->print("environment"); break;
692 case CONFIG_FILE:
693 st->print("config file"); break;
694 case MANAGEMENT:
695 st->print("management"); break;
696 case ERGONOMIC:
697 if (_flags & ORIG_COMMAND_LINE) {
698 st->print("command line, ");
699 }
700 st->print("ergonomic"); break;
701 case ATTACH_ON_DEMAND:
702 st->print("attach"); break;
703 case INTERNAL:
704 st->print("internal"); break;
705 case JIMAGE_RESOURCE:
706 st->print("jimage"); break;
707 }
708 st->print("}");
709 }
710
print_as_flag(outputStream * st)711 void JVMFlag::print_as_flag(outputStream* st) {
712 if (is_bool()) {
713 st->print("-XX:%s%s", get_bool() ? "+" : "-", _name);
714 } else if (is_int()) {
715 st->print("-XX:%s=%d", _name, get_int());
716 } else if (is_uint()) {
717 st->print("-XX:%s=%u", _name, get_uint());
718 } else if (is_intx()) {
719 st->print("-XX:%s=" INTX_FORMAT, _name, get_intx());
720 } else if (is_uintx()) {
721 st->print("-XX:%s=" UINTX_FORMAT, _name, get_uintx());
722 } else if (is_uint64_t()) {
723 st->print("-XX:%s=" UINT64_FORMAT, _name, get_uint64_t());
724 } else if (is_size_t()) {
725 st->print("-XX:%s=" SIZE_FORMAT, _name, get_size_t());
726 } else if (is_double()) {
727 st->print("-XX:%s=%f", _name, get_double());
728 } else if (is_ccstr()) {
729 st->print("-XX:%s=", _name);
730 const char* cp = get_ccstr();
731 if (cp != NULL) {
732 // Need to turn embedded '\n's back into separate arguments
733 // Not so efficient to print one character at a time,
734 // but the choice is to do the transformation to a buffer
735 // and print that. And this need not be efficient.
736 for (; *cp != '\0'; cp += 1) {
737 switch (*cp) {
738 default:
739 st->print("%c", *cp);
740 break;
741 case '\n':
742 st->print(" -XX:%s=", _name);
743 break;
744 }
745 }
746 }
747 } else {
748 ShouldNotReachHere();
749 }
750 }
751
flag_error_str(JVMFlag::Error error)752 const char* JVMFlag::flag_error_str(JVMFlag::Error error) {
753 switch (error) {
754 case JVMFlag::MISSING_NAME: return "MISSING_NAME";
755 case JVMFlag::MISSING_VALUE: return "MISSING_VALUE";
756 case JVMFlag::NON_WRITABLE: return "NON_WRITABLE";
757 case JVMFlag::OUT_OF_BOUNDS: return "OUT_OF_BOUNDS";
758 case JVMFlag::VIOLATES_CONSTRAINT: return "VIOLATES_CONSTRAINT";
759 case JVMFlag::INVALID_FLAG: return "INVALID_FLAG";
760 case JVMFlag::ERR_OTHER: return "ERR_OTHER";
761 case JVMFlag::SUCCESS: return "SUCCESS";
762 default: ShouldNotReachHere(); return "NULL";
763 }
764 }
765
766 // 4991491 do not "optimize out" the was_set false values: omitting them
767 // tickles a Microsoft compiler bug causing flagTable to be malformed
768
769 #define RUNTIME_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_PRODUCT) },
770 #define RUNTIME_PD_PRODUCT_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_PRODUCT | JVMFlag::KIND_PLATFORM_DEPENDENT) },
771 #define RUNTIME_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_DIAGNOSTIC) },
772 #define RUNTIME_PD_DIAGNOSTIC_FLAG_STRUCT(type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_DIAGNOSTIC | JVMFlag::KIND_PLATFORM_DEPENDENT) },
773 #define RUNTIME_EXPERIMENTAL_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_EXPERIMENTAL) },
774 #define RUNTIME_MANAGEABLE_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_MANAGEABLE) },
775 #define RUNTIME_PRODUCT_RW_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_PRODUCT | JVMFlag::KIND_READ_WRITE) },
776 #define RUNTIME_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_DEVELOP) },
777 #define RUNTIME_PD_DEVELOP_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_DEVELOP | JVMFlag::KIND_PLATFORM_DEPENDENT) },
778 #define RUNTIME_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_NOT_PRODUCT) },
779
780 #define JVMCI_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_PRODUCT) },
781 #define JVMCI_PD_PRODUCT_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_PRODUCT | JVMFlag::KIND_PLATFORM_DEPENDENT) },
782 #define JVMCI_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_DIAGNOSTIC) },
783 #define JVMCI_PD_DIAGNOSTIC_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_DIAGNOSTIC | JVMFlag::KIND_PLATFORM_DEPENDENT) },
784 #define JVMCI_EXPERIMENTAL_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_EXPERIMENTAL) },
785 #define JVMCI_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_DEVELOP) },
786 #define JVMCI_PD_DEVELOP_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_DEVELOP | JVMFlag::KIND_PLATFORM_DEPENDENT) },
787 #define JVMCI_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_NOT_PRODUCT) },
788
789 #ifdef _LP64
790 #define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_LP64_PRODUCT) },
791 #else
792 #define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) /* flag is constant */
793 #endif // _LP64
794
795 #define C1_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_PRODUCT) },
796 #define C1_PD_PRODUCT_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_PRODUCT | JVMFlag::KIND_PLATFORM_DEPENDENT) },
797 #define C1_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_DIAGNOSTIC) },
798 #define C1_PD_DIAGNOSTIC_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_DIAGNOSTIC | JVMFlag::KIND_PLATFORM_DEPENDENT) },
799 #define C1_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_DEVELOP) },
800 #define C1_PD_DEVELOP_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_DEVELOP | JVMFlag::KIND_PLATFORM_DEPENDENT) },
801 #define C1_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_NOT_PRODUCT) },
802
803 #define C2_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_PRODUCT) },
804 #define C2_PD_PRODUCT_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_PRODUCT | JVMFlag::KIND_PLATFORM_DEPENDENT) },
805 #define C2_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_DIAGNOSTIC) },
806 #define C2_PD_DIAGNOSTIC_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_DIAGNOSTIC | JVMFlag::KIND_PLATFORM_DEPENDENT) },
807 #define C2_EXPERIMENTAL_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_EXPERIMENTAL) },
808 #define C2_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_DEVELOP) },
809 #define C2_PD_DEVELOP_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_DEVELOP | JVMFlag::KIND_PLATFORM_DEPENDENT) },
810 #define C2_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_NOT_PRODUCT) },
811
812 #define ARCH_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_ARCH | JVMFlag::KIND_PRODUCT) },
813 #define ARCH_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_ARCH | JVMFlag::KIND_DIAGNOSTIC) },
814 #define ARCH_EXPERIMENTAL_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_ARCH | JVMFlag::KIND_EXPERIMENTAL) },
815 #define ARCH_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_ARCH | JVMFlag::KIND_DEVELOP) },
816 #define ARCH_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_ARCH | JVMFlag::KIND_NOT_PRODUCT) },
817
818 static JVMFlag flagTable[] = {
819 VM_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, \
820 RUNTIME_PD_DEVELOP_FLAG_STRUCT, \
821 RUNTIME_PRODUCT_FLAG_STRUCT, \
822 RUNTIME_PD_PRODUCT_FLAG_STRUCT, \
823 RUNTIME_DIAGNOSTIC_FLAG_STRUCT, \
824 RUNTIME_PD_DIAGNOSTIC_FLAG_STRUCT, \
825 RUNTIME_EXPERIMENTAL_FLAG_STRUCT, \
826 RUNTIME_NOTPRODUCT_FLAG_STRUCT, \
827 RUNTIME_MANAGEABLE_FLAG_STRUCT, \
828 RUNTIME_PRODUCT_RW_FLAG_STRUCT, \
829 RUNTIME_LP64_PRODUCT_FLAG_STRUCT, \
830 IGNORE_RANGE, \
831 IGNORE_CONSTRAINT, \
832 IGNORE_WRITEABLE)
833
834 RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, \
835 RUNTIME_PD_DEVELOP_FLAG_STRUCT, \
836 RUNTIME_PRODUCT_FLAG_STRUCT, \
837 RUNTIME_PD_PRODUCT_FLAG_STRUCT, \
838 RUNTIME_DIAGNOSTIC_FLAG_STRUCT, \
839 RUNTIME_PD_DIAGNOSTIC_FLAG_STRUCT, \
840 RUNTIME_NOTPRODUCT_FLAG_STRUCT, \
841 IGNORE_RANGE, \
842 IGNORE_CONSTRAINT, \
843 IGNORE_WRITEABLE)
844 #if INCLUDE_JVMCI
845 JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_STRUCT, \
846 JVMCI_PD_DEVELOP_FLAG_STRUCT, \
847 JVMCI_PRODUCT_FLAG_STRUCT, \
848 JVMCI_PD_PRODUCT_FLAG_STRUCT, \
849 JVMCI_DIAGNOSTIC_FLAG_STRUCT, \
850 JVMCI_PD_DIAGNOSTIC_FLAG_STRUCT, \
851 JVMCI_EXPERIMENTAL_FLAG_STRUCT, \
852 JVMCI_NOTPRODUCT_FLAG_STRUCT, \
853 IGNORE_RANGE, \
854 IGNORE_CONSTRAINT, \
855 IGNORE_WRITEABLE)
856 #endif // INCLUDE_JVMCI
857 #ifdef COMPILER1
858 C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, \
859 C1_PD_DEVELOP_FLAG_STRUCT, \
860 C1_PRODUCT_FLAG_STRUCT, \
861 C1_PD_PRODUCT_FLAG_STRUCT, \
862 C1_DIAGNOSTIC_FLAG_STRUCT, \
863 C1_PD_DIAGNOSTIC_FLAG_STRUCT, \
864 C1_NOTPRODUCT_FLAG_STRUCT, \
865 IGNORE_RANGE, \
866 IGNORE_CONSTRAINT, \
867 IGNORE_WRITEABLE)
868 #endif // COMPILER1
869 #ifdef COMPILER2
870 C2_FLAGS(C2_DEVELOP_FLAG_STRUCT, \
871 C2_PD_DEVELOP_FLAG_STRUCT, \
872 C2_PRODUCT_FLAG_STRUCT, \
873 C2_PD_PRODUCT_FLAG_STRUCT, \
874 C2_DIAGNOSTIC_FLAG_STRUCT, \
875 C2_PD_DIAGNOSTIC_FLAG_STRUCT, \
876 C2_EXPERIMENTAL_FLAG_STRUCT, \
877 C2_NOTPRODUCT_FLAG_STRUCT, \
878 IGNORE_RANGE, \
879 IGNORE_CONSTRAINT, \
880 IGNORE_WRITEABLE)
881 #endif // COMPILER2
882 ARCH_FLAGS(ARCH_DEVELOP_FLAG_STRUCT, \
883 ARCH_PRODUCT_FLAG_STRUCT, \
884 ARCH_DIAGNOSTIC_FLAG_STRUCT, \
885 ARCH_EXPERIMENTAL_FLAG_STRUCT, \
886 ARCH_NOTPRODUCT_FLAG_STRUCT, \
887 IGNORE_RANGE, \
888 IGNORE_CONSTRAINT, \
889 IGNORE_WRITEABLE)
890 FLAGTABLE_EXT
891 {0, NULL, NULL}
892 };
893
894 JVMFlag* JVMFlag::flags = flagTable;
895 size_t JVMFlag::numFlags = (sizeof(flagTable) / sizeof(JVMFlag));
896
str_equal(const char * s,size_t s_len,const char * q,size_t q_len)897 inline bool str_equal(const char* s, size_t s_len, const char* q, size_t q_len) {
898 if (s_len != q_len) return false;
899 return memcmp(s, q, q_len) == 0;
900 }
901
902 // Search the flag table for a named flag
find_flag(const char * name,size_t length,bool allow_locked,bool return_flag)903 JVMFlag* JVMFlag::find_flag(const char* name, size_t length, bool allow_locked, bool return_flag) {
904 for (JVMFlag* current = &flagTable[0]; current->_name != NULL; current++) {
905 if (str_equal(current->_name, current->get_name_length(), name, length)) {
906 // Found a matching entry.
907 // Don't report notproduct and develop flags in product builds.
908 if (current->is_constant_in_binary()) {
909 return (return_flag ? current : NULL);
910 }
911 // Report locked flags only if allowed.
912 if (!(current->is_unlocked() || current->is_unlocker())) {
913 if (!allow_locked) {
914 // disable use of locked flags, e.g. diagnostic, experimental,
915 // etc. until they are explicitly unlocked
916 return NULL;
917 }
918 }
919 return current;
920 }
921 }
922 // JVMFlag name is not in the flag table
923 return NULL;
924 }
925
926 // Get or compute the flag name length
get_name_length()927 size_t JVMFlag::get_name_length() {
928 if (_name_len == 0) {
929 _name_len = strlen(_name);
930 }
931 return _name_len;
932 }
933
fuzzy_match(const char * name,size_t length,bool allow_locked)934 JVMFlag* JVMFlag::fuzzy_match(const char* name, size_t length, bool allow_locked) {
935 float VMOptionsFuzzyMatchSimilarity = 0.7f;
936 JVMFlag* match = NULL;
937 float score;
938 float max_score = -1;
939
940 for (JVMFlag* current = &flagTable[0]; current->_name != NULL; current++) {
941 score = StringUtils::similarity(current->_name, strlen(current->_name), name, length);
942 if (score > max_score) {
943 max_score = score;
944 match = current;
945 }
946 }
947
948 if (match == NULL) {
949 return NULL;
950 }
951
952 if (!(match->is_unlocked() || match->is_unlocker())) {
953 if (!allow_locked) {
954 return NULL;
955 }
956 }
957
958 if (max_score < VMOptionsFuzzyMatchSimilarity) {
959 return NULL;
960 }
961
962 return match;
963 }
964
965 // Returns the address of the index'th element
address_of_flag(JVMFlagsWithType flag)966 static JVMFlag* address_of_flag(JVMFlagsWithType flag) {
967 assert((size_t)flag < JVMFlag::numFlags, "bad command line flag index");
968 return &JVMFlag::flags[flag];
969 }
970
is_default(JVMFlags flag)971 bool JVMFlagEx::is_default(JVMFlags flag) {
972 assert((size_t)flag < JVMFlag::numFlags, "bad command line flag index");
973 JVMFlag* f = &JVMFlag::flags[flag];
974 return f->is_default();
975 }
976
is_ergo(JVMFlags flag)977 bool JVMFlagEx::is_ergo(JVMFlags flag) {
978 assert((size_t)flag < JVMFlag::numFlags, "bad command line flag index");
979 JVMFlag* f = &JVMFlag::flags[flag];
980 return f->is_ergonomic();
981 }
982
is_cmdline(JVMFlags flag)983 bool JVMFlagEx::is_cmdline(JVMFlags flag) {
984 assert((size_t)flag < JVMFlag::numFlags, "bad command line flag index");
985 JVMFlag* f = &JVMFlag::flags[flag];
986 return f->is_command_line();
987 }
988
wasSetOnCmdline(const char * name,bool * value)989 bool JVMFlag::wasSetOnCmdline(const char* name, bool* value) {
990 JVMFlag* result = JVMFlag::find_flag((char*)name, strlen(name));
991 if (result == NULL) return false;
992 *value = result->is_command_line();
993 return true;
994 }
995
is_jimage_resource(JVMFlags flag)996 bool JVMFlagEx::is_jimage_resource(JVMFlags flag) {
997 assert((size_t)flag < JVMFlag::numFlags, "bad command line flag index");
998 JVMFlag* f = &JVMFlag::flags[flag];
999 return f->is_jimage_resource();
1000 }
1001
setOnCmdLine(JVMFlagsWithType flag)1002 void JVMFlagEx::setOnCmdLine(JVMFlagsWithType flag) {
1003 JVMFlag* faddr = address_of_flag(flag);
1004 assert(faddr != NULL, "Unknown flag");
1005 faddr->set_command_line();
1006 }
1007
1008 template<class E, class T>
trace_flag_changed(const char * name,const T old_value,const T new_value,const JVMFlag::Flags origin)1009 static void trace_flag_changed(const char* name, const T old_value, const T new_value, const JVMFlag::Flags origin) {
1010 E e;
1011 e.set_name(name);
1012 e.set_oldValue(old_value);
1013 e.set_newValue(new_value);
1014 e.set_origin(origin);
1015 e.commit();
1016 }
1017
apply_constraint_and_check_range_bool(const char * name,bool new_value,bool verbose)1018 static JVMFlag::Error apply_constraint_and_check_range_bool(const char* name, bool new_value, bool verbose) {
1019 JVMFlag::Error status = JVMFlag::SUCCESS;
1020 JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
1021 if (constraint != NULL) {
1022 status = constraint->apply_bool(new_value, verbose);
1023 }
1024 return status;
1025 }
1026
boolAt(const char * name,size_t len,bool * value,bool allow_locked,bool return_flag)1027 JVMFlag::Error JVMFlag::boolAt(const char* name, size_t len, bool* value, bool allow_locked, bool return_flag) {
1028 JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
1029 if (result == NULL) return JVMFlag::INVALID_FLAG;
1030 if (!result->is_bool()) return JVMFlag::WRONG_FORMAT;
1031 *value = result->get_bool();
1032 return JVMFlag::SUCCESS;
1033 }
1034
boolAtPut(JVMFlag * flag,bool * value,JVMFlag::Flags origin)1035 JVMFlag::Error JVMFlag::boolAtPut(JVMFlag* flag, bool* value, JVMFlag::Flags origin) {
1036 const char* name;
1037 if (flag == NULL) return JVMFlag::INVALID_FLAG;
1038 if (!flag->is_bool()) return JVMFlag::WRONG_FORMAT;
1039 name = flag->_name;
1040 JVMFlag::Error check = apply_constraint_and_check_range_bool(name, *value, !JVMFlagConstraintList::validated_after_ergo());
1041 if (check != JVMFlag::SUCCESS) return check;
1042 bool old_value = flag->get_bool();
1043 trace_flag_changed<EventBooleanFlagChanged, bool>(name, old_value, *value, origin);
1044 check = flag->set_bool(*value);
1045 *value = old_value;
1046 flag->set_origin(origin);
1047 return check;
1048 }
1049
boolAtPut(const char * name,size_t len,bool * value,JVMFlag::Flags origin)1050 JVMFlag::Error JVMFlag::boolAtPut(const char* name, size_t len, bool* value, JVMFlag::Flags origin) {
1051 JVMFlag* result = JVMFlag::find_flag(name, len);
1052 return boolAtPut(result, value, origin);
1053 }
1054
boolAtPut(JVMFlagsWithType flag,bool value,JVMFlag::Flags origin)1055 JVMFlag::Error JVMFlagEx::boolAtPut(JVMFlagsWithType flag, bool value, JVMFlag::Flags origin) {
1056 JVMFlag* faddr = address_of_flag(flag);
1057 guarantee(faddr != NULL && faddr->is_bool(), "wrong flag type");
1058 return JVMFlag::boolAtPut(faddr, &value, origin);
1059 }
1060
apply_constraint_and_check_range_int(const char * name,int new_value,bool verbose)1061 static JVMFlag::Error apply_constraint_and_check_range_int(const char* name, int new_value, bool verbose) {
1062 JVMFlag::Error status = JVMFlag::SUCCESS;
1063 JVMFlagRange* range = JVMFlagRangeList::find(name);
1064 if (range != NULL) {
1065 status = range->check_int(new_value, verbose);
1066 }
1067 if (status == JVMFlag::SUCCESS) {
1068 JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
1069 if (constraint != NULL) {
1070 status = constraint->apply_int(new_value, verbose);
1071 }
1072 }
1073 return status;
1074 }
1075
intAt(const char * name,size_t len,int * value,bool allow_locked,bool return_flag)1076 JVMFlag::Error JVMFlag::intAt(const char* name, size_t len, int* value, bool allow_locked, bool return_flag) {
1077 JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
1078 if (result == NULL) return JVMFlag::INVALID_FLAG;
1079 if (!result->is_int()) return JVMFlag::WRONG_FORMAT;
1080 *value = result->get_int();
1081 return JVMFlag::SUCCESS;
1082 }
1083
intAtPut(JVMFlag * flag,int * value,JVMFlag::Flags origin)1084 JVMFlag::Error JVMFlag::intAtPut(JVMFlag* flag, int* value, JVMFlag::Flags origin) {
1085 const char* name;
1086 if (flag == NULL) return JVMFlag::INVALID_FLAG;
1087 if (!flag->is_int()) return JVMFlag::WRONG_FORMAT;
1088 name = flag->_name;
1089 JVMFlag::Error check = apply_constraint_and_check_range_int(name, *value, !JVMFlagConstraintList::validated_after_ergo());
1090 if (check != JVMFlag::SUCCESS) return check;
1091 int old_value = flag->get_int();
1092 trace_flag_changed<EventIntFlagChanged, s4>(name, old_value, *value, origin);
1093 check = flag->set_int(*value);
1094 *value = old_value;
1095 flag->set_origin(origin);
1096 return check;
1097 }
1098
intAtPut(const char * name,size_t len,int * value,JVMFlag::Flags origin)1099 JVMFlag::Error JVMFlag::intAtPut(const char* name, size_t len, int* value, JVMFlag::Flags origin) {
1100 JVMFlag* result = JVMFlag::find_flag(name, len);
1101 return intAtPut(result, value, origin);
1102 }
1103
intAtPut(JVMFlagsWithType flag,int value,JVMFlag::Flags origin)1104 JVMFlag::Error JVMFlagEx::intAtPut(JVMFlagsWithType flag, int value, JVMFlag::Flags origin) {
1105 JVMFlag* faddr = address_of_flag(flag);
1106 guarantee(faddr != NULL && faddr->is_int(), "wrong flag type");
1107 return JVMFlag::intAtPut(faddr, &value, origin);
1108 }
1109
apply_constraint_and_check_range_uint(const char * name,uint new_value,bool verbose)1110 static JVMFlag::Error apply_constraint_and_check_range_uint(const char* name, uint new_value, bool verbose) {
1111 JVMFlag::Error status = JVMFlag::SUCCESS;
1112 JVMFlagRange* range = JVMFlagRangeList::find(name);
1113 if (range != NULL) {
1114 status = range->check_uint(new_value, verbose);
1115 }
1116 if (status == JVMFlag::SUCCESS) {
1117 JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
1118 if (constraint != NULL) {
1119 status = constraint->apply_uint(new_value, verbose);
1120 }
1121 }
1122 return status;
1123 }
1124
uintAt(const char * name,size_t len,uint * value,bool allow_locked,bool return_flag)1125 JVMFlag::Error JVMFlag::uintAt(const char* name, size_t len, uint* value, bool allow_locked, bool return_flag) {
1126 JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
1127 if (result == NULL) return JVMFlag::INVALID_FLAG;
1128 if (!result->is_uint()) return JVMFlag::WRONG_FORMAT;
1129 *value = result->get_uint();
1130 return JVMFlag::SUCCESS;
1131 }
1132
uintAtPut(JVMFlag * flag,uint * value,JVMFlag::Flags origin)1133 JVMFlag::Error JVMFlag::uintAtPut(JVMFlag* flag, uint* value, JVMFlag::Flags origin) {
1134 const char* name;
1135 if (flag == NULL) return JVMFlag::INVALID_FLAG;
1136 if (!flag->is_uint()) return JVMFlag::WRONG_FORMAT;
1137 name = flag->_name;
1138 JVMFlag::Error check = apply_constraint_and_check_range_uint(name, *value, !JVMFlagConstraintList::validated_after_ergo());
1139 if (check != JVMFlag::SUCCESS) return check;
1140 uint old_value = flag->get_uint();
1141 trace_flag_changed<EventUnsignedIntFlagChanged, u4>(name, old_value, *value, origin);
1142 check = flag->set_uint(*value);
1143 *value = old_value;
1144 flag->set_origin(origin);
1145 return check;
1146 }
1147
uintAtPut(const char * name,size_t len,uint * value,JVMFlag::Flags origin)1148 JVMFlag::Error JVMFlag::uintAtPut(const char* name, size_t len, uint* value, JVMFlag::Flags origin) {
1149 JVMFlag* result = JVMFlag::find_flag(name, len);
1150 return uintAtPut(result, value, origin);
1151 }
1152
uintAtPut(JVMFlagsWithType flag,uint value,JVMFlag::Flags origin)1153 JVMFlag::Error JVMFlagEx::uintAtPut(JVMFlagsWithType flag, uint value, JVMFlag::Flags origin) {
1154 JVMFlag* faddr = address_of_flag(flag);
1155 guarantee(faddr != NULL && faddr->is_uint(), "wrong flag type");
1156 return JVMFlag::uintAtPut(faddr, &value, origin);
1157 }
1158
intxAt(const char * name,size_t len,intx * value,bool allow_locked,bool return_flag)1159 JVMFlag::Error JVMFlag::intxAt(const char* name, size_t len, intx* value, bool allow_locked, bool return_flag) {
1160 JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
1161 if (result == NULL) return JVMFlag::INVALID_FLAG;
1162 if (!result->is_intx()) return JVMFlag::WRONG_FORMAT;
1163 *value = result->get_intx();
1164 return JVMFlag::SUCCESS;
1165 }
1166
apply_constraint_and_check_range_intx(const char * name,intx new_value,bool verbose)1167 static JVMFlag::Error apply_constraint_and_check_range_intx(const char* name, intx new_value, bool verbose) {
1168 JVMFlag::Error status = JVMFlag::SUCCESS;
1169 JVMFlagRange* range = JVMFlagRangeList::find(name);
1170 if (range != NULL) {
1171 status = range->check_intx(new_value, verbose);
1172 }
1173 if (status == JVMFlag::SUCCESS) {
1174 JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
1175 if (constraint != NULL) {
1176 status = constraint->apply_intx(new_value, verbose);
1177 }
1178 }
1179 return status;
1180 }
1181
intxAtPut(JVMFlag * flag,intx * value,JVMFlag::Flags origin)1182 JVMFlag::Error JVMFlag::intxAtPut(JVMFlag* flag, intx* value, JVMFlag::Flags origin) {
1183 const char* name;
1184 if (flag == NULL) return JVMFlag::INVALID_FLAG;
1185 if (!flag->is_intx()) return JVMFlag::WRONG_FORMAT;
1186 name = flag->_name;
1187 JVMFlag::Error check = apply_constraint_and_check_range_intx(name, *value, !JVMFlagConstraintList::validated_after_ergo());
1188 if (check != JVMFlag::SUCCESS) return check;
1189 intx old_value = flag->get_intx();
1190 trace_flag_changed<EventLongFlagChanged, intx>(name, old_value, *value, origin);
1191 check = flag->set_intx(*value);
1192 *value = old_value;
1193 flag->set_origin(origin);
1194 return check;
1195 }
1196
intxAtPut(const char * name,size_t len,intx * value,JVMFlag::Flags origin)1197 JVMFlag::Error JVMFlag::intxAtPut(const char* name, size_t len, intx* value, JVMFlag::Flags origin) {
1198 JVMFlag* result = JVMFlag::find_flag(name, len);
1199 return intxAtPut(result, value, origin);
1200 }
1201
intxAtPut(JVMFlagsWithType flag,intx value,JVMFlag::Flags origin)1202 JVMFlag::Error JVMFlagEx::intxAtPut(JVMFlagsWithType flag, intx value, JVMFlag::Flags origin) {
1203 JVMFlag* faddr = address_of_flag(flag);
1204 guarantee(faddr != NULL && faddr->is_intx(), "wrong flag type");
1205 return JVMFlag::intxAtPut(faddr, &value, origin);
1206 }
1207
uintxAt(const char * name,size_t len,uintx * value,bool allow_locked,bool return_flag)1208 JVMFlag::Error JVMFlag::uintxAt(const char* name, size_t len, uintx* value, bool allow_locked, bool return_flag) {
1209 JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
1210 if (result == NULL) return JVMFlag::INVALID_FLAG;
1211 if (!result->is_uintx()) return JVMFlag::WRONG_FORMAT;
1212 *value = result->get_uintx();
1213 return JVMFlag::SUCCESS;
1214 }
1215
apply_constraint_and_check_range_uintx(const char * name,uintx new_value,bool verbose)1216 static JVMFlag::Error apply_constraint_and_check_range_uintx(const char* name, uintx new_value, bool verbose) {
1217 JVMFlag::Error status = JVMFlag::SUCCESS;
1218 JVMFlagRange* range = JVMFlagRangeList::find(name);
1219 if (range != NULL) {
1220 status = range->check_uintx(new_value, verbose);
1221 }
1222 if (status == JVMFlag::SUCCESS) {
1223 JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
1224 if (constraint != NULL) {
1225 status = constraint->apply_uintx(new_value, verbose);
1226 }
1227 }
1228 return status;
1229 }
1230
uintxAtPut(JVMFlag * flag,uintx * value,JVMFlag::Flags origin)1231 JVMFlag::Error JVMFlag::uintxAtPut(JVMFlag* flag, uintx* value, JVMFlag::Flags origin) {
1232 const char* name;
1233 if (flag == NULL) return JVMFlag::INVALID_FLAG;
1234 if (!flag->is_uintx()) return JVMFlag::WRONG_FORMAT;
1235 name = flag->_name;
1236 JVMFlag::Error check = apply_constraint_and_check_range_uintx(name, *value, !JVMFlagConstraintList::validated_after_ergo());
1237 if (check != JVMFlag::SUCCESS) return check;
1238 uintx old_value = flag->get_uintx();
1239 trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
1240 check = flag->set_uintx(*value);
1241 *value = old_value;
1242 flag->set_origin(origin);
1243 return check;
1244 }
1245
uintxAtPut(const char * name,size_t len,uintx * value,JVMFlag::Flags origin)1246 JVMFlag::Error JVMFlag::uintxAtPut(const char* name, size_t len, uintx* value, JVMFlag::Flags origin) {
1247 JVMFlag* result = JVMFlag::find_flag(name, len);
1248 return uintxAtPut(result, value, origin);
1249 }
1250
uintxAtPut(JVMFlagsWithType flag,uintx value,JVMFlag::Flags origin)1251 JVMFlag::Error JVMFlagEx::uintxAtPut(JVMFlagsWithType flag, uintx value, JVMFlag::Flags origin) {
1252 JVMFlag* faddr = address_of_flag(flag);
1253 guarantee(faddr != NULL && faddr->is_uintx(), "wrong flag type");
1254 return JVMFlag::uintxAtPut(faddr, &value, origin);
1255 }
1256
uint64_tAt(const char * name,size_t len,uint64_t * value,bool allow_locked,bool return_flag)1257 JVMFlag::Error JVMFlag::uint64_tAt(const char* name, size_t len, uint64_t* value, bool allow_locked, bool return_flag) {
1258 JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
1259 if (result == NULL) return JVMFlag::INVALID_FLAG;
1260 if (!result->is_uint64_t()) return JVMFlag::WRONG_FORMAT;
1261 *value = result->get_uint64_t();
1262 return JVMFlag::SUCCESS;
1263 }
1264
apply_constraint_and_check_range_uint64_t(const char * name,uint64_t new_value,bool verbose)1265 static JVMFlag::Error apply_constraint_and_check_range_uint64_t(const char* name, uint64_t new_value, bool verbose) {
1266 JVMFlag::Error status = JVMFlag::SUCCESS;
1267 JVMFlagRange* range = JVMFlagRangeList::find(name);
1268 if (range != NULL) {
1269 status = range->check_uint64_t(new_value, verbose);
1270 }
1271 if (status == JVMFlag::SUCCESS) {
1272 JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
1273 if (constraint != NULL) {
1274 status = constraint->apply_uint64_t(new_value, verbose);
1275 }
1276 }
1277 return status;
1278 }
1279
uint64_tAtPut(JVMFlag * flag,uint64_t * value,JVMFlag::Flags origin)1280 JVMFlag::Error JVMFlag::uint64_tAtPut(JVMFlag* flag, uint64_t* value, JVMFlag::Flags origin) {
1281 const char* name;
1282 if (flag == NULL) return JVMFlag::INVALID_FLAG;
1283 if (!flag->is_uint64_t()) return JVMFlag::WRONG_FORMAT;
1284 name = flag->_name;
1285 JVMFlag::Error check = apply_constraint_and_check_range_uint64_t(name, *value, !JVMFlagConstraintList::validated_after_ergo());
1286 if (check != JVMFlag::SUCCESS) return check;
1287 uint64_t old_value = flag->get_uint64_t();
1288 trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
1289 check = flag->set_uint64_t(*value);
1290 *value = old_value;
1291 flag->set_origin(origin);
1292 return check;
1293 }
1294
uint64_tAtPut(const char * name,size_t len,uint64_t * value,JVMFlag::Flags origin)1295 JVMFlag::Error JVMFlag::uint64_tAtPut(const char* name, size_t len, uint64_t* value, JVMFlag::Flags origin) {
1296 JVMFlag* result = JVMFlag::find_flag(name, len);
1297 return uint64_tAtPut(result, value, origin);
1298 }
1299
uint64_tAtPut(JVMFlagsWithType flag,uint64_t value,JVMFlag::Flags origin)1300 JVMFlag::Error JVMFlagEx::uint64_tAtPut(JVMFlagsWithType flag, uint64_t value, JVMFlag::Flags origin) {
1301 JVMFlag* faddr = address_of_flag(flag);
1302 guarantee(faddr != NULL && faddr->is_uint64_t(), "wrong flag type");
1303 return JVMFlag::uint64_tAtPut(faddr, &value, origin);
1304 }
1305
size_tAt(const char * name,size_t len,size_t * value,bool allow_locked,bool return_flag)1306 JVMFlag::Error JVMFlag::size_tAt(const char* name, size_t len, size_t* value, bool allow_locked, bool return_flag) {
1307 JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
1308 if (result == NULL) return JVMFlag::INVALID_FLAG;
1309 if (!result->is_size_t()) return JVMFlag::WRONG_FORMAT;
1310 *value = result->get_size_t();
1311 return JVMFlag::SUCCESS;
1312 }
1313
apply_constraint_and_check_range_size_t(const char * name,size_t new_value,bool verbose)1314 static JVMFlag::Error apply_constraint_and_check_range_size_t(const char* name, size_t new_value, bool verbose) {
1315 JVMFlag::Error status = JVMFlag::SUCCESS;
1316 JVMFlagRange* range = JVMFlagRangeList::find(name);
1317 if (range != NULL) {
1318 status = range->check_size_t(new_value, verbose);
1319 }
1320 if (status == JVMFlag::SUCCESS) {
1321 JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
1322 if (constraint != NULL) {
1323 status = constraint->apply_size_t(new_value, verbose);
1324 }
1325 }
1326 return status;
1327 }
1328
1329
size_tAtPut(JVMFlag * flag,size_t * value,JVMFlag::Flags origin)1330 JVMFlag::Error JVMFlag::size_tAtPut(JVMFlag* flag, size_t* value, JVMFlag::Flags origin) {
1331 const char* name;
1332 if (flag == NULL) return JVMFlag::INVALID_FLAG;
1333 if (!flag->is_size_t()) return JVMFlag::WRONG_FORMAT;
1334 name = flag->_name;
1335 JVMFlag::Error check = apply_constraint_and_check_range_size_t(name, *value, !JVMFlagConstraintList::validated_after_ergo());
1336 if (check != JVMFlag::SUCCESS) return check;
1337 size_t old_value = flag->get_size_t();
1338 trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
1339 check = flag->set_size_t(*value);
1340 *value = old_value;
1341 flag->set_origin(origin);
1342 return check;
1343 }
1344
size_tAtPut(const char * name,size_t len,size_t * value,JVMFlag::Flags origin)1345 JVMFlag::Error JVMFlag::size_tAtPut(const char* name, size_t len, size_t* value, JVMFlag::Flags origin) {
1346 JVMFlag* result = JVMFlag::find_flag(name, len);
1347 return size_tAtPut(result, value, origin);
1348 }
1349
size_tAtPut(JVMFlagsWithType flag,size_t value,JVMFlag::Flags origin)1350 JVMFlag::Error JVMFlagEx::size_tAtPut(JVMFlagsWithType flag, size_t value, JVMFlag::Flags origin) {
1351 JVMFlag* faddr = address_of_flag(flag);
1352 guarantee(faddr != NULL && faddr->is_size_t(), "wrong flag type");
1353 return JVMFlag::size_tAtPut(faddr, &value, origin);
1354 }
1355
doubleAt(const char * name,size_t len,double * value,bool allow_locked,bool return_flag)1356 JVMFlag::Error JVMFlag::doubleAt(const char* name, size_t len, double* value, bool allow_locked, bool return_flag) {
1357 JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
1358 if (result == NULL) return JVMFlag::INVALID_FLAG;
1359 if (!result->is_double()) return JVMFlag::WRONG_FORMAT;
1360 *value = result->get_double();
1361 return JVMFlag::SUCCESS;
1362 }
1363
apply_constraint_and_check_range_double(const char * name,double new_value,bool verbose)1364 static JVMFlag::Error apply_constraint_and_check_range_double(const char* name, double new_value, bool verbose) {
1365 JVMFlag::Error status = JVMFlag::SUCCESS;
1366 JVMFlagRange* range = JVMFlagRangeList::find(name);
1367 if (range != NULL) {
1368 status = range->check_double(new_value, verbose);
1369 }
1370 if (status == JVMFlag::SUCCESS) {
1371 JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
1372 if (constraint != NULL) {
1373 status = constraint->apply_double(new_value, verbose);
1374 }
1375 }
1376 return status;
1377 }
1378
doubleAtPut(JVMFlag * flag,double * value,JVMFlag::Flags origin)1379 JVMFlag::Error JVMFlag::doubleAtPut(JVMFlag* flag, double* value, JVMFlag::Flags origin) {
1380 const char* name;
1381 if (flag == NULL) return JVMFlag::INVALID_FLAG;
1382 if (!flag->is_double()) return JVMFlag::WRONG_FORMAT;
1383 name = flag->_name;
1384 JVMFlag::Error check = apply_constraint_and_check_range_double(name, *value, !JVMFlagConstraintList::validated_after_ergo());
1385 if (check != JVMFlag::SUCCESS) return check;
1386 double old_value = flag->get_double();
1387 trace_flag_changed<EventDoubleFlagChanged, double>(name, old_value, *value, origin);
1388 check = flag->set_double(*value);
1389 *value = old_value;
1390 flag->set_origin(origin);
1391 return check;
1392 }
1393
doubleAtPut(const char * name,size_t len,double * value,JVMFlag::Flags origin)1394 JVMFlag::Error JVMFlag::doubleAtPut(const char* name, size_t len, double* value, JVMFlag::Flags origin) {
1395 JVMFlag* result = JVMFlag::find_flag(name, len);
1396 return doubleAtPut(result, value, origin);
1397 }
1398
doubleAtPut(JVMFlagsWithType flag,double value,JVMFlag::Flags origin)1399 JVMFlag::Error JVMFlagEx::doubleAtPut(JVMFlagsWithType flag, double value, JVMFlag::Flags origin) {
1400 JVMFlag* faddr = address_of_flag(flag);
1401 guarantee(faddr != NULL && faddr->is_double(), "wrong flag type");
1402 return JVMFlag::doubleAtPut(faddr, &value, origin);
1403 }
1404
ccstrAt(const char * name,size_t len,ccstr * value,bool allow_locked,bool return_flag)1405 JVMFlag::Error JVMFlag::ccstrAt(const char* name, size_t len, ccstr* value, bool allow_locked, bool return_flag) {
1406 JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
1407 if (result == NULL) return JVMFlag::INVALID_FLAG;
1408 if (!result->is_ccstr()) return JVMFlag::WRONG_FORMAT;
1409 *value = result->get_ccstr();
1410 return JVMFlag::SUCCESS;
1411 }
1412
ccstrAtPut(const char * name,size_t len,ccstr * value,JVMFlag::Flags origin)1413 JVMFlag::Error JVMFlag::ccstrAtPut(const char* name, size_t len, ccstr* value, JVMFlag::Flags origin) {
1414 JVMFlag* result = JVMFlag::find_flag(name, len);
1415 if (result == NULL) return JVMFlag::INVALID_FLAG;
1416 if (!result->is_ccstr()) return JVMFlag::WRONG_FORMAT;
1417 ccstr old_value = result->get_ccstr();
1418 trace_flag_changed<EventStringFlagChanged, const char*>(name, old_value, *value, origin);
1419 char* new_value = NULL;
1420 if (*value != NULL) {
1421 new_value = os::strdup_check_oom(*value);
1422 }
1423 JVMFlag::Error check = result->set_ccstr(new_value);
1424 if (result->is_default() && old_value != NULL) {
1425 // Prior value is NOT heap allocated, but was a literal constant.
1426 old_value = os::strdup_check_oom(old_value);
1427 }
1428 *value = old_value;
1429 result->set_origin(origin);
1430 return check;
1431 }
1432
ccstrAtPut(JVMFlagsWithType flag,ccstr value,JVMFlag::Flags origin)1433 JVMFlag::Error JVMFlagEx::ccstrAtPut(JVMFlagsWithType flag, ccstr value, JVMFlag::Flags origin) {
1434 JVMFlag* faddr = address_of_flag(flag);
1435 guarantee(faddr != NULL && faddr->is_ccstr(), "wrong flag type");
1436 ccstr old_value = faddr->get_ccstr();
1437 trace_flag_changed<EventStringFlagChanged, const char*>(faddr->_name, old_value, value, origin);
1438 char* new_value = os::strdup_check_oom(value);
1439 JVMFlag::Error check = faddr->set_ccstr(new_value);
1440 if (!faddr->is_default() && old_value != NULL) {
1441 // Prior value is heap allocated so free it.
1442 FREE_C_HEAP_ARRAY(char, old_value);
1443 }
1444 faddr->set_origin(origin);
1445 return check;
1446 }
1447
1448 extern "C" {
compare_flags(const void * void_a,const void * void_b)1449 static int compare_flags(const void* void_a, const void* void_b) {
1450 return strcmp((*((JVMFlag**) void_a))->_name, (*((JVMFlag**) void_b))->_name);
1451 }
1452 }
1453
printSetFlags(outputStream * out)1454 void JVMFlag::printSetFlags(outputStream* out) {
1455 // Print which flags were set on the command line
1456 // note: this method is called before the thread structure is in place
1457 // which means resource allocation cannot be used.
1458
1459 // The last entry is the null entry.
1460 const size_t length = JVMFlag::numFlags - 1;
1461
1462 // Sort
1463 JVMFlag** array = NEW_C_HEAP_ARRAY(JVMFlag*, length, mtArguments);
1464 for (size_t i = 0; i < length; i++) {
1465 array[i] = &flagTable[i];
1466 }
1467 qsort(array, length, sizeof(JVMFlag*), compare_flags);
1468
1469 // Print
1470 for (size_t i = 0; i < length; i++) {
1471 if (array[i]->get_origin() /* naked field! */) {
1472 array[i]->print_as_flag(out);
1473 out->print(" ");
1474 }
1475 }
1476 out->cr();
1477 FREE_C_HEAP_ARRAY(JVMFlag*, array);
1478 }
1479
1480 #ifndef PRODUCT
1481
verify()1482 void JVMFlag::verify() {
1483 assert(Arguments::check_vm_args_consistency(), "Some flag settings conflict");
1484 }
1485
1486 #endif // PRODUCT
1487
printFlags(outputStream * out,bool withComments,bool printRanges,bool skipDefaults)1488 void JVMFlag::printFlags(outputStream* out, bool withComments, bool printRanges, bool skipDefaults) {
1489 // Print the flags sorted by name
1490 // Note: This method may be called before the thread structure is in place
1491 // which means resource allocation cannot be used. Also, it may be
1492 // called as part of error reporting, so handle native OOMs gracefully.
1493
1494 // The last entry is the null entry.
1495 const size_t length = JVMFlag::numFlags - 1;
1496
1497 // Print
1498 if (!printRanges) {
1499 out->print_cr("[Global flags]");
1500 } else {
1501 out->print_cr("[Global flags ranges]");
1502 }
1503
1504 // Sort
1505 JVMFlag** array = NEW_C_HEAP_ARRAY_RETURN_NULL(JVMFlag*, length, mtArguments);
1506 if (array != NULL) {
1507 for (size_t i = 0; i < length; i++) {
1508 array[i] = &flagTable[i];
1509 }
1510 qsort(array, length, sizeof(JVMFlag*), compare_flags);
1511
1512 for (size_t i = 0; i < length; i++) {
1513 if (array[i]->is_unlocked() && !(skipDefaults && array[i]->is_default())) {
1514 array[i]->print_on(out, withComments, printRanges);
1515 }
1516 }
1517 FREE_C_HEAP_ARRAY(JVMFlag*, array);
1518 } else {
1519 // OOM? Print unsorted.
1520 for (size_t i = 0; i < length; i++) {
1521 if (flagTable[i].is_unlocked() && !(skipDefaults && flagTable[i].is_default())) {
1522 flagTable[i].print_on(out, withComments, printRanges);
1523 }
1524 }
1525 }
1526 }
1527
printError(bool verbose,const char * msg,...)1528 void JVMFlag::printError(bool verbose, const char* msg, ...) {
1529 if (verbose) {
1530 va_list listPointer;
1531 va_start(listPointer, msg);
1532 jio_vfprintf(defaultStream::error_stream(), msg, listPointer);
1533 va_end(listPointer);
1534 }
1535 }
1536
1537