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