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