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