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