1 /*
   2  * Copyright (c) 1997, 2015, 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 
 407     if (printRanges) {
 408 
 409       st->print("%9s %-50s ", _type, _name);
 410 
 411       CommandLineFlagRangeList::print(_name, st, true);
 412 
 413       st->print(" %-20s", " ");
 414       print_kind(st);
 415 
 416 #ifndef PRODUCT
 417       if (withComments) {
 418         st->print("%s", _doc);
 419       }
 420 #endif
 421 
 422       st->cr();
 423 
 424     }
 425   }
 426 }
 427 
 428 void Flag::print_kind(outputStream* st) {
 429   struct Data {
 430     int flag;
 431     const char* name;
 432   };
 433 
 434   Data data[] = {
 435       { KIND_JVMCI, "JVMCI" },
 436       { KIND_C1, "C1" },
 437       { KIND_C2, "C2" },
 438       { KIND_ARCH, "ARCH" },
 439       { KIND_SHARK, "SHARK" },
 440       { KIND_PLATFORM_DEPENDENT, "pd" },
 441       { KIND_PRODUCT, "product" },
 442       { KIND_MANAGEABLE, "manageable" },
 443       { KIND_DIAGNOSTIC, "diagnostic" },
 444       { KIND_EXPERIMENTAL, "experimental" },
 445       { KIND_COMMERCIAL, "commercial" },
 446       { KIND_NOT_PRODUCT, "notproduct" },
 447       { KIND_DEVELOP, "develop" },
 448       { KIND_LP64_PRODUCT, "lp64_product" },
 449       { KIND_READ_WRITE, "rw" },
 450       { -1, "" }
 451   };
 452 
 453   if ((_flags & KIND_MASK) != 0) {
 454     st->print("{");
 455     bool is_first = true;
 456 
 457     for (int i = 0; data[i].flag != -1; i++) {
 458       Data d = data[i];
 459       if ((_flags & d.flag) != 0) {
 460         if (is_first) {
 461           is_first = false;
 462         } else {
 463           st->print(" ");
 464         }
 465         st->print("%s", d.name);
 466       }
 467     }
 468 
 469     st->print("}");
 470   }
 471 }
 472 
 473 void Flag::print_as_flag(outputStream* st) {
 474   if (is_bool()) {
 475     st->print("-XX:%s%s", get_bool() ? "+" : "-", _name);
 476   } else if (is_int()) {
 477     st->print("-XX:%s=%d", _name, get_int());
 478   } else if (is_uint()) {
 479     st->print("-XX:%s=%u", _name, get_uint());
 480   } else if (is_intx()) {
 481     st->print("-XX:%s=" INTX_FORMAT, _name, get_intx());
 482   } else if (is_uintx()) {
 483     st->print("-XX:%s=" UINTX_FORMAT, _name, get_uintx());
 484   } else if (is_uint64_t()) {
 485     st->print("-XX:%s=" UINT64_FORMAT, _name, get_uint64_t());
 486   } else if (is_size_t()) {
 487     st->print("-XX:%s=" SIZE_FORMAT, _name, get_size_t());
 488   } else if (is_double()) {
 489     st->print("-XX:%s=%f", _name, get_double());
 490   } else if (is_ccstr()) {
 491     st->print("-XX:%s=", _name);
 492     const char* cp = get_ccstr();
 493     if (cp != NULL) {
 494       // Need to turn embedded '\n's back into separate arguments
 495       // Not so efficient to print one character at a time,
 496       // but the choice is to do the transformation to a buffer
 497       // and print that.  And this need not be efficient.
 498       for (; *cp != '\0'; cp += 1) {
 499         switch (*cp) {
 500           default:
 501             st->print("%c", *cp);
 502             break;
 503           case '\n':
 504             st->print(" -XX:%s=", _name);
 505             break;
 506         }
 507       }
 508     }
 509   } else {
 510     ShouldNotReachHere();
 511   }
 512 }
 513 
 514 const char* Flag::flag_error_str(Flag::Error error) {
 515   switch (error) {
 516     case Flag::MISSING_NAME: return "MISSING_NAME";
 517     case Flag::MISSING_VALUE: return "MISSING_VALUE";
 518     case Flag::NON_WRITABLE: return "NON_WRITABLE";
 519     case Flag::OUT_OF_BOUNDS: return "OUT_OF_BOUNDS";
 520     case Flag::VIOLATES_CONSTRAINT: return "VIOLATES_CONSTRAINT";
 521     case Flag::INVALID_FLAG: return "INVALID_FLAG";
 522     case Flag::ERR_OTHER: return "ERR_OTHER";
 523     case Flag::SUCCESS: return "SUCCESS";
 524     default: ShouldNotReachHere(); return "NULL";
 525   }
 526 }
 527 
 528 // 4991491 do not "optimize out" the was_set false values: omitting them
 529 // tickles a Microsoft compiler bug causing flagTable to be malformed
 530 
 531 #define RUNTIME_PRODUCT_FLAG_STRUCT(     type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_PRODUCT) },
 532 #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) },
 533 #define RUNTIME_DIAGNOSTIC_FLAG_STRUCT(  type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_DIAGNOSTIC) },
 534 #define RUNTIME_EXPERIMENTAL_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_EXPERIMENTAL) },
 535 #define RUNTIME_MANAGEABLE_FLAG_STRUCT(  type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_MANAGEABLE) },
 536 #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) },
 537 #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) },
 538 #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) },
 539 #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) },
 540 
 541 #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) },
 542 #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) },
 543 #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) },
 544 #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) },
 545 #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) },
 546 #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) },
 547 #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) },
 548 
 549 #ifdef _LP64
 550 #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) },
 551 #else
 552 #define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) /* flag is constant */
 553 #endif // _LP64
 554 
 555 #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) },
 556 #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) },
 557 #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) },
 558 #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) },
 559 #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) },
 560 #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) },
 561 
 562 #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) },
 563 #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) },
 564 #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) },
 565 #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) },
 566 #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) },
 567 #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) },
 568 #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) },
 569 
 570 #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) },
 571 #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) },
 572 #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) },
 573 #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) },
 574 #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) },
 575 
 576 #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) },
 577 #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) },
 578 #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) },
 579 #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) },
 580 #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) },
 581 #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) },
 582 
 583 static Flag flagTable[] = {
 584  RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, \
 585                RUNTIME_PD_DEVELOP_FLAG_STRUCT, \
 586                RUNTIME_PRODUCT_FLAG_STRUCT, \
 587                RUNTIME_PD_PRODUCT_FLAG_STRUCT, \
 588                RUNTIME_DIAGNOSTIC_FLAG_STRUCT, \
 589                RUNTIME_EXPERIMENTAL_FLAG_STRUCT, \
 590                RUNTIME_NOTPRODUCT_FLAG_STRUCT, \
 591                RUNTIME_MANAGEABLE_FLAG_STRUCT, \
 592                RUNTIME_PRODUCT_RW_FLAG_STRUCT, \
 593                RUNTIME_LP64_PRODUCT_FLAG_STRUCT, \
 594                IGNORE_RANGE, \
 595                IGNORE_CONSTRAINT)
 596  RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, \
 597                   RUNTIME_PD_DEVELOP_FLAG_STRUCT, \
 598                   RUNTIME_PRODUCT_FLAG_STRUCT, \
 599                   RUNTIME_PD_PRODUCT_FLAG_STRUCT, \
 600                   RUNTIME_DIAGNOSTIC_FLAG_STRUCT, \
 601                   RUNTIME_NOTPRODUCT_FLAG_STRUCT, \
 602                   IGNORE_RANGE, \
 603                   IGNORE_CONSTRAINT)
 604 #if INCLUDE_ALL_GCS
 605  G1_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, \
 606           RUNTIME_PD_DEVELOP_FLAG_STRUCT, \
 607           RUNTIME_PRODUCT_FLAG_STRUCT, \
 608           RUNTIME_PD_PRODUCT_FLAG_STRUCT, \
 609           RUNTIME_DIAGNOSTIC_FLAG_STRUCT, \
 610           RUNTIME_EXPERIMENTAL_FLAG_STRUCT, \
 611           RUNTIME_NOTPRODUCT_FLAG_STRUCT, \
 612           RUNTIME_MANAGEABLE_FLAG_STRUCT, \
 613           RUNTIME_PRODUCT_RW_FLAG_STRUCT, \
 614           IGNORE_RANGE, \
 615           IGNORE_CONSTRAINT)
 616 #endif // INCLUDE_ALL_GCS
 617 #if INCLUDE_JVMCI
 618  JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_STRUCT, \
 619              JVMCI_PD_DEVELOP_FLAG_STRUCT, \
 620              JVMCI_PRODUCT_FLAG_STRUCT, \
 621              JVMCI_PD_PRODUCT_FLAG_STRUCT, \
 622              JVMCI_DIAGNOSTIC_FLAG_STRUCT, \
 623              JVMCI_EXPERIMENTAL_FLAG_STRUCT, \
 624              JVMCI_NOTPRODUCT_FLAG_STRUCT, \
 625              IGNORE_RANGE, \
 626              IGNORE_CONSTRAINT)
 627 #endif // INCLUDE_JVMCI
 628 #ifdef COMPILER1
 629  C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, \
 630           C1_PD_DEVELOP_FLAG_STRUCT, \
 631           C1_PRODUCT_FLAG_STRUCT, \
 632           C1_PD_PRODUCT_FLAG_STRUCT, \
 633           C1_DIAGNOSTIC_FLAG_STRUCT, \
 634           C1_NOTPRODUCT_FLAG_STRUCT, \
 635           IGNORE_RANGE, \
 636           IGNORE_CONSTRAINT)
 637 #endif // COMPILER1
 638 #ifdef COMPILER2
 639  C2_FLAGS(C2_DEVELOP_FLAG_STRUCT, \
 640           C2_PD_DEVELOP_FLAG_STRUCT, \
 641           C2_PRODUCT_FLAG_STRUCT, \
 642           C2_PD_PRODUCT_FLAG_STRUCT, \
 643           C2_DIAGNOSTIC_FLAG_STRUCT, \
 644           C2_EXPERIMENTAL_FLAG_STRUCT, \
 645           C2_NOTPRODUCT_FLAG_STRUCT, \
 646           IGNORE_RANGE, \
 647           IGNORE_CONSTRAINT)
 648 #endif // COMPILER2
 649 #ifdef SHARK
 650  SHARK_FLAGS(SHARK_DEVELOP_FLAG_STRUCT, \
 651              SHARK_PD_DEVELOP_FLAG_STRUCT, \
 652              SHARK_PRODUCT_FLAG_STRUCT, \
 653              SHARK_PD_PRODUCT_FLAG_STRUCT, \
 654              SHARK_DIAGNOSTIC_FLAG_STRUCT, \
 655              SHARK_NOTPRODUCT_FLAG_STRUCT)
 656 #endif // SHARK
 657  ARCH_FLAGS(ARCH_DEVELOP_FLAG_STRUCT, \
 658             ARCH_PRODUCT_FLAG_STRUCT, \
 659             ARCH_DIAGNOSTIC_FLAG_STRUCT, \
 660             ARCH_EXPERIMENTAL_FLAG_STRUCT, \
 661             ARCH_NOTPRODUCT_FLAG_STRUCT, \
 662             IGNORE_RANGE, \
 663             IGNORE_CONSTRAINT)
 664  FLAGTABLE_EXT
 665  {0, NULL, NULL}
 666 };
 667 
 668 Flag* Flag::flags = flagTable;
 669 size_t Flag::numFlags = (sizeof(flagTable) / sizeof(Flag));
 670 
 671 inline bool str_equal(const char* s, const char* q, size_t len) {
 672   // s is null terminated, q is not!
 673   if (strlen(s) != (unsigned int) len) return false;
 674   return strncmp(s, q, len) == 0;
 675 }
 676 
 677 // Search the flag table for a named flag
 678 Flag* Flag::find_flag(const char* name, size_t length, bool allow_locked, bool return_flag) {
 679   for (Flag* current = &flagTable[0]; current->_name != NULL; current++) {
 680     if (str_equal(current->_name, name, length)) {
 681       // Found a matching entry.
 682       // Don't report notproduct and develop flags in product builds.
 683       if (current->is_constant_in_binary()) {
 684         return (return_flag ? current : NULL);
 685       }
 686       // Report locked flags only if allowed.
 687       if (!(current->is_unlocked() || current->is_unlocker())) {
 688         if (!allow_locked) {
 689           // disable use of locked flags, e.g. diagnostic, experimental,
 690           // commercial... until they are explicitly unlocked
 691           return NULL;
 692         }
 693       }
 694       return current;
 695     }
 696   }
 697   // Flag name is not in the flag table
 698   return NULL;
 699 }
 700 
 701 // Compute string similarity based on Dice's coefficient
 702 static float str_similar(const char* str1, const char* str2, size_t len2) {
 703   int len1 = (int) strlen(str1);
 704   int total = len1 + (int) len2;
 705 
 706   int hit = 0;
 707 
 708   for (int i = 0; i < len1 -1; ++i) {
 709     for (int j = 0; j < (int) len2 -1; ++j) {
 710       if ((str1[i] == str2[j]) && (str1[i+1] == str2[j+1])) {
 711         ++hit;
 712         break;
 713       }
 714     }
 715   }
 716 
 717   return 2.0f * (float) hit / (float) total;
 718 }
 719 
 720 Flag* Flag::fuzzy_match(const char* name, size_t length, bool allow_locked) {
 721   float VMOptionsFuzzyMatchSimilarity = 0.7f;
 722   Flag* match = NULL;
 723   float score;
 724   float max_score = -1;
 725 
 726   for (Flag* current = &flagTable[0]; current->_name != NULL; current++) {
 727     score = str_similar(current->_name, name, length);
 728     if (score > max_score) {
 729       max_score = score;
 730       match = current;
 731     }
 732   }
 733 
 734   if (!(match->is_unlocked() || match->is_unlocker())) {
 735     if (!allow_locked) {
 736       return NULL;
 737     }
 738   }
 739 
 740   if (max_score < VMOptionsFuzzyMatchSimilarity) {
 741     return NULL;
 742   }
 743 
 744   return match;
 745 }
 746 
 747 // Returns the address of the index'th element
 748 static Flag* address_of_flag(CommandLineFlagWithType flag) {
 749   assert((size_t)flag < Flag::numFlags, "bad command line flag index");
 750   return &Flag::flags[flag];
 751 }
 752 
 753 bool CommandLineFlagsEx::is_default(CommandLineFlag flag) {
 754   assert((size_t)flag < Flag::numFlags, "bad command line flag index");
 755   Flag* f = &Flag::flags[flag];
 756   return f->is_default();
 757 }
 758 
 759 bool CommandLineFlagsEx::is_ergo(CommandLineFlag flag) {
 760   assert((size_t)flag < Flag::numFlags, "bad command line flag index");
 761   Flag* f = &Flag::flags[flag];
 762   return f->is_ergonomic();
 763 }
 764 
 765 bool CommandLineFlagsEx::is_cmdline(CommandLineFlag flag) {
 766   assert((size_t)flag < Flag::numFlags, "bad command line flag index");
 767   Flag* f = &Flag::flags[flag];
 768   return f->is_command_line();
 769 }
 770 
 771 bool CommandLineFlags::wasSetOnCmdline(const char* name, bool* value) {
 772   Flag* result = Flag::find_flag((char*)name, strlen(name));
 773   if (result == NULL) return false;
 774   *value = result->is_command_line();
 775   return true;
 776 }
 777 
 778 template<class E, class T>
 779 static void trace_flag_changed(const char* name, const T old_value, const T new_value, const Flag::Flags origin) {
 780   E e;
 781   e.set_name(name);
 782   e.set_old_value(old_value);
 783   e.set_new_value(new_value);
 784   e.set_origin(origin);
 785   e.commit();
 786 }
 787 
 788 static Flag::Error apply_constraint_and_check_range_bool(const char* name, bool new_value, bool verbose) {
 789   Flag::Error status = Flag::SUCCESS;
 790   CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
 791   if (constraint != NULL) {
 792     status = constraint->apply_bool(new_value, verbose);
 793   }
 794   return status;
 795 }
 796 
 797 Flag::Error CommandLineFlags::boolAt(const char* name, size_t len, bool* value, bool allow_locked, bool return_flag) {
 798   Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
 799   if (result == NULL) return Flag::INVALID_FLAG;
 800   if (!result->is_bool()) return Flag::WRONG_FORMAT;
 801   *value = result->get_bool();
 802   return Flag::SUCCESS;
 803 }
 804 
 805 Flag::Error CommandLineFlags::boolAtPut(Flag* flag, bool* value, Flag::Flags origin) {
 806   const char* name;
 807   if (flag == NULL) return Flag::INVALID_FLAG;
 808   if (!flag->is_bool()) return Flag::WRONG_FORMAT;
 809   name = flag->_name;
 810   Flag::Error check = apply_constraint_and_check_range_bool(name, *value, !CommandLineFlagConstraintList::validated_after_ergo());
 811   if (check != Flag::SUCCESS) return check;
 812   bool old_value = flag->get_bool();
 813   trace_flag_changed<EventBooleanFlagChanged, bool>(name, old_value, *value, origin);
 814   flag->set_bool(*value);
 815   *value = old_value;
 816   flag->set_origin(origin);
 817   return Flag::SUCCESS;
 818 }
 819 
 820 Flag::Error CommandLineFlags::boolAtPut(const char* name, size_t len, bool* value, Flag::Flags origin) {
 821   Flag* result = Flag::find_flag(name, len);
 822   return boolAtPut(result, value, origin);
 823 }
 824 
 825 Flag::Error CommandLineFlagsEx::boolAtPut(CommandLineFlagWithType flag, bool value, Flag::Flags origin) {
 826   Flag* faddr = address_of_flag(flag);
 827   guarantee(faddr != NULL && faddr->is_bool(), "wrong flag type");
 828   return CommandLineFlags::boolAtPut(faddr, &value, origin);
 829 }
 830 
 831 static Flag::Error apply_constraint_and_check_range_int(const char* name, int new_value, bool verbose) {
 832   Flag::Error status = Flag::SUCCESS;
 833   CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
 834   if (range != NULL) {
 835     status = range->check_int(new_value, verbose);
 836   }
 837   if (status == Flag::SUCCESS) {
 838     CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
 839     if (constraint != NULL) {
 840       status = constraint->apply_int(new_value, verbose);
 841     }
 842   }
 843   return status;
 844 }
 845 
 846 Flag::Error CommandLineFlags::intAt(const char* name, size_t len, int* value, bool allow_locked, bool return_flag) {
 847   Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
 848   if (result == NULL) return Flag::INVALID_FLAG;
 849   if (!result->is_int()) return Flag::WRONG_FORMAT;
 850   *value = result->get_int();
 851   return Flag::SUCCESS;
 852 }
 853 
 854 Flag::Error CommandLineFlags::intAtPut(Flag* flag, int* value, Flag::Flags origin) {
 855   const char* name;
 856   if (flag == NULL) return Flag::INVALID_FLAG;
 857   if (!flag->is_int()) return Flag::WRONG_FORMAT;
 858   name = flag->_name;
 859   Flag::Error check = apply_constraint_and_check_range_int(name, *value, !CommandLineFlagConstraintList::validated_after_ergo());
 860   if (check != Flag::SUCCESS) return check;
 861   int old_value = flag->get_int();
 862   trace_flag_changed<EventIntFlagChanged, s4>(name, old_value, *value, origin);
 863   flag->set_int(*value);
 864   *value = old_value;
 865   flag->set_origin(origin);
 866   return Flag::SUCCESS;
 867 }
 868 
 869 Flag::Error CommandLineFlags::intAtPut(const char* name, size_t len, int* value, Flag::Flags origin) {
 870   Flag* result = Flag::find_flag(name, len);
 871   return intAtPut(result, value, origin);
 872 }
 873 
 874 Flag::Error CommandLineFlagsEx::intAtPut(CommandLineFlagWithType flag, int value, Flag::Flags origin) {
 875   Flag* faddr = address_of_flag(flag);
 876   guarantee(faddr != NULL && faddr->is_int(), "wrong flag type");
 877   return CommandLineFlags::intAtPut(faddr, &value, origin);
 878 }
 879 
 880 static Flag::Error apply_constraint_and_check_range_uint(const char* name, uint new_value, bool verbose) {
 881   Flag::Error status = Flag::SUCCESS;
 882   CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
 883   if (range != NULL) {
 884     status = range->check_uint(new_value, verbose);
 885   }
 886   if (status == Flag::SUCCESS) {
 887     CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
 888     if (constraint != NULL) {
 889       status = constraint->apply_uint(new_value, verbose);
 890     }
 891   }
 892   return status;
 893 }
 894 
 895 Flag::Error CommandLineFlags::uintAt(const char* name, size_t len, uint* value, bool allow_locked, bool return_flag) {
 896   Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
 897   if (result == NULL) return Flag::INVALID_FLAG;
 898   if (!result->is_uint()) return Flag::WRONG_FORMAT;
 899   *value = result->get_uint();
 900   return Flag::SUCCESS;
 901 }
 902 
 903 Flag::Error CommandLineFlags::uintAtPut(Flag* flag, uint* value, Flag::Flags origin) {
 904   const char* name;
 905   if (flag == NULL) return Flag::INVALID_FLAG;
 906   if (!flag->is_uint()) return Flag::WRONG_FORMAT;
 907   name = flag->_name;
 908   Flag::Error check = apply_constraint_and_check_range_uint(name, *value, !CommandLineFlagConstraintList::validated_after_ergo());
 909   if (check != Flag::SUCCESS) return check;
 910   uint old_value = flag->get_uint();
 911   trace_flag_changed<EventUnsignedIntFlagChanged, u4>(name, old_value, *value, origin);
 912   flag->set_uint(*value);
 913   *value = old_value;
 914   flag->set_origin(origin);
 915   return Flag::SUCCESS;
 916 }
 917 
 918 Flag::Error CommandLineFlags::uintAtPut(const char* name, size_t len, uint* value, Flag::Flags origin) {
 919   Flag* result = Flag::find_flag(name, len);
 920   return uintAtPut(result, value, origin);
 921 }
 922 
 923 Flag::Error CommandLineFlagsEx::uintAtPut(CommandLineFlagWithType flag, uint value, Flag::Flags origin) {
 924   Flag* faddr = address_of_flag(flag);
 925   guarantee(faddr != NULL && faddr->is_uint(), "wrong flag type");
 926   return CommandLineFlags::uintAtPut(faddr, &value, origin);
 927 }
 928 
 929 Flag::Error CommandLineFlags::intxAt(const char* name, size_t len, intx* value, bool allow_locked, bool return_flag) {
 930   Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
 931   if (result == NULL) return Flag::INVALID_FLAG;
 932   if (!result->is_intx()) return Flag::WRONG_FORMAT;
 933   *value = result->get_intx();
 934   return Flag::SUCCESS;
 935 }
 936 
 937 static Flag::Error apply_constraint_and_check_range_intx(const char* name, intx new_value, bool verbose) {
 938   Flag::Error status = Flag::SUCCESS;
 939   CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
 940   if (range != NULL) {
 941     status = range->check_intx(new_value, verbose);
 942   }
 943   if (status == Flag::SUCCESS) {
 944     CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
 945     if (constraint != NULL) {
 946       status = constraint->apply_intx(new_value, verbose);
 947     }
 948   }
 949   return status;
 950 }
 951 
 952 Flag::Error CommandLineFlags::intxAtPut(Flag* flag, intx* value, Flag::Flags origin) {
 953   const char* name;
 954   if (flag == NULL) return Flag::INVALID_FLAG;
 955   if (!flag->is_intx()) return Flag::WRONG_FORMAT;
 956   name = flag->_name;
 957   Flag::Error check = apply_constraint_and_check_range_intx(name, *value, !CommandLineFlagConstraintList::validated_after_ergo());
 958   if (check != Flag::SUCCESS) return check;
 959   intx old_value = flag->get_intx();
 960   trace_flag_changed<EventLongFlagChanged, intx>(name, old_value, *value, origin);
 961   flag->set_intx(*value);
 962   *value = old_value;
 963   flag->set_origin(origin);
 964   return Flag::SUCCESS;
 965 }
 966 
 967 Flag::Error CommandLineFlags::intxAtPut(const char* name, size_t len, intx* value, Flag::Flags origin) {
 968   Flag* result = Flag::find_flag(name, len);
 969   return intxAtPut(result, value, origin);
 970 }
 971 
 972 Flag::Error CommandLineFlagsEx::intxAtPut(CommandLineFlagWithType flag, intx value, Flag::Flags origin) {
 973   Flag* faddr = address_of_flag(flag);
 974   guarantee(faddr != NULL && faddr->is_intx(), "wrong flag type");
 975   return CommandLineFlags::intxAtPut(faddr, &value, origin);
 976 }
 977 
 978 Flag::Error CommandLineFlags::uintxAt(const char* name, size_t len, uintx* value, bool allow_locked, bool return_flag) {
 979   Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
 980   if (result == NULL) return Flag::INVALID_FLAG;
 981   if (!result->is_uintx()) return Flag::WRONG_FORMAT;
 982   *value = result->get_uintx();
 983   return Flag::SUCCESS;
 984 }
 985 
 986 static Flag::Error apply_constraint_and_check_range_uintx(const char* name, uintx new_value, bool verbose) {
 987   Flag::Error status = Flag::SUCCESS;
 988   CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
 989   if (range != NULL) {
 990     status = range->check_uintx(new_value, verbose);
 991   }
 992   if (status == Flag::SUCCESS) {
 993     CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
 994     if (constraint != NULL) {
 995       status = constraint->apply_uintx(new_value, verbose);
 996     }
 997   }
 998   return status;
 999 }
1000 
1001 Flag::Error CommandLineFlags::uintxAtPut(Flag* flag, uintx* value, Flag::Flags origin) {
1002   const char* name;
1003   if (flag == NULL) return Flag::INVALID_FLAG;
1004   if (!flag->is_uintx()) return Flag::WRONG_FORMAT;
1005   name = flag->_name;
1006   Flag::Error check = apply_constraint_and_check_range_uintx(name, *value, !CommandLineFlagConstraintList::validated_after_ergo());
1007   if (check != Flag::SUCCESS) return check;
1008   uintx old_value = flag->get_uintx();
1009   trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
1010   flag->set_uintx(*value);
1011   *value = old_value;
1012   flag->set_origin(origin);
1013   return Flag::SUCCESS;
1014 }
1015 
1016 Flag::Error CommandLineFlags::uintxAtPut(const char* name, size_t len, uintx* value, Flag::Flags origin) {
1017   Flag* result = Flag::find_flag(name, len);
1018   return uintxAtPut(result, value, origin);
1019 }
1020 
1021 Flag::Error CommandLineFlagsEx::uintxAtPut(CommandLineFlagWithType flag, uintx value, Flag::Flags origin) {
1022   Flag* faddr = address_of_flag(flag);
1023   guarantee(faddr != NULL && faddr->is_uintx(), "wrong flag type");
1024   return CommandLineFlags::uintxAtPut(faddr, &value, origin);
1025 }
1026 
1027 Flag::Error CommandLineFlags::uint64_tAt(const char* name, size_t len, uint64_t* value, bool allow_locked, bool return_flag) {
1028   Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
1029   if (result == NULL) return Flag::INVALID_FLAG;
1030   if (!result->is_uint64_t()) return Flag::WRONG_FORMAT;
1031   *value = result->get_uint64_t();
1032   return Flag::SUCCESS;
1033 }
1034 
1035 static Flag::Error apply_constraint_and_check_range_uint64_t(const char* name, uint64_t new_value, bool verbose) {
1036   Flag::Error status = Flag::SUCCESS;
1037   CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
1038   if (range != NULL) {
1039     status = range->check_uint64_t(new_value, verbose);
1040   }
1041   if (status == Flag::SUCCESS) {
1042     CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
1043     if (constraint != NULL) {
1044       status = constraint->apply_uint64_t(new_value, verbose);
1045     }
1046   }
1047   return status;
1048 }
1049 
1050 Flag::Error CommandLineFlags::uint64_tAtPut(Flag* flag, uint64_t* value, Flag::Flags origin) {
1051   const char* name;
1052   if (flag == NULL) return Flag::INVALID_FLAG;
1053   if (!flag->is_uint64_t()) return Flag::WRONG_FORMAT;
1054   name = flag->_name;
1055   Flag::Error check = apply_constraint_and_check_range_uint64_t(name, *value, !CommandLineFlagConstraintList::validated_after_ergo());
1056   if (check != Flag::SUCCESS) return check;
1057   uint64_t old_value = flag->get_uint64_t();
1058   trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
1059   flag->set_uint64_t(*value);
1060   *value = old_value;
1061   flag->set_origin(origin);
1062   return Flag::SUCCESS;
1063 }
1064 
1065 Flag::Error CommandLineFlags::uint64_tAtPut(const char* name, size_t len, uint64_t* value, Flag::Flags origin) {
1066   Flag* result = Flag::find_flag(name, len);
1067   return uint64_tAtPut(result, value, origin);
1068 }
1069 
1070 Flag::Error CommandLineFlagsEx::uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, Flag::Flags origin) {
1071   Flag* faddr = address_of_flag(flag);
1072   guarantee(faddr != NULL && faddr->is_uint64_t(), "wrong flag type");
1073   return CommandLineFlags::uint64_tAtPut(faddr, &value, origin);
1074 }
1075 
1076 Flag::Error CommandLineFlags::size_tAt(const char* name, size_t len, size_t* value, bool allow_locked, bool return_flag) {
1077   Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
1078   if (result == NULL) return Flag::INVALID_FLAG;
1079   if (!result->is_size_t()) return Flag::WRONG_FORMAT;
1080   *value = result->get_size_t();
1081   return Flag::SUCCESS;
1082 }
1083 
1084 static Flag::Error apply_constraint_and_check_range_size_t(const char* name, size_t new_value, bool verbose) {
1085   Flag::Error status = Flag::SUCCESS;
1086   CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
1087   if (range != NULL) {
1088     status = range->check_size_t(new_value, verbose);
1089   }
1090   if (status == Flag::SUCCESS) {
1091     CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
1092     if (constraint != NULL) {
1093       status = constraint->apply_size_t(new_value, verbose);
1094     }
1095   }
1096   return status;
1097 }
1098 
1099 
1100 Flag::Error CommandLineFlags::size_tAtPut(Flag* flag, size_t* value, Flag::Flags origin) {
1101   const char* name;
1102   if (flag == NULL) return Flag::INVALID_FLAG;
1103   if (!flag->is_size_t()) return Flag::WRONG_FORMAT;
1104   name = flag->_name;
1105   Flag::Error check = apply_constraint_and_check_range_size_t(name, *value, !CommandLineFlagConstraintList::validated_after_ergo());
1106   if (check != Flag::SUCCESS) return check;
1107   size_t old_value = flag->get_size_t();
1108   trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
1109   flag->set_size_t(*value);
1110   *value = old_value;
1111   flag->set_origin(origin);
1112   return Flag::SUCCESS;
1113 }
1114 
1115 Flag::Error CommandLineFlags::size_tAtPut(const char* name, size_t len, size_t* value, Flag::Flags origin) {
1116   Flag* result = Flag::find_flag(name, len);
1117   return size_tAtPut(result, value, origin);
1118 }
1119 
1120 Flag::Error CommandLineFlagsEx::size_tAtPut(CommandLineFlagWithType flag, size_t value, Flag::Flags origin) {
1121   Flag* faddr = address_of_flag(flag);
1122   guarantee(faddr != NULL && faddr->is_size_t(), "wrong flag type");
1123   return CommandLineFlags::size_tAtPut(faddr, &value, origin);
1124 }
1125 
1126 Flag::Error CommandLineFlags::doubleAt(const char* name, size_t len, double* value, bool allow_locked, bool return_flag) {
1127   Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
1128   if (result == NULL) return Flag::INVALID_FLAG;
1129   if (!result->is_double()) return Flag::WRONG_FORMAT;
1130   *value = result->get_double();
1131   return Flag::SUCCESS;
1132 }
1133 
1134 static Flag::Error apply_constraint_and_check_range_double(const char* name, double new_value, bool verbose) {
1135   Flag::Error status = Flag::SUCCESS;
1136   CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
1137   if (range != NULL) {
1138     status = range->check_double(new_value, verbose);
1139   }
1140   if (status == Flag::SUCCESS) {
1141     CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find_if_needs_check(name);
1142     if (constraint != NULL) {
1143       status = constraint->apply_double(new_value, verbose);
1144     }
1145   }
1146   return status;
1147 }
1148 
1149 Flag::Error CommandLineFlags::doubleAtPut(Flag* flag, double* value, Flag::Flags origin) {
1150   const char* name;
1151   if (flag == NULL) return Flag::INVALID_FLAG;
1152   if (!flag->is_double()) return Flag::WRONG_FORMAT;
1153   name = flag->_name;
1154   Flag::Error check = apply_constraint_and_check_range_double(name, *value, !CommandLineFlagConstraintList::validated_after_ergo());
1155   if (check != Flag::SUCCESS) return check;
1156   double old_value = flag->get_double();
1157   trace_flag_changed<EventDoubleFlagChanged, double>(name, old_value, *value, origin);
1158   flag->set_double(*value);
1159   *value = old_value;
1160   flag->set_origin(origin);
1161   return Flag::SUCCESS;
1162 }
1163 
1164 Flag::Error CommandLineFlags::doubleAtPut(const char* name, size_t len, double* value, Flag::Flags origin) {
1165   Flag* result = Flag::find_flag(name, len);
1166   return doubleAtPut(result, value, origin);
1167 }
1168 
1169 Flag::Error CommandLineFlagsEx::doubleAtPut(CommandLineFlagWithType flag, double value, Flag::Flags origin) {
1170   Flag* faddr = address_of_flag(flag);
1171   guarantee(faddr != NULL && faddr->is_double(), "wrong flag type");
1172   return CommandLineFlags::doubleAtPut(faddr, &value, origin);
1173 }
1174 
1175 Flag::Error CommandLineFlags::ccstrAt(const char* name, size_t len, ccstr* value, bool allow_locked, bool return_flag) {
1176   Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
1177   if (result == NULL) return Flag::INVALID_FLAG;
1178   if (!result->is_ccstr()) return Flag::WRONG_FORMAT;
1179   *value = result->get_ccstr();
1180   return Flag::SUCCESS;
1181 }
1182 
1183 Flag::Error CommandLineFlags::ccstrAtPut(const char* name, size_t len, ccstr* value, Flag::Flags origin) {
1184   Flag* result = Flag::find_flag(name, len);
1185   if (result == NULL) return Flag::INVALID_FLAG;
1186   if (!result->is_ccstr()) return Flag::WRONG_FORMAT;
1187   ccstr old_value = result->get_ccstr();
1188   trace_flag_changed<EventStringFlagChanged, const char*>(name, old_value, *value, origin);
1189   char* new_value = NULL;
1190   if (*value != NULL) {
1191     new_value = os::strdup_check_oom(*value);
1192   }
1193   result->set_ccstr(new_value);
1194   if (result->is_default() && old_value != NULL) {
1195     // Prior value is NOT heap allocated, but was a literal constant.
1196     old_value = os::strdup_check_oom(old_value);
1197   }
1198   *value = old_value;
1199   result->set_origin(origin);
1200   return Flag::SUCCESS;
1201 }
1202 
1203 Flag::Error CommandLineFlagsEx::ccstrAtPut(CommandLineFlagWithType flag, ccstr value, Flag::Flags origin) {
1204   Flag* faddr = address_of_flag(flag);
1205   guarantee(faddr != NULL && faddr->is_ccstr(), "wrong flag type");
1206   ccstr old_value = faddr->get_ccstr();
1207   trace_flag_changed<EventStringFlagChanged, const char*>(faddr->_name, old_value, value, origin);
1208   char* new_value = os::strdup_check_oom(value);
1209   faddr->set_ccstr(new_value);
1210   if (!faddr->is_default() && old_value != NULL) {
1211     // Prior value is heap allocated so free it.
1212     FREE_C_HEAP_ARRAY(char, old_value);
1213   }
1214   faddr->set_origin(origin);
1215   return Flag::SUCCESS;
1216 }
1217 
1218 extern "C" {
1219   static int compare_flags(const void* void_a, const void* void_b) {
1220     return strcmp((*((Flag**) void_a))->_name, (*((Flag**) void_b))->_name);
1221   }
1222 }
1223 
1224 void CommandLineFlags::printSetFlags(outputStream* out) {
1225   // Print which flags were set on the command line
1226   // note: this method is called before the thread structure is in place
1227   //       which means resource allocation cannot be used.
1228 
1229   // The last entry is the null entry.
1230   const size_t length = Flag::numFlags - 1;
1231 
1232   // Sort
1233   Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtInternal);
1234   for (size_t i = 0; i < length; i++) {
1235     array[i] = &flagTable[i];
1236   }
1237   qsort(array, length, sizeof(Flag*), compare_flags);
1238 
1239   // Print
1240   for (size_t i = 0; i < length; i++) {
1241     if (array[i]->get_origin() /* naked field! */) {
1242       array[i]->print_as_flag(out);
1243       out->print(" ");
1244     }
1245   }
1246   out->cr();
1247   FREE_C_HEAP_ARRAY(Flag*, array);
1248 }
1249 
1250 #ifndef PRODUCT
1251 
1252 void CommandLineFlags::verify() {
1253   assert(Arguments::check_vm_args_consistency(), "Some flag settings conflict");
1254 }
1255 
1256 #endif // PRODUCT
1257 
1258 #define ONLY_PRINT_PRODUCT_FLAGS
1259 
1260 void CommandLineFlags::printFlags(outputStream* out, bool withComments, bool printRanges) {
1261   // Print the flags sorted by name
1262   // note: this method is called before the thread structure is in place
1263   //       which means resource allocation cannot be used.
1264 
1265   // The last entry is the null entry.
1266   const size_t length = Flag::numFlags - 1;
1267 
1268   // Sort
1269   Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtInternal);
1270   for (size_t i = 0; i < length; i++) {
1271     array[i] = &flagTable[i];
1272   }
1273   qsort(array, length, sizeof(Flag*), compare_flags);
1274 
1275   // Print
1276   if (!printRanges) {
1277     out->print_cr("[Global flags]");
1278   } else {
1279     out->print_cr("[Global flags ranges]");
1280   }
1281 
1282   for (size_t i = 0; i < length; i++) {
1283     if (array[i]->is_unlocked()) {
1284 #ifdef ONLY_PRINT_PRODUCT_FLAGS
1285       if (!array[i]->is_notproduct() && !array[i]->is_develop())
1286 #endif // ONLY_PRINT_PRODUCT_FLAGS
1287       array[i]->print_on(out, withComments, printRanges);
1288     }
1289   }
1290   FREE_C_HEAP_ARRAY(Flag*, array);
1291 }