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 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 // 312 // Sample output: 313 // bool ThreadPriorityVerbose = false {product} {default} 314 // uintx ThresholdTolerance = 10 {product} {default} 315 // size_t TLABSize = 0 {product} {default} 316 // uintx SurvivorRatio = 8 {product} {default} 317 // double InitialRAMPercentage = 1.562500 {product} {default} 318 // ccstr CompileCommandFile = MyFile.cmd {product} {command line} 319 // ccstrlist CompileOnly = Method1 320 // CompileOnly += Method2 {product} {command line} 321 // | | | | | | | 322 // | | | | | | +-- col7 323 // | | | | | +-- col6 324 // | | | | +-- col5 325 // | | | +-- col4 326 // | | +-- col3 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} 426 // double MinRAMPercentage [ 0.000 ... 100.000 ] {product} {default} 427 // uintx MinSurvivorRatio [ 3 ... 18446744073709551615 ] {product} {default} 428 // size_t MinTLABSize [ 1 ... 9223372036854775807 ] {product} {default} 429 // intx MonitorBound [ 0 ... 2147483647 ] {product} {default} 430 // | | | | | | 431 // | | | | | +-- col7 432 // | | | | +-- col6 433 // | | | +-- col5 434 // | | +-- col4 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 }