1 /*
   2  * Copyright (c) 1997, 2014, 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 #if INCLUDE_JFR
  27 #include "jfr/jfrEvents.hpp"
  28 #endif
  29 #include "memory/allocation.inline.hpp"
  30 #include "oops/oop.inline.hpp"
  31 #include "runtime/arguments.hpp"
  32 #include "runtime/globals.hpp"
  33 #include "runtime/globals_extension.hpp"
  34 #include "utilities/ostream.hpp"
  35 #include "utilities/macros.hpp"
  36 #include "utilities/top.hpp"
  37 #if INCLUDE_ALL_GCS
  38 #include "gc_implementation/g1/g1_globals.hpp"
  39 #endif // INCLUDE_ALL_GCS
  40 #ifdef COMPILER1
  41 #include "c1/c1_globals.hpp"
  42 #endif
  43 #ifdef COMPILER2
  44 #include "opto/c2_globals.hpp"
  45 #endif
  46 #ifdef SHARK
  47 #include "shark/shark_globals.hpp"
  48 #endif
  49 
  50 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
  51 
  52 RUNTIME_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, \
  53               MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, \
  54               MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_EXPERIMENTAL_FLAG, \
  55               MATERIALIZE_NOTPRODUCT_FLAG, \
  56               MATERIALIZE_MANAGEABLE_FLAG, MATERIALIZE_PRODUCT_RW_FLAG, \
  57               MATERIALIZE_LP64_PRODUCT_FLAG)
  58 
  59 RUNTIME_OS_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, \
  60                  MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, \
  61                  MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_NOTPRODUCT_FLAG)
  62 
  63 ARCH_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, \
  64            MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_EXPERIMENTAL_FLAG, \
  65            MATERIALIZE_NOTPRODUCT_FLAG)
  66 
  67 MATERIALIZE_FLAGS_EXT
  68 
  69 
  70 static bool is_product_build() {
  71 #ifdef PRODUCT
  72   return true;
  73 #else
  74   return false;
  75 #endif
  76 }
  77 
  78 void Flag::check_writable() {
  79   if (is_constant_in_binary()) {
  80     fatal(err_msg("flag is constant: %s", _name));
  81   }
  82 }
  83 
  84 bool Flag::is_bool() const {
  85   return strcmp(_type, "bool") == 0;
  86 }
  87 
  88 bool Flag::get_bool() const {
  89   return *((bool*) _addr);
  90 }
  91 
  92 void Flag::set_bool(bool value) {
  93   check_writable();
  94   *((bool*) _addr) = value;
  95 }
  96 
  97 bool Flag::is_intx() const {
  98   return strcmp(_type, "intx")  == 0;
  99 }
 100 
 101 intx Flag::get_intx() const {
 102   return *((intx*) _addr);
 103 }
 104 
 105 void Flag::set_intx(intx value) {
 106   check_writable();
 107   *((intx*) _addr) = value;
 108 }
 109 
 110 bool Flag::is_uintx() const {
 111   return strcmp(_type, "uintx") == 0;
 112 }
 113 
 114 uintx Flag::get_uintx() const {
 115   return *((uintx*) _addr);
 116 }
 117 
 118 void Flag::set_uintx(uintx value) {
 119   check_writable();
 120   *((uintx*) _addr) = value;
 121 }
 122 
 123 bool Flag::is_uint64_t() const {
 124   return strcmp(_type, "uint64_t") == 0;
 125 }
 126 
 127 uint64_t Flag::get_uint64_t() const {
 128   return *((uint64_t*) _addr);
 129 }
 130 
 131 void Flag::set_uint64_t(uint64_t value) {
 132   check_writable();
 133   *((uint64_t*) _addr) = value;
 134 }
 135 
 136 bool Flag::is_double() const {
 137   return strcmp(_type, "double") == 0;
 138 }
 139 
 140 double Flag::get_double() const {
 141   return *((double*) _addr);
 142 }
 143 
 144 void Flag::set_double(double value) {
 145   check_writable();
 146   *((double*) _addr) = value;
 147 }
 148 
 149 bool Flag::is_ccstr() const {
 150   return strcmp(_type, "ccstr") == 0 || strcmp(_type, "ccstrlist") == 0;
 151 }
 152 
 153 bool Flag::ccstr_accumulates() const {
 154   return strcmp(_type, "ccstrlist") == 0;
 155 }
 156 
 157 ccstr Flag::get_ccstr() const {
 158   return *((ccstr*) _addr);
 159 }
 160 
 161 void Flag::set_ccstr(ccstr value) {
 162   check_writable();
 163   *((ccstr*) _addr) = value;
 164 }
 165 
 166 
 167 Flag::Flags Flag::get_origin() {
 168   return Flags(_flags & VALUE_ORIGIN_MASK);
 169 }
 170 
 171 void Flag::set_origin(Flags origin) {
 172   assert((origin & VALUE_ORIGIN_MASK) == origin, "sanity");
 173   _flags = Flags((_flags & ~VALUE_ORIGIN_MASK) | origin);
 174 }
 175 
 176 bool Flag::is_default() {
 177   return (get_origin() == DEFAULT);
 178 }
 179 
 180 bool Flag::is_ergonomic() {
 181   return (get_origin() == ERGONOMIC);
 182 }
 183 
 184 bool Flag::is_command_line() {
 185   return (get_origin() == COMMAND_LINE);
 186 }
 187 
 188 bool Flag::is_product() const {
 189   return (_flags & KIND_PRODUCT) != 0;
 190 }
 191 
 192 bool Flag::is_manageable() const {
 193   return (_flags & KIND_MANAGEABLE) != 0;
 194 }
 195 
 196 bool Flag::is_diagnostic() const {
 197   return (_flags & KIND_DIAGNOSTIC) != 0;
 198 }
 199 
 200 bool Flag::is_experimental() const {
 201   return (_flags & KIND_EXPERIMENTAL) != 0;
 202 }
 203 
 204 bool Flag::is_notproduct() const {
 205   return (_flags & KIND_NOT_PRODUCT) != 0;
 206 }
 207 
 208 bool Flag::is_develop() const {
 209   return (_flags & KIND_DEVELOP) != 0;
 210 }
 211 
 212 bool Flag::is_read_write() const {
 213   return (_flags & KIND_READ_WRITE) != 0;
 214 }
 215 
 216 bool Flag::is_commercial() const {
 217   return (_flags & KIND_COMMERCIAL) != 0;
 218 }
 219 
 220 /**
 221  * Returns if this flag is a constant in the binary.  Right now this is
 222  * true for notproduct and develop flags in product builds.
 223  */
 224 bool Flag::is_constant_in_binary() const {
 225 #ifdef PRODUCT
 226     return is_notproduct() || is_develop();
 227 #else
 228     return false;
 229 #endif
 230 }
 231 
 232 bool Flag::is_unlocker() const {
 233   return strcmp(_name, "UnlockDiagnosticVMOptions") == 0     ||
 234          strcmp(_name, "UnlockExperimentalVMOptions") == 0   ||
 235          is_unlocker_ext();
 236 }
 237 
 238 bool Flag::is_unlocked() const {
 239   if (is_diagnostic()) {
 240     return UnlockDiagnosticVMOptions;
 241   }
 242   if (is_experimental()) {
 243     return UnlockExperimentalVMOptions;
 244   }
 245   return is_unlocked_ext();
 246 }
 247 
 248 void Flag::unlock_diagnostic() {
 249   assert(is_diagnostic(), "sanity");
 250   _flags = Flags(_flags & ~KIND_DIAGNOSTIC);
 251 }
 252 
 253 // Get custom message for this locked flag, or return NULL if
 254 // none is available.
 255 void Flag::get_locked_message(char* buf, int buflen) const {
 256   buf[0] = '\0';
 257   if (is_diagnostic() && !is_unlocked()) {
 258     jio_snprintf(buf, buflen, "Error: VM option '%s' is diagnostic and must be enabled via -XX:+UnlockDiagnosticVMOptions.\n",
 259                  _name);
 260     return;
 261   }
 262   if (is_experimental() && !is_unlocked()) {
 263     jio_snprintf(buf, buflen, "Error: VM option '%s' is experimental and must be enabled via -XX:+UnlockExperimentalVMOptions.\n",
 264                  _name);
 265     return;
 266   }
 267   if (is_develop() && is_product_build()) {
 268     jio_snprintf(buf, buflen, "Error: VM option '%s' is develop and is available only in debug version of VM.\n",
 269                  _name);
 270     return;
 271   }
 272   if (is_notproduct() && is_product_build()) {
 273     jio_snprintf(buf, buflen, "Error: VM option '%s' is notproduct and is available only in debug version of VM.\n",
 274                  _name);
 275     return;
 276   }
 277   get_locked_message_ext(buf, buflen);
 278 }
 279 
 280 bool Flag::is_writeable() const {
 281   return is_manageable() || (is_product() && is_read_write()) || is_writeable_ext();
 282 }
 283 
 284 // All flags except "manageable" are assumed to be internal flags.
 285 // Long term, we need to define a mechanism to specify which flags
 286 // are external/stable and change this function accordingly.
 287 bool Flag::is_external() const {
 288   return is_manageable() || is_external_ext();
 289 }
 290 
 291 
 292 // Length of format string (e.g. "%.1234s") for printing ccstr below
 293 #define FORMAT_BUFFER_LEN 16
 294 
 295 PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL
 296 void Flag::print_on(outputStream* st, bool withComments) {
 297   // Don't print notproduct and develop flags in a product build.
 298   if (is_constant_in_binary()) {
 299     return;
 300   }
 301 
 302   st->print("%9s %-40s %c= ", _type, _name, (!is_default() ? ':' : ' '));
 303 
 304   if (is_bool()) {
 305     st->print("%-16s", get_bool() ? "true" : "false");
 306   }
 307   if (is_intx()) {
 308     st->print("%-16ld", get_intx());
 309   }
 310   if (is_uintx()) {
 311     st->print("%-16lu", get_uintx());
 312   }
 313   if (is_uint64_t()) {
 314     st->print("%-16lu", get_uint64_t());
 315   }
 316   if (is_double()) {
 317     st->print("%-16f", get_double());
 318   }
 319   if (is_ccstr()) {
 320     const char* cp = get_ccstr();
 321     if (cp != NULL) {
 322       const char* eol;
 323       while ((eol = strchr(cp, '\n')) != NULL) {
 324         char format_buffer[FORMAT_BUFFER_LEN];
 325         size_t llen = pointer_delta(eol, cp, sizeof(char));
 326         jio_snprintf(format_buffer, FORMAT_BUFFER_LEN,
 327             "%%." SIZE_FORMAT "s", llen);
 328 PRAGMA_DIAG_PUSH
 329 PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL
 330         st->print(format_buffer, cp);
 331 PRAGMA_DIAG_POP
 332         st->cr();
 333         cp = eol+1;
 334         st->print("%5s %-35s += ", "", _name);
 335       }
 336       st->print("%-16s", cp);
 337     }
 338     else st->print("%-16s", "");
 339   }
 340 
 341   st->print("%-20s", " ");
 342   print_kind(st);
 343 
 344   if (withComments) {
 345 #ifndef PRODUCT
 346     st->print("%s", _doc);
 347 #endif
 348   }
 349   st->cr();
 350 }
 351 
 352 void Flag::print_kind(outputStream* st) {
 353   struct Data {
 354     int flag;
 355     const char* name;
 356   };
 357 
 358   Data data[] = {
 359       { KIND_C1, "C1" },
 360       { KIND_C2, "C2" },
 361       { KIND_ARCH, "ARCH" },
 362       { KIND_SHARK, "SHARK" },
 363       { KIND_PLATFORM_DEPENDENT, "pd" },
 364       { KIND_PRODUCT, "product" },
 365       { KIND_MANAGEABLE, "manageable" },
 366       { KIND_DIAGNOSTIC, "diagnostic" },
 367       { KIND_EXPERIMENTAL, "experimental" },
 368       { KIND_COMMERCIAL, "commercial" },
 369       { KIND_NOT_PRODUCT, "notproduct" },
 370       { KIND_DEVELOP, "develop" },
 371       { KIND_LP64_PRODUCT, "lp64_product" },
 372       { KIND_READ_WRITE, "rw" },
 373       { -1, "" }
 374   };
 375 
 376   if ((_flags & KIND_MASK) != 0) {
 377     st->print("{");
 378     bool is_first = true;
 379 
 380     for (int i = 0; data[i].flag != -1; i++) {
 381       Data d = data[i];
 382       if ((_flags & d.flag) != 0) {
 383         if (is_first) {
 384           is_first = false;
 385         } else {
 386           st->print(" ");
 387         }
 388         st->print("%s", d.name);
 389       }
 390     }
 391 
 392     st->print("}");
 393   }
 394 }
 395 
 396 void Flag::print_as_flag(outputStream* st) {
 397   if (is_bool()) {
 398     st->print("-XX:%s%s", get_bool() ? "+" : "-", _name);
 399   } else if (is_intx()) {
 400     st->print("-XX:%s=" INTX_FORMAT, _name, get_intx());
 401   } else if (is_uintx()) {
 402     st->print("-XX:%s=" UINTX_FORMAT, _name, get_uintx());
 403   } else if (is_uint64_t()) {
 404     st->print("-XX:%s=" UINT64_FORMAT, _name, get_uint64_t());
 405   } else if (is_double()) {
 406     st->print("-XX:%s=%f", _name, get_double());
 407   } else if (is_ccstr()) {
 408     st->print("-XX:%s=", _name);
 409     const char* cp = get_ccstr();
 410     if (cp != NULL) {
 411       // Need to turn embedded '\n's back into separate arguments
 412       // Not so efficient to print one character at a time,
 413       // but the choice is to do the transformation to a buffer
 414       // and print that.  And this need not be efficient.
 415       for (; *cp != '\0'; cp += 1) {
 416         switch (*cp) {
 417           default:
 418             st->print("%c", *cp);
 419             break;
 420           case '\n':
 421             st->print(" -XX:%s=", _name);
 422             break;
 423         }
 424       }
 425     }
 426   } else {
 427     ShouldNotReachHere();
 428   }
 429 }
 430 
 431 // 4991491 do not "optimize out" the was_set false values: omitting them
 432 // tickles a Microsoft compiler bug causing flagTable to be malformed
 433 
 434 #define NAME(name) NOT_PRODUCT(&name) PRODUCT_ONLY(&CONST_##name)
 435 
 436 #define RUNTIME_PRODUCT_FLAG_STRUCT(     type, name, value, doc) { #type, XSTR(name), &name,      NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_PRODUCT) },
 437 #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) },
 438 #define RUNTIME_DIAGNOSTIC_FLAG_STRUCT(  type, name, value, doc) { #type, XSTR(name), &name,      NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_DIAGNOSTIC) },
 439 #define RUNTIME_EXPERIMENTAL_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name,      NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_EXPERIMENTAL) },
 440 #define RUNTIME_MANAGEABLE_FLAG_STRUCT(  type, name, value, doc) { #type, XSTR(name), &name,      NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_MANAGEABLE) },
 441 #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) },
 442 #define RUNTIME_DEVELOP_FLAG_STRUCT(     type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_DEVELOP) },
 443 #define RUNTIME_PD_DEVELOP_FLAG_STRUCT(  type, name,        doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_DEVELOP | Flag::KIND_PLATFORM_DEPENDENT) },
 444 #define RUNTIME_NOTPRODUCT_FLAG_STRUCT(  type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_NOT_PRODUCT) },
 445 
 446 #ifdef _LP64
 447 #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) },
 448 #else
 449 #define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) /* flag is constant */
 450 #endif // _LP64
 451 
 452 #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) },
 453 #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) },
 454 #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) },
 455 #define C1_DEVELOP_FLAG_STRUCT(          type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C1 | Flag::KIND_DEVELOP) },
 456 #define C1_PD_DEVELOP_FLAG_STRUCT(       type, name,        doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C1 | Flag::KIND_DEVELOP | Flag::KIND_PLATFORM_DEPENDENT) },
 457 #define C1_NOTPRODUCT_FLAG_STRUCT(       type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C1 | Flag::KIND_NOT_PRODUCT) },
 458 
 459 #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) },
 460 #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) },
 461 #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) },
 462 #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) },
 463 #define C2_DEVELOP_FLAG_STRUCT(          type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_DEVELOP) },
 464 #define C2_PD_DEVELOP_FLAG_STRUCT(       type, name,        doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_DEVELOP | Flag::KIND_PLATFORM_DEPENDENT) },
 465 #define C2_NOTPRODUCT_FLAG_STRUCT(       type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_NOT_PRODUCT) },
 466 
 467 #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) },
 468 #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) },
 469 #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) },
 470 #define ARCH_DEVELOP_FLAG_STRUCT(        type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_ARCH | Flag::KIND_DEVELOP) },
 471 #define ARCH_NOTPRODUCT_FLAG_STRUCT(     type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_ARCH | Flag::KIND_NOT_PRODUCT) },
 472 
 473 #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) },
 474 #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) },
 475 #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) },
 476 #define SHARK_DEVELOP_FLAG_STRUCT(       type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_DEVELOP) },
 477 #define SHARK_PD_DEVELOP_FLAG_STRUCT(    type, name,        doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_DEVELOP | Flag::KIND_PLATFORM_DEPENDENT) },
 478 #define SHARK_NOTPRODUCT_FLAG_STRUCT(    type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_NOT_PRODUCT) },
 479 
 480 static Flag flagTable[] = {
 481  RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_EXPERIMENTAL_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT, RUNTIME_LP64_PRODUCT_FLAG_STRUCT)
 482  RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT)
 483 #if INCLUDE_ALL_GCS
 484  G1_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_EXPERIMENTAL_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT)
 485 #endif // INCLUDE_ALL_GCS
 486 #ifdef COMPILER1
 487  C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, C1_PD_DEVELOP_FLAG_STRUCT, C1_PRODUCT_FLAG_STRUCT, C1_PD_PRODUCT_FLAG_STRUCT, C1_DIAGNOSTIC_FLAG_STRUCT, C1_NOTPRODUCT_FLAG_STRUCT)
 488 #endif
 489 #ifdef COMPILER2
 490  C2_FLAGS(C2_DEVELOP_FLAG_STRUCT, C2_PD_DEVELOP_FLAG_STRUCT, C2_PRODUCT_FLAG_STRUCT, C2_PD_PRODUCT_FLAG_STRUCT, C2_DIAGNOSTIC_FLAG_STRUCT, C2_EXPERIMENTAL_FLAG_STRUCT, C2_NOTPRODUCT_FLAG_STRUCT)
 491 #endif
 492 #ifdef SHARK
 493  SHARK_FLAGS(SHARK_DEVELOP_FLAG_STRUCT, SHARK_PD_DEVELOP_FLAG_STRUCT, SHARK_PRODUCT_FLAG_STRUCT, SHARK_PD_PRODUCT_FLAG_STRUCT, SHARK_DIAGNOSTIC_FLAG_STRUCT, SHARK_NOTPRODUCT_FLAG_STRUCT)
 494 #endif
 495  ARCH_FLAGS(ARCH_DEVELOP_FLAG_STRUCT, ARCH_PRODUCT_FLAG_STRUCT, ARCH_DIAGNOSTIC_FLAG_STRUCT, ARCH_EXPERIMENTAL_FLAG_STRUCT, ARCH_NOTPRODUCT_FLAG_STRUCT)
 496  FLAGTABLE_EXT
 497  {0, NULL, NULL}
 498 };
 499 
 500 Flag* Flag::flags = flagTable;
 501 size_t Flag::numFlags = (sizeof(flagTable) / sizeof(Flag));
 502 
 503 inline bool str_equal(const char* s, const char* q, size_t len) {
 504   // s is null terminated, q is not!
 505   if (strlen(s) != (unsigned int) len) return false;
 506   return strncmp(s, q, len) == 0;
 507 }
 508 
 509 // Search the flag table for a named flag
 510 Flag* Flag::find_flag(const char* name, size_t length, bool allow_locked, bool return_flag) {
 511   for (Flag* current = &flagTable[0]; current->_name != NULL; current++) {
 512     if (str_equal(current->_name, name, length)) {
 513       // Found a matching entry.
 514       // Don't report notproduct and develop flags in product builds.
 515       if (current->is_constant_in_binary()) {
 516         return (return_flag == true ? current : NULL);
 517       }
 518       // Report locked flags only if allowed.
 519       if (!(current->is_unlocked() || current->is_unlocker())) {
 520         if (!allow_locked) {
 521           // disable use of locked flags, e.g. diagnostic, experimental,
 522           // commercial... until they are explicitly unlocked
 523           return NULL;
 524         }
 525       }
 526       return current;
 527     }
 528   }
 529   // Flag name is not in the flag table
 530   return NULL;
 531 }
 532 
 533 // Compute string similarity based on Dice's coefficient
 534 static float str_similar(const char* str1, const char* str2, size_t len2) {
 535   int len1 = (int) strlen(str1);
 536   int total = len1 + (int) len2;
 537 
 538   int hit = 0;
 539 
 540   for (int i = 0; i < len1 -1; ++i) {
 541     for (int j = 0; j < (int) len2 -1; ++j) {
 542       if ((str1[i] == str2[j]) && (str1[i+1] == str2[j+1])) {
 543         ++hit;
 544         break;
 545       }
 546     }
 547   }
 548 
 549   return 2.0f * (float) hit / (float) total;
 550 }
 551 
 552 Flag* Flag::fuzzy_match(const char* name, size_t length, bool allow_locked) {
 553   float VMOptionsFuzzyMatchSimilarity = 0.7f;
 554   Flag* match = NULL;
 555   float score;
 556   float max_score = -1;
 557 
 558   for (Flag* current = &flagTable[0]; current->_name != NULL; current++) {
 559     score = str_similar(current->_name, name, length);
 560     if (score > max_score) {
 561       max_score = score;
 562       match = current;
 563     }
 564   }
 565 
 566   if (!(match->is_unlocked() || match->is_unlocker())) {
 567     if (!allow_locked) {
 568       return NULL;
 569     }
 570   }
 571 
 572   if (max_score < VMOptionsFuzzyMatchSimilarity) {
 573     return NULL;
 574   }
 575 
 576   return match;
 577 }
 578 
 579 // Returns the address of the index'th element
 580 static Flag* address_of_flag(CommandLineFlagWithType flag) {
 581   assert((size_t)flag < Flag::numFlags, "bad command line flag index");
 582   return &Flag::flags[flag];
 583 }
 584 
 585 bool CommandLineFlagsEx::is_default(CommandLineFlag flag) {
 586   assert((size_t)flag < Flag::numFlags, "bad command line flag index");
 587   Flag* f = &Flag::flags[flag];
 588   return f->is_default();
 589 }
 590 
 591 bool CommandLineFlagsEx::is_ergo(CommandLineFlag flag) {
 592   assert((size_t)flag < Flag::numFlags, "bad command line flag index");
 593   Flag* f = &Flag::flags[flag];
 594   return f->is_ergonomic();
 595 }
 596 
 597 bool CommandLineFlagsEx::is_cmdline(CommandLineFlag flag) {
 598   assert((size_t)flag < Flag::numFlags, "bad command line flag index");
 599   Flag* f = &Flag::flags[flag];
 600   return f->is_command_line();
 601 }
 602 
 603 bool CommandLineFlags::wasSetOnCmdline(const char* name, bool* value) {
 604   Flag* result = Flag::find_flag((char*)name, strlen(name));
 605   if (result == NULL) return false;
 606   *value = result->is_command_line();
 607   return true;
 608 }
 609 
 610 template<class E, class T>
 611 static void trace_flag_changed(const char* name, const T old_value, const T new_value, const Flag::Flags origin)
 612 {
 613   E e;
 614   e.set_name(name);
 615   e.set_oldValue(old_value);
 616   e.set_newValue(new_value);
 617   e.set_origin(origin);
 618   e.commit();
 619 }
 620 
 621 bool CommandLineFlags::boolAt(const char* name, size_t len, bool* value, bool allow_locked, bool return_flag) {
 622   Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
 623   if (result == NULL) return false;
 624   if (!result->is_bool()) return false;
 625   *value = result->get_bool();
 626   return true;
 627 }
 628 
 629 bool CommandLineFlags::boolAtPut(const char* name, size_t len, bool* value, Flag::Flags origin) {
 630   Flag* result = Flag::find_flag(name, len);
 631   if (result == NULL) return false;
 632   if (!result->is_bool()) return false;
 633   bool old_value = result->get_bool();
 634 #if INCLUDE_JFR
 635   trace_flag_changed<EventBooleanFlagChanged, bool>(name, old_value, *value, origin);
 636 #endif
 637   result->set_bool(*value);
 638   *value = old_value;
 639   result->set_origin(origin);
 640   return true;
 641 }
 642 
 643 void CommandLineFlagsEx::boolAtPut(CommandLineFlagWithType flag, bool value, Flag::Flags origin) {
 644   Flag* faddr = address_of_flag(flag);
 645   guarantee(faddr != NULL && faddr->is_bool(), "wrong flag type");
 646 #if INCLUDE_JFR
 647   trace_flag_changed<EventBooleanFlagChanged, bool>(faddr->_name, faddr->get_bool(), value, origin);
 648 #endif
 649   faddr->set_bool(value);
 650   faddr->set_origin(origin);
 651 }
 652 
 653 bool CommandLineFlags::intxAt(const char* name, size_t len, intx* value, bool allow_locked, bool return_flag) {
 654   Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
 655   if (result == NULL) return false;
 656   if (!result->is_intx()) return false;
 657   *value = result->get_intx();
 658   return true;
 659 }
 660 
 661 bool CommandLineFlags::intxAtPut(const char* name, size_t len, intx* value, Flag::Flags origin) {
 662   Flag* result = Flag::find_flag(name, len);
 663   if (result == NULL) return false;
 664   if (!result->is_intx()) return false;
 665   intx old_value = result->get_intx();
 666 #if INCLUDE_JFR
 667   trace_flag_changed<EventLongFlagChanged, s8>(name, old_value, *value, origin);
 668 #endif
 669   result->set_intx(*value);
 670   *value = old_value;
 671   result->set_origin(origin);
 672   return true;
 673 }
 674 
 675 void CommandLineFlagsEx::intxAtPut(CommandLineFlagWithType flag, intx value, Flag::Flags origin) {
 676   Flag* faddr = address_of_flag(flag);
 677   guarantee(faddr != NULL && faddr->is_intx(), "wrong flag type");
 678 #if INCLUDE_JFR
 679   trace_flag_changed<EventLongFlagChanged, s8>(faddr->_name, faddr->get_intx(), value, origin);
 680 #endif
 681   faddr->set_intx(value);
 682   faddr->set_origin(origin);
 683 }
 684 
 685 bool CommandLineFlags::uintxAt(const char* name, size_t len, uintx* value, bool allow_locked, bool return_flag) {
 686   Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
 687   if (result == NULL) return false;
 688   if (!result->is_uintx()) return false;
 689   *value = result->get_uintx();
 690   return true;
 691 }
 692 
 693 bool CommandLineFlags::uintxAtPut(const char* name, size_t len, uintx* value, Flag::Flags origin) {
 694   Flag* result = Flag::find_flag(name, len);
 695   if (result == NULL) return false;
 696   if (!result->is_uintx()) return false;
 697   uintx old_value = result->get_uintx();
 698 #if INCLUDE_JFR
 699   trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
 700 #endif
 701   result->set_uintx(*value);
 702   *value = old_value;
 703   result->set_origin(origin);
 704   return true;
 705 }
 706 
 707 void CommandLineFlagsEx::uintxAtPut(CommandLineFlagWithType flag, uintx value, Flag::Flags origin) {
 708   Flag* faddr = address_of_flag(flag);
 709   guarantee(faddr != NULL && faddr->is_uintx(), "wrong flag type");
 710 #if INCLUDE_JFR
 711   trace_flag_changed<EventUnsignedLongFlagChanged, u8>(faddr->_name, faddr->get_uintx(), value, origin);
 712 #endif
 713   faddr->set_uintx(value);
 714   faddr->set_origin(origin);
 715 }
 716 
 717 bool CommandLineFlags::uint64_tAt(const char* name, size_t len, uint64_t* value, bool allow_locked, bool return_flag) {
 718   Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
 719   if (result == NULL) return false;
 720   if (!result->is_uint64_t()) return false;
 721   *value = result->get_uint64_t();
 722   return true;
 723 }
 724 
 725 bool CommandLineFlags::uint64_tAtPut(const char* name, size_t len, uint64_t* value, Flag::Flags origin) {
 726   Flag* result = Flag::find_flag(name, len);
 727   if (result == NULL) return false;
 728   if (!result->is_uint64_t()) return false;
 729   uint64_t old_value = result->get_uint64_t();
 730 #if INCLUDE_JFR
 731   trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
 732 #endif
 733   result->set_uint64_t(*value);
 734   *value = old_value;
 735   result->set_origin(origin);
 736   return true;
 737 }
 738 
 739 void CommandLineFlagsEx::uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, Flag::Flags origin) {
 740   Flag* faddr = address_of_flag(flag);
 741   guarantee(faddr != NULL && faddr->is_uint64_t(), "wrong flag type");
 742 #if INCLUDE_JFR
 743   trace_flag_changed<EventUnsignedLongFlagChanged, u8>(faddr->_name, faddr->get_uint64_t(), value, origin);
 744 #endif
 745   faddr->set_uint64_t(value);
 746   faddr->set_origin(origin);
 747 }
 748 
 749 bool CommandLineFlags::doubleAt(const char* name, size_t len, double* value, bool allow_locked, bool return_flag) {
 750   Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
 751   if (result == NULL) return false;
 752   if (!result->is_double()) return false;
 753   *value = result->get_double();
 754   return true;
 755 }
 756 
 757 bool CommandLineFlags::doubleAtPut(const char* name, size_t len, double* value, Flag::Flags origin) {
 758   Flag* result = Flag::find_flag(name, len);
 759   if (result == NULL) return false;
 760   if (!result->is_double()) return false;
 761   double old_value = result->get_double();
 762 #if INCLUDE_JFR
 763   trace_flag_changed<EventDoubleFlagChanged, double>(name, old_value, *value, origin);
 764 #endif
 765   result->set_double(*value);
 766   *value = old_value;
 767   result->set_origin(origin);
 768   return true;
 769 }
 770 
 771 void CommandLineFlagsEx::doubleAtPut(CommandLineFlagWithType flag, double value, Flag::Flags origin) {
 772   Flag* faddr = address_of_flag(flag);
 773   guarantee(faddr != NULL && faddr->is_double(), "wrong flag type");
 774 #if INCLUDE_JFR
 775   trace_flag_changed<EventDoubleFlagChanged, double>(faddr->_name, faddr->get_double(), value, origin);
 776 #endif
 777   faddr->set_double(value);
 778   faddr->set_origin(origin);
 779 }
 780 
 781 bool CommandLineFlags::ccstrAt(const char* name, size_t len, ccstr* value, bool allow_locked, bool return_flag) {
 782   Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
 783   if (result == NULL) return false;
 784   if (!result->is_ccstr()) return false;
 785   *value = result->get_ccstr();
 786   return true;
 787 }
 788 
 789 bool CommandLineFlags::ccstrAtPut(const char* name, size_t len, ccstr* value, Flag::Flags origin) {
 790   Flag* result = Flag::find_flag(name, len);
 791   if (result == NULL) return false;
 792   if (!result->is_ccstr()) return false;
 793   ccstr old_value = result->get_ccstr();
 794 #if INCLUDE_JFR
 795   trace_flag_changed<EventStringFlagChanged, const char*>(name, old_value, *value, origin);
 796 #endif
 797   char* new_value = NULL;
 798   if (*value != NULL) {
 799     new_value = NEW_C_HEAP_ARRAY(char, strlen(*value)+1, mtInternal);
 800     strcpy(new_value, *value);
 801   }
 802   result->set_ccstr(new_value);
 803   if (result->is_default() && old_value != NULL) {
 804     // Prior value is NOT heap allocated, but was a literal constant.
 805     char* old_value_to_free = NEW_C_HEAP_ARRAY(char, strlen(old_value)+1, mtInternal);
 806     strcpy(old_value_to_free, old_value);
 807     old_value = old_value_to_free;
 808   }
 809   *value = old_value;
 810   result->set_origin(origin);
 811   return true;
 812 }
 813 
 814 void CommandLineFlagsEx::ccstrAtPut(CommandLineFlagWithType flag, ccstr value, Flag::Flags origin) {
 815   Flag* faddr = address_of_flag(flag);
 816   guarantee(faddr != NULL && faddr->is_ccstr(), "wrong flag type");
 817   ccstr old_value = faddr->get_ccstr();
 818 #if INCLUDE_JFR
 819   trace_flag_changed<EventStringFlagChanged, const char*>(faddr->_name, old_value, value, origin);
 820 #endif
 821   char* new_value = NEW_C_HEAP_ARRAY(char, strlen(value)+1, mtInternal);
 822   strcpy(new_value, value);
 823   faddr->set_ccstr(new_value);
 824   if (!faddr->is_default() && old_value != NULL) {
 825     // Prior value is heap allocated so free it.
 826     FREE_C_HEAP_ARRAY(char, old_value, mtInternal);
 827   }
 828   faddr->set_origin(origin);
 829 }
 830 
 831 extern "C" {
 832   static int compare_flags(const void* void_a, const void* void_b) {
 833     return strcmp((*((Flag**) void_a))->_name, (*((Flag**) void_b))->_name);
 834   }
 835 }
 836 
 837 void CommandLineFlags::printSetFlags(outputStream* out) {
 838   // Print which flags were set on the command line
 839   // note: this method is called before the thread structure is in place
 840   //       which means resource allocation cannot be used.
 841 
 842   // The last entry is the null entry.
 843   const size_t length = Flag::numFlags - 1;
 844 
 845   // Sort
 846   Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtInternal);
 847   for (size_t i = 0; i < length; i++) {
 848     array[i] = &flagTable[i];
 849   }
 850   qsort(array, length, sizeof(Flag*), compare_flags);
 851 
 852   // Print
 853   for (size_t i = 0; i < length; i++) {
 854     if (array[i]->get_origin() /* naked field! */) {
 855       array[i]->print_as_flag(out);
 856       out->print(" ");
 857     }
 858   }
 859   out->cr();
 860   FREE_C_HEAP_ARRAY(Flag*, array, mtInternal);
 861 }
 862 
 863 #ifndef PRODUCT
 864 
 865 
 866 void CommandLineFlags::verify() {
 867   assert(Arguments::check_vm_args_consistency(), "Some flag settings conflict");
 868 }
 869 
 870 #endif // PRODUCT
 871 
 872 void CommandLineFlags::printFlags(outputStream* out, bool withComments) {
 873   // Print the flags sorted by name
 874   // note: this method is called before the thread structure is in place
 875   //       which means resource allocation cannot be used.
 876 
 877   // The last entry is the null entry.
 878   const size_t length = Flag::numFlags - 1;
 879 
 880   // Sort
 881   Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtInternal);
 882   for (size_t i = 0; i < length; i++) {
 883     array[i] = &flagTable[i];
 884   }
 885   qsort(array, length, sizeof(Flag*), compare_flags);
 886 
 887   // Print
 888   out->print_cr("[Global flags]");
 889   for (size_t i = 0; i < length; i++) {
 890     if (array[i]->is_unlocked()) {
 891       array[i]->print_on(out, withComments);
 892     }
 893   }
 894   FREE_C_HEAP_ARRAY(Flag*, array, mtInternal);
 895 }