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