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