globals.cpp 31.5 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
22 23 24
 *
 */

25 26 27 28 29 30 31
#include "precompiled.hpp"
#include "memory/allocation.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/arguments.hpp"
#include "runtime/globals.hpp"
#include "runtime/globals_extension.hpp"
#include "utilities/ostream.hpp"
32
#include "utilities/macros.hpp"
33
#include "utilities/top.hpp"
34
#include "trace/tracing.hpp"
35
#if INCLUDE_ALL_GCS
36
#include "gc_implementation/g1/g1_globals.hpp"
37
#endif // INCLUDE_ALL_GCS
38 39 40 41 42 43 44 45 46
#ifdef COMPILER1
#include "c1/c1_globals.hpp"
#endif
#ifdef COMPILER2
#include "opto/c2_globals.hpp"
#endif
#ifdef SHARK
#include "shark/shark_globals.hpp"
#endif
D
duke 已提交
47

48 49
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC

D
duke 已提交
50 51
RUNTIME_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, \
              MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, \
52 53
              MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_EXPERIMENTAL_FLAG, \
              MATERIALIZE_NOTPRODUCT_FLAG, \
54 55
              MATERIALIZE_MANAGEABLE_FLAG, MATERIALIZE_PRODUCT_RW_FLAG, \
              MATERIALIZE_LP64_PRODUCT_FLAG)
D
duke 已提交
56 57 58 59 60

RUNTIME_OS_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, \
                 MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, \
                 MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_NOTPRODUCT_FLAG)

61 62 63 64
ARCH_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, \
           MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_EXPERIMENTAL_FLAG, \
           MATERIALIZE_NOTPRODUCT_FLAG)

65 66 67
MATERIALIZE_FLAGS_EXT


68 69 70 71 72 73 74 75
static bool is_product_build() {
#ifdef PRODUCT
  return true;
#else
  return false;
#endif
}

76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
void Flag::check_writable() {
  if (is_constant_in_binary()) {
    fatal(err_msg("flag is constant: %s", _name));
  }
}

bool Flag::is_bool() const {
  return strcmp(_type, "bool") == 0;
}

bool Flag::get_bool() const {
  return *((bool*) _addr);
}

void Flag::set_bool(bool value) {
  check_writable();
  *((bool*) _addr) = value;
}

bool Flag::is_intx() const {
  return strcmp(_type, "intx")  == 0;
}

intx Flag::get_intx() const {
  return *((intx*) _addr);
}

void Flag::set_intx(intx value) {
  check_writable();
  *((intx*) _addr) = value;
}

bool Flag::is_uintx() const {
  return strcmp(_type, "uintx") == 0;
}

uintx Flag::get_uintx() const {
  return *((uintx*) _addr);
}

void Flag::set_uintx(uintx value) {
  check_writable();
  *((uintx*) _addr) = value;
}

bool Flag::is_uint64_t() const {
  return strcmp(_type, "uint64_t") == 0;
}

uint64_t Flag::get_uint64_t() const {
  return *((uint64_t*) _addr);
}

void Flag::set_uint64_t(uint64_t value) {
  check_writable();
  *((uint64_t*) _addr) = value;
}

bool Flag::is_double() const {
  return strcmp(_type, "double") == 0;
}

double Flag::get_double() const {
  return *((double*) _addr);
}

void Flag::set_double(double value) {
  check_writable();
  *((double*) _addr) = value;
}

bool Flag::is_ccstr() const {
  return strcmp(_type, "ccstr") == 0 || strcmp(_type, "ccstrlist") == 0;
}

bool Flag::ccstr_accumulates() const {
  return strcmp(_type, "ccstrlist") == 0;
}

ccstr Flag::get_ccstr() const {
  return *((ccstr*) _addr);
}

void Flag::set_ccstr(ccstr value) {
  check_writable();
  *((ccstr*) _addr) = value;
}


Flag::Flags Flag::get_origin() {
  return Flags(_flags & VALUE_ORIGIN_MASK);
}

void Flag::set_origin(Flags origin) {
  assert((origin & VALUE_ORIGIN_MASK) == origin, "sanity");
  _flags = Flags((_flags & ~VALUE_ORIGIN_MASK) | origin);
}

bool Flag::is_default() {
  return (get_origin() == DEFAULT);
}

bool Flag::is_ergonomic() {
  return (get_origin() == ERGONOMIC);
}

bool Flag::is_command_line() {
  return (get_origin() == COMMAND_LINE);
}

bool Flag::is_product() const {
  return (_flags & KIND_PRODUCT) != 0;
}

bool Flag::is_manageable() const {
  return (_flags & KIND_MANAGEABLE) != 0;
}

bool Flag::is_diagnostic() const {
  return (_flags & KIND_DIAGNOSTIC) != 0;
}

bool Flag::is_experimental() const {
  return (_flags & KIND_EXPERIMENTAL) != 0;
}

bool Flag::is_notproduct() const {
  return (_flags & KIND_NOT_PRODUCT) != 0;
}

bool Flag::is_develop() const {
  return (_flags & KIND_DEVELOP) != 0;
}

bool Flag::is_read_write() const {
  return (_flags & KIND_READ_WRITE) != 0;
}

bool Flag::is_commercial() const {
  return (_flags & KIND_COMMERCIAL) != 0;
}

/**
 * Returns if this flag is a constant in the binary.  Right now this is
 * true for notproduct and develop flags in product builds.
 */
bool Flag::is_constant_in_binary() const {
#ifdef PRODUCT
    return is_notproduct() || is_develop();
#else
    return false;
#endif
}

D
duke 已提交
230
bool Flag::is_unlocker() const {
231 232
  return strcmp(_name, "UnlockDiagnosticVMOptions") == 0     ||
         strcmp(_name, "UnlockExperimentalVMOptions") == 0   ||
233
         is_unlocker_ext();
D
duke 已提交
234 235 236
}

bool Flag::is_unlocked() const {
237
  if (is_diagnostic()) {
D
duke 已提交
238
    return UnlockDiagnosticVMOptions;
239 240
  }
  if (is_experimental()) {
241
    return UnlockExperimentalVMOptions;
D
duke 已提交
242
  }
243
  return is_unlocked_ext();
D
duke 已提交
244 245
}

246 247 248
// Get custom message for this locked flag, or return NULL if
// none is available.
void Flag::get_locked_message(char* buf, int buflen) const {
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
  buf[0] = '\0';
  if (is_diagnostic() && !is_unlocked()) {
    jio_snprintf(buf, buflen, "Error: VM option '%s' is diagnostic and must be enabled via -XX:+UnlockDiagnosticVMOptions.\n",
                 _name);
    return;
  }
  if (is_experimental() && !is_unlocked()) {
    jio_snprintf(buf, buflen, "Error: VM option '%s' is experimental and must be enabled via -XX:+UnlockExperimentalVMOptions.\n",
                 _name);
    return;
  }
  if (is_develop() && is_product_build()) {
    jio_snprintf(buf, buflen, "Error: VM option '%s' is develop and is available only in debug version of VM.\n",
                 _name);
    return;
  }
  if (is_notproduct() && is_product_build()) {
    jio_snprintf(buf, buflen, "Error: VM option '%s' is notproduct and is available only in debug version of VM.\n",
                 _name);
    return;
  }
270 271 272
  get_locked_message_ext(buf, buflen);
}

D
duke 已提交
273
bool Flag::is_writeable() const {
274
  return is_manageable() || (is_product() && is_read_write()) || is_writeable_ext();
D
duke 已提交
275 276
}

277
// All flags except "manageable" are assumed to be internal flags.
D
duke 已提交
278 279 280
// Long term, we need to define a mechanism to specify which flags
// are external/stable and change this function accordingly.
bool Flag::is_external() const {
281
  return is_manageable() || is_external_ext();
D
duke 已提交
282 283
}

284

D
duke 已提交
285 286 287
// Length of format string (e.g. "%.1234s") for printing ccstr below
#define FORMAT_BUFFER_LEN 16

288
PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL
289
void Flag::print_on(outputStream* st, bool withComments) {
290 291 292 293
  // Don't print notproduct and develop flags in a product build.
  if (is_constant_in_binary()) {
    return;
  }
294

295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
  st->print("%9s %-40s %c= ", _type, _name, (!is_default() ? ':' : ' '));

  if (is_bool()) {
    st->print("%-16s", get_bool() ? "true" : "false");
  }
  if (is_intx()) {
    st->print("%-16ld", get_intx());
  }
  if (is_uintx()) {
    st->print("%-16lu", get_uintx());
  }
  if (is_uint64_t()) {
    st->print("%-16lu", get_uint64_t());
  }
  if (is_double()) {
    st->print("%-16f", get_double());
  }
D
duke 已提交
312
  if (is_ccstr()) {
313 314 315 316 317 318 319 320
    const char* cp = get_ccstr();
    if (cp != NULL) {
      const char* eol;
      while ((eol = strchr(cp, '\n')) != NULL) {
        char format_buffer[FORMAT_BUFFER_LEN];
        size_t llen = pointer_delta(eol, cp, sizeof(char));
        jio_snprintf(format_buffer, FORMAT_BUFFER_LEN,
            "%%." SIZE_FORMAT "s", llen);
321 322
PRAGMA_DIAG_PUSH
PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL
323
        st->print(format_buffer, cp);
324
PRAGMA_DIAG_POP
325 326 327 328 329 330 331
        st->cr();
        cp = eol+1;
        st->print("%5s %-35s += ", "", _name);
      }
      st->print("%-16s", cp);
    }
    else st->print("%-16s", "");
332
  }
333

334
  st->print("%-20s", " ");
335 336
  print_kind(st);

337 338
  if (withComments) {
#ifndef PRODUCT
339
    st->print("%s", _doc);
340
#endif
D
duke 已提交
341 342 343 344
  }
  st->cr();
}

345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
void Flag::print_kind(outputStream* st) {
  struct Data {
    int flag;
    const char* name;
  };

  Data data[] = {
      { KIND_C1, "C1" },
      { KIND_C2, "C2" },
      { KIND_ARCH, "ARCH" },
      { KIND_SHARK, "SHARK" },
      { KIND_PLATFORM_DEPENDENT, "pd" },
      { KIND_PRODUCT, "product" },
      { KIND_MANAGEABLE, "manageable" },
      { KIND_DIAGNOSTIC, "diagnostic" },
360 361
      { KIND_EXPERIMENTAL, "experimental" },
      { KIND_COMMERCIAL, "commercial" },
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
      { KIND_NOT_PRODUCT, "notproduct" },
      { KIND_DEVELOP, "develop" },
      { KIND_LP64_PRODUCT, "lp64_product" },
      { KIND_READ_WRITE, "rw" },
      { -1, "" }
  };

  if ((_flags & KIND_MASK) != 0) {
    st->print("{");
    bool is_first = true;

    for (int i = 0; data[i].flag != -1; i++) {
      Data d = data[i];
      if ((_flags & d.flag) != 0) {
        if (is_first) {
          is_first = false;
        } else {
          st->print(" ");
        }
381
        st->print("%s", d.name);
382 383 384 385 386 387 388
      }
    }

    st->print("}");
  }
}

D
duke 已提交
389 390
void Flag::print_as_flag(outputStream* st) {
  if (is_bool()) {
391
    st->print("-XX:%s%s", get_bool() ? "+" : "-", _name);
D
duke 已提交
392
  } else if (is_intx()) {
393
    st->print("-XX:%s=" INTX_FORMAT, _name, get_intx());
D
duke 已提交
394
  } else if (is_uintx()) {
395
    st->print("-XX:%s=" UINTX_FORMAT, _name, get_uintx());
396
  } else if (is_uint64_t()) {
397
    st->print("-XX:%s=" UINT64_FORMAT, _name, get_uint64_t());
398
  } else if (is_double()) {
399
    st->print("-XX:%s=%f", _name, get_double());
D
duke 已提交
400
  } else if (is_ccstr()) {
401
    st->print("-XX:%s=", _name);
402 403 404 405 406 407 408 409 410 411 412 413
    const char* cp = get_ccstr();
    if (cp != NULL) {
      // Need to turn embedded '\n's back into separate arguments
      // Not so efficient to print one character at a time,
      // but the choice is to do the transformation to a buffer
      // and print that.  And this need not be efficient.
      for (; *cp != '\0'; cp += 1) {
        switch (*cp) {
          default:
            st->print("%c", *cp);
            break;
          case '\n':
414
            st->print(" -XX:%s=", _name);
415 416
            break;
        }
D
duke 已提交
417 418 419 420 421 422 423 424 425 426
      }
    }
  } else {
    ShouldNotReachHere();
  }
}

// 4991491 do not "optimize out" the was_set false values: omitting them
// tickles a Microsoft compiler bug causing flagTable to be malformed

427
#define NAME(name) NOT_PRODUCT(&name) PRODUCT_ONLY(&CONST_##name)
D
duke 已提交
428

429 430 431 432 433 434 435 436 437
#define RUNTIME_PRODUCT_FLAG_STRUCT(     type, name, value, doc) { #type, XSTR(name), &name,      NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_PRODUCT) },
#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) },
#define RUNTIME_DIAGNOSTIC_FLAG_STRUCT(  type, name, value, doc) { #type, XSTR(name), &name,      NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_DIAGNOSTIC) },
#define RUNTIME_EXPERIMENTAL_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name,      NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_EXPERIMENTAL) },
#define RUNTIME_MANAGEABLE_FLAG_STRUCT(  type, name, value, doc) { #type, XSTR(name), &name,      NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_MANAGEABLE) },
#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) },
#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) },
#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) },
#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) },
D
duke 已提交
438

439
#ifdef _LP64
440
#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) },
441
#else
442
#define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) /* flag is constant */
443 444
#endif // _LP64

445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
#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) },
#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) },
#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) },
#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) },
#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) },
#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) },

#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) },
#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) },
#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) },
#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) },
#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) },
#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) },
#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) },

#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) },
#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) },
#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) },
#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) },
#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) },

#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) },
#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) },
#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) },
#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) },
#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) },
#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) },
D
duke 已提交
472 473

static Flag flagTable[] = {
474
 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)
D
duke 已提交
475
 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)
476
#if INCLUDE_ALL_GCS
477
 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)
478
#endif // INCLUDE_ALL_GCS
D
duke 已提交
479
#ifdef COMPILER1
480
 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)
D
duke 已提交
481 482
#endif
#ifdef COMPILER2
483
 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)
484 485 486
#endif
#ifdef SHARK
 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)
D
duke 已提交
487
#endif
488
 ARCH_FLAGS(ARCH_DEVELOP_FLAG_STRUCT, ARCH_PRODUCT_FLAG_STRUCT, ARCH_DIAGNOSTIC_FLAG_STRUCT, ARCH_EXPERIMENTAL_FLAG_STRUCT, ARCH_NOTPRODUCT_FLAG_STRUCT)
489
 FLAGTABLE_EXT
D
duke 已提交
490 491 492 493 494 495
 {0, NULL, NULL}
};

Flag* Flag::flags = flagTable;
size_t Flag::numFlags = (sizeof(flagTable) / sizeof(Flag));

496
inline bool str_equal(const char* s, const char* q, size_t len) {
D
duke 已提交
497 498 499 500 501
  // s is null terminated, q is not!
  if (strlen(s) != (unsigned int) len) return false;
  return strncmp(s, q, len) == 0;
}

502
// Search the flag table for a named flag
503
Flag* Flag::find_flag(const char* name, size_t length, bool allow_locked, bool return_flag) {
504 505 506 507 508
  for (Flag* current = &flagTable[0]; current->_name != NULL; current++) {
    if (str_equal(current->_name, name, length)) {
      // Found a matching entry.
      // Don't report notproduct and develop flags in product builds.
      if (current->is_constant_in_binary()) {
509
        return (return_flag == true ? current : NULL);
510 511
      }
      // Report locked flags only if allowed.
D
duke 已提交
512
      if (!(current->is_unlocked() || current->is_unlocker())) {
513 514 515 516 517
        if (!allow_locked) {
          // disable use of locked flags, e.g. diagnostic, experimental,
          // commercial... until they are explicitly unlocked
          return NULL;
        }
D
duke 已提交
518 519 520 521
      }
      return current;
    }
  }
522
  // Flag name is not in the flag table
D
duke 已提交
523 524 525
  return NULL;
}

526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
// Compute string similarity based on Dice's coefficient
static float str_similar(const char* str1, const char* str2, size_t len2) {
  int len1 = (int) strlen(str1);
  int total = len1 + (int) len2;

  int hit = 0;

  for (int i = 0; i < len1 -1; ++i) {
    for (int j = 0; j < (int) len2 -1; ++j) {
      if ((str1[i] == str2[j]) && (str1[i+1] == str2[j+1])) {
        ++hit;
        break;
      }
    }
  }

  return 2.0f * (float) hit / (float) total;
}

Flag* Flag::fuzzy_match(const char* name, size_t length, bool allow_locked) {
  float VMOptionsFuzzyMatchSimilarity = 0.7f;
  Flag* match = NULL;
  float score;
  float max_score = -1;

551 552
  for (Flag* current = &flagTable[0]; current->_name != NULL; current++) {
    score = str_similar(current->_name, name, length);
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
    if (score > max_score) {
      max_score = score;
      match = current;
    }
  }

  if (!(match->is_unlocked() || match->is_unlocker())) {
    if (!allow_locked) {
      return NULL;
    }
  }

  if (max_score < VMOptionsFuzzyMatchSimilarity) {
    return NULL;
  }

  return match;
}

D
duke 已提交
572 573 574 575 576 577 578 579 580
// Returns the address of the index'th element
static Flag* address_of_flag(CommandLineFlagWithType flag) {
  assert((size_t)flag < Flag::numFlags, "bad command line flag index");
  return &Flag::flags[flag];
}

bool CommandLineFlagsEx::is_default(CommandLineFlag flag) {
  assert((size_t)flag < Flag::numFlags, "bad command line flag index");
  Flag* f = &Flag::flags[flag];
581
  return f->is_default();
D
duke 已提交
582 583
}

584 585 586
bool CommandLineFlagsEx::is_ergo(CommandLineFlag flag) {
  assert((size_t)flag < Flag::numFlags, "bad command line flag index");
  Flag* f = &Flag::flags[flag];
587
  return f->is_ergonomic();
588 589 590 591 592
}

bool CommandLineFlagsEx::is_cmdline(CommandLineFlag flag) {
  assert((size_t)flag < Flag::numFlags, "bad command line flag index");
  Flag* f = &Flag::flags[flag];
593
  return f->is_command_line();
594 595
}

D
duke 已提交
596 597 598
bool CommandLineFlags::wasSetOnCmdline(const char* name, bool* value) {
  Flag* result = Flag::find_flag((char*)name, strlen(name));
  if (result == NULL) return false;
599
  *value = result->is_command_line();
D
duke 已提交
600 601 602
  return true;
}

603 604 605 606 607 608 609 610 611 612 613
template<class E, class T>
static void trace_flag_changed(const char* name, const T old_value, const T new_value, const Flag::Flags origin)
{
  E e;
  e.set_name(name);
  e.set_old_value(old_value);
  e.set_new_value(new_value);
  e.set_origin(origin);
  e.commit();
}

D
duke 已提交
614 615 616 617 618 619 620 621
bool CommandLineFlags::boolAt(char* name, size_t len, bool* value) {
  Flag* result = Flag::find_flag(name, len);
  if (result == NULL) return false;
  if (!result->is_bool()) return false;
  *value = result->get_bool();
  return true;
}

622
bool CommandLineFlags::boolAtPut(char* name, size_t len, bool* value, Flag::Flags origin) {
D
duke 已提交
623 624 625 626
  Flag* result = Flag::find_flag(name, len);
  if (result == NULL) return false;
  if (!result->is_bool()) return false;
  bool old_value = result->get_bool();
627
  trace_flag_changed<EventBooleanFlagChanged, bool>(name, old_value, *value, origin);
D
duke 已提交
628 629
  result->set_bool(*value);
  *value = old_value;
630
  result->set_origin(origin);
D
duke 已提交
631 632 633
  return true;
}

634
void CommandLineFlagsEx::boolAtPut(CommandLineFlagWithType flag, bool value, Flag::Flags origin) {
D
duke 已提交
635 636
  Flag* faddr = address_of_flag(flag);
  guarantee(faddr != NULL && faddr->is_bool(), "wrong flag type");
637
  trace_flag_changed<EventBooleanFlagChanged, bool>(faddr->_name, faddr->get_bool(), value, origin);
D
duke 已提交
638
  faddr->set_bool(value);
639
  faddr->set_origin(origin);
D
duke 已提交
640 641 642 643 644 645 646 647 648 649
}

bool CommandLineFlags::intxAt(char* name, size_t len, intx* value) {
  Flag* result = Flag::find_flag(name, len);
  if (result == NULL) return false;
  if (!result->is_intx()) return false;
  *value = result->get_intx();
  return true;
}

650
bool CommandLineFlags::intxAtPut(char* name, size_t len, intx* value, Flag::Flags origin) {
D
duke 已提交
651 652 653 654
  Flag* result = Flag::find_flag(name, len);
  if (result == NULL) return false;
  if (!result->is_intx()) return false;
  intx old_value = result->get_intx();
655
  trace_flag_changed<EventLongFlagChanged, s8>(name, old_value, *value, origin);
D
duke 已提交
656 657
  result->set_intx(*value);
  *value = old_value;
658
  result->set_origin(origin);
D
duke 已提交
659 660 661
  return true;
}

662
void CommandLineFlagsEx::intxAtPut(CommandLineFlagWithType flag, intx value, Flag::Flags origin) {
D
duke 已提交
663 664
  Flag* faddr = address_of_flag(flag);
  guarantee(faddr != NULL && faddr->is_intx(), "wrong flag type");
665
  trace_flag_changed<EventLongFlagChanged, s8>(faddr->_name, faddr->get_intx(), value, origin);
D
duke 已提交
666
  faddr->set_intx(value);
667
  faddr->set_origin(origin);
D
duke 已提交
668 669 670 671 672 673 674 675 676 677
}

bool CommandLineFlags::uintxAt(char* name, size_t len, uintx* value) {
  Flag* result = Flag::find_flag(name, len);
  if (result == NULL) return false;
  if (!result->is_uintx()) return false;
  *value = result->get_uintx();
  return true;
}

678
bool CommandLineFlags::uintxAtPut(char* name, size_t len, uintx* value, Flag::Flags origin) {
D
duke 已提交
679 680 681 682
  Flag* result = Flag::find_flag(name, len);
  if (result == NULL) return false;
  if (!result->is_uintx()) return false;
  uintx old_value = result->get_uintx();
683
  trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
D
duke 已提交
684 685
  result->set_uintx(*value);
  *value = old_value;
686
  result->set_origin(origin);
D
duke 已提交
687 688 689
  return true;
}

690
void CommandLineFlagsEx::uintxAtPut(CommandLineFlagWithType flag, uintx value, Flag::Flags origin) {
D
duke 已提交
691 692
  Flag* faddr = address_of_flag(flag);
  guarantee(faddr != NULL && faddr->is_uintx(), "wrong flag type");
693
  trace_flag_changed<EventUnsignedLongFlagChanged, u8>(faddr->_name, faddr->get_uintx(), value, origin);
D
duke 已提交
694
  faddr->set_uintx(value);
695
  faddr->set_origin(origin);
D
duke 已提交
696 697
}

P
phh 已提交
698 699 700 701 702 703 704 705
bool CommandLineFlags::uint64_tAt(char* name, size_t len, uint64_t* value) {
  Flag* result = Flag::find_flag(name, len);
  if (result == NULL) return false;
  if (!result->is_uint64_t()) return false;
  *value = result->get_uint64_t();
  return true;
}

706
bool CommandLineFlags::uint64_tAtPut(char* name, size_t len, uint64_t* value, Flag::Flags origin) {
P
phh 已提交
707 708 709 710
  Flag* result = Flag::find_flag(name, len);
  if (result == NULL) return false;
  if (!result->is_uint64_t()) return false;
  uint64_t old_value = result->get_uint64_t();
711
  trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
P
phh 已提交
712 713
  result->set_uint64_t(*value);
  *value = old_value;
714
  result->set_origin(origin);
P
phh 已提交
715 716 717
  return true;
}

718
void CommandLineFlagsEx::uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, Flag::Flags origin) {
P
phh 已提交
719 720
  Flag* faddr = address_of_flag(flag);
  guarantee(faddr != NULL && faddr->is_uint64_t(), "wrong flag type");
721
  trace_flag_changed<EventUnsignedLongFlagChanged, u8>(faddr->_name, faddr->get_uint64_t(), value, origin);
P
phh 已提交
722
  faddr->set_uint64_t(value);
723
  faddr->set_origin(origin);
P
phh 已提交
724 725
}

D
duke 已提交
726 727 728 729 730 731 732 733
bool CommandLineFlags::doubleAt(char* name, size_t len, double* value) {
  Flag* result = Flag::find_flag(name, len);
  if (result == NULL) return false;
  if (!result->is_double()) return false;
  *value = result->get_double();
  return true;
}

734
bool CommandLineFlags::doubleAtPut(char* name, size_t len, double* value, Flag::Flags origin) {
D
duke 已提交
735 736 737 738
  Flag* result = Flag::find_flag(name, len);
  if (result == NULL) return false;
  if (!result->is_double()) return false;
  double old_value = result->get_double();
739
  trace_flag_changed<EventDoubleFlagChanged, double>(name, old_value, *value, origin);
D
duke 已提交
740 741
  result->set_double(*value);
  *value = old_value;
742
  result->set_origin(origin);
D
duke 已提交
743 744 745
  return true;
}

746
void CommandLineFlagsEx::doubleAtPut(CommandLineFlagWithType flag, double value, Flag::Flags origin) {
D
duke 已提交
747 748
  Flag* faddr = address_of_flag(flag);
  guarantee(faddr != NULL && faddr->is_double(), "wrong flag type");
749
  trace_flag_changed<EventDoubleFlagChanged, double>(faddr->_name, faddr->get_double(), value, origin);
D
duke 已提交
750
  faddr->set_double(value);
751
  faddr->set_origin(origin);
D
duke 已提交
752 753 754 755 756 757 758 759 760 761 762 763
}

bool CommandLineFlags::ccstrAt(char* name, size_t len, ccstr* value) {
  Flag* result = Flag::find_flag(name, len);
  if (result == NULL) return false;
  if (!result->is_ccstr()) return false;
  *value = result->get_ccstr();
  return true;
}

// Contract:  Flag will make private copy of the incoming value.
// Outgoing value is always malloc-ed, and caller MUST call free.
764
bool CommandLineFlags::ccstrAtPut(char* name, size_t len, ccstr* value, Flag::Flags origin) {
D
duke 已提交
765 766 767 768
  Flag* result = Flag::find_flag(name, len);
  if (result == NULL) return false;
  if (!result->is_ccstr()) return false;
  ccstr old_value = result->get_ccstr();
769
  trace_flag_changed<EventStringFlagChanged, const char*>(name, old_value, *value, origin);
770 771
  char* new_value = NULL;
  if (*value != NULL) {
Z
zgu 已提交
772
    new_value = NEW_C_HEAP_ARRAY(char, strlen(*value)+1, mtInternal);
773 774
    strcpy(new_value, *value);
  }
D
duke 已提交
775
  result->set_ccstr(new_value);
776
  if (result->is_default() && old_value != NULL) {
D
duke 已提交
777
    // Prior value is NOT heap allocated, but was a literal constant.
Z
zgu 已提交
778
    char* old_value_to_free = NEW_C_HEAP_ARRAY(char, strlen(old_value)+1, mtInternal);
D
duke 已提交
779 780 781 782
    strcpy(old_value_to_free, old_value);
    old_value = old_value_to_free;
  }
  *value = old_value;
783
  result->set_origin(origin);
D
duke 已提交
784 785 786 787
  return true;
}

// Contract:  Flag will make private copy of the incoming value.
788
void CommandLineFlagsEx::ccstrAtPut(CommandLineFlagWithType flag, ccstr value, Flag::Flags origin) {
D
duke 已提交
789 790 791
  Flag* faddr = address_of_flag(flag);
  guarantee(faddr != NULL && faddr->is_ccstr(), "wrong flag type");
  ccstr old_value = faddr->get_ccstr();
792
  trace_flag_changed<EventStringFlagChanged, const char*>(faddr->_name, old_value, value, origin);
Z
zgu 已提交
793
  char* new_value = NEW_C_HEAP_ARRAY(char, strlen(value)+1, mtInternal);
D
duke 已提交
794 795
  strcpy(new_value, value);
  faddr->set_ccstr(new_value);
796
  if (!faddr->is_default() && old_value != NULL) {
D
duke 已提交
797
    // Prior value is heap allocated so free it.
Z
zgu 已提交
798
    FREE_C_HEAP_ARRAY(char, old_value, mtInternal);
D
duke 已提交
799
  }
800
  faddr->set_origin(origin);
D
duke 已提交
801 802 803 804
}

extern "C" {
  static int compare_flags(const void* void_a, const void* void_b) {
805
    return strcmp((*((Flag**) void_a))->_name, (*((Flag**) void_b))->_name);
D
duke 已提交
806 807 808
  }
}

F
fparain 已提交
809
void CommandLineFlags::printSetFlags(outputStream* out) {
D
duke 已提交
810 811 812 813
  // Print which flags were set on the command line
  // note: this method is called before the thread structure is in place
  //       which means resource allocation cannot be used.

814 815
  // The last entry is the null entry.
  const size_t length = Flag::numFlags - 1;
D
duke 已提交
816 817

  // Sort
Z
zgu 已提交
818
  Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtInternal);
819 820
  for (size_t i = 0; i < length; i++) {
    array[i] = &flagTable[i];
D
duke 已提交
821 822 823 824
  }
  qsort(array, length, sizeof(Flag*), compare_flags);

  // Print
825 826
  for (size_t i = 0; i < length; i++) {
    if (array[i]->get_origin() /* naked field! */) {
F
fparain 已提交
827 828
      array[i]->print_as_flag(out);
      out->print(" ");
D
duke 已提交
829 830
    }
  }
F
fparain 已提交
831
  out->cr();
Z
zgu 已提交
832
  FREE_C_HEAP_ARRAY(Flag*, array, mtInternal);
D
duke 已提交
833 834 835 836 837 838 839 840 841
}

#ifndef PRODUCT


void CommandLineFlags::verify() {
  assert(Arguments::check_vm_args_consistency(), "Some flag settings conflict");
}

842 843
#endif // PRODUCT

F
fparain 已提交
844
void CommandLineFlags::printFlags(outputStream* out, bool withComments) {
D
duke 已提交
845 846 847 848
  // Print the flags sorted by name
  // note: this method is called before the thread structure is in place
  //       which means resource allocation cannot be used.

849 850
  // The last entry is the null entry.
  const size_t length = Flag::numFlags - 1;
D
duke 已提交
851 852

  // Sort
Z
zgu 已提交
853
  Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtInternal);
854 855
  for (size_t i = 0; i < length; i++) {
    array[i] = &flagTable[i];
D
duke 已提交
856 857 858 859
  }
  qsort(array, length, sizeof(Flag*), compare_flags);

  // Print
F
fparain 已提交
860
  out->print_cr("[Global flags]");
861
  for (size_t i = 0; i < length; i++) {
D
duke 已提交
862
    if (array[i]->is_unlocked()) {
F
fparain 已提交
863
      array[i]->print_on(out, withComments);
D
duke 已提交
864 865
    }
  }
Z
zgu 已提交
866
  FREE_C_HEAP_ARRAY(Flag*, array, mtInternal);
D
duke 已提交
867
}