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