1 /*
2  * Copyright (c) 1997, 2018, 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 "jfr/jfrEvents.hpp"
27 #include "memory/allocation.inline.hpp"
28 #include "runtime/arguments.hpp"
29 #include "runtime/flags/jvmFlag.hpp"
30 #include "runtime/flags/jvmFlagConstraintList.hpp"
31 #include "runtime/flags/jvmFlagWriteableList.hpp"
32 #include "runtime/flags/jvmFlagRangeList.hpp"
33 #include "runtime/globals_extension.hpp"
34 #include "utilities/defaultStream.hpp"
35 #include "utilities/stringUtils.hpp"
36 
37 #define DEFAULT_RANGE_STR_CHUNK_SIZE 64
create_range_str(const char * fmt,...)38 static char* create_range_str(const char *fmt, ...) {
39   static size_t string_length = DEFAULT_RANGE_STR_CHUNK_SIZE;
40   static char* range_string = NEW_C_HEAP_ARRAY(char, string_length, mtLogging);
41 
42   int size_needed = 0;
43   do {
44     va_list args;
45     va_start(args, fmt);
46     size_needed = jio_vsnprintf(range_string, string_length, fmt, args);
47     va_end(args);
48 
49     if (size_needed < 0) {
50       string_length += DEFAULT_RANGE_STR_CHUNK_SIZE;
51       range_string = REALLOC_C_HEAP_ARRAY(char, range_string, string_length, mtLogging);
52       guarantee(range_string != NULL, "create_range_str string should not be NULL");
53     }
54   } while (size_needed < 0);
55 
56   return range_string;
57 }
58 
get_int_default_range_str()59 const char* JVMFlag::get_int_default_range_str() {
60   return create_range_str("[ " INT32_FORMAT_W(-25) " ... " INT32_FORMAT_W(25) " ]", INT_MIN, INT_MAX);
61 }
62 
get_uint_default_range_str()63 const char* JVMFlag::get_uint_default_range_str() {
64   return create_range_str("[ " UINT32_FORMAT_W(-25) " ... " UINT32_FORMAT_W(25) " ]", 0, UINT_MAX);
65 }
66 
get_intx_default_range_str()67 const char* JVMFlag::get_intx_default_range_str() {
68   return create_range_str("[ " INTX_FORMAT_W(-25) " ... " INTX_FORMAT_W(25) " ]", min_intx, max_intx);
69 }
70 
get_uintx_default_range_str()71 const char* JVMFlag::get_uintx_default_range_str() {
72   return create_range_str("[ " UINTX_FORMAT_W(-25) " ... " UINTX_FORMAT_W(25) " ]", 0, max_uintx);
73 }
74 
get_uint64_t_default_range_str()75 const char* JVMFlag::get_uint64_t_default_range_str() {
76   return create_range_str("[ " UINT64_FORMAT_W(-25) " ... " UINT64_FORMAT_W(25) " ]", 0, uint64_t(max_juint));
77 }
78 
get_size_t_default_range_str()79 const char* JVMFlag::get_size_t_default_range_str() {
80   return create_range_str("[ " SIZE_FORMAT_W(-25) " ... " SIZE_FORMAT_W(25) " ]", 0, SIZE_MAX);
81 }
82 
get_double_default_range_str()83 const char* JVMFlag::get_double_default_range_str() {
84   return create_range_str("[ %-25.3f ... %25.3f ]", DBL_MIN, DBL_MAX);
85 }
86 
is_product_build()87 static bool is_product_build() {
88 #ifdef PRODUCT
89   return true;
90 #else
91   return false;
92 #endif
93 }
94 
check_writable(bool changed)95 JVMFlag::Error JVMFlag::check_writable(bool changed) {
96   if (is_constant_in_binary()) {
97     fatal("flag is constant: %s", _name);
98   }
99 
100   JVMFlag::Error error = JVMFlag::SUCCESS;
101   if (changed) {
102     JVMFlagWriteable* writeable = JVMFlagWriteableList::find(_name);
103     if (writeable) {
104       if (writeable->is_writeable() == false) {
105         switch (writeable->type())
106         {
107           case JVMFlagWriteable::Once:
108             error = JVMFlag::SET_ONLY_ONCE;
109             jio_fprintf(defaultStream::error_stream(), "Error: %s may not be set more than once\n", _name);
110             break;
111           case JVMFlagWriteable::CommandLineOnly:
112             error = JVMFlag::COMMAND_LINE_ONLY;
113             jio_fprintf(defaultStream::error_stream(), "Error: %s may be modified only from commad line\n", _name);
114             break;
115           default:
116             ShouldNotReachHere();
117             break;
118         }
119       }
120       writeable->mark_once();
121     }
122   }
123   return error;
124 }
125 
is_bool() const126 bool JVMFlag::is_bool() const {
127   return strcmp(_type, "bool") == 0;
128 }
129 
get_bool() const130 bool JVMFlag::get_bool() const {
131   return *((bool*) _addr);
132 }
133 
set_bool(bool value)134 JVMFlag::Error JVMFlag::set_bool(bool value) {
135   JVMFlag::Error error = check_writable(value!=get_bool());
136   if (error == JVMFlag::SUCCESS) {
137     *((bool*) _addr) = value;
138   }
139   return error;
140 }
141 
is_int() const142 bool JVMFlag::is_int() const {
143   return strcmp(_type, "int")  == 0;
144 }
145 
get_int() const146 int JVMFlag::get_int() const {
147   return *((int*) _addr);
148 }
149 
set_int(int value)150 JVMFlag::Error JVMFlag::set_int(int value) {
151   JVMFlag::Error error = check_writable(value!=get_int());
152   if (error == JVMFlag::SUCCESS) {
153     *((int*) _addr) = value;
154   }
155   return error;
156 }
157 
is_uint() const158 bool JVMFlag::is_uint() const {
159   return strcmp(_type, "uint")  == 0;
160 }
161 
get_uint() const162 uint JVMFlag::get_uint() const {
163   return *((uint*) _addr);
164 }
165 
set_uint(uint value)166 JVMFlag::Error JVMFlag::set_uint(uint value) {
167   JVMFlag::Error error = check_writable(value!=get_uint());
168   if (error == JVMFlag::SUCCESS) {
169     *((uint*) _addr) = value;
170   }
171   return error;
172 }
173 
is_intx() const174 bool JVMFlag::is_intx() const {
175   return strcmp(_type, "intx")  == 0;
176 }
177 
get_intx() const178 intx JVMFlag::get_intx() const {
179   return *((intx*) _addr);
180 }
181 
set_intx(intx value)182 JVMFlag::Error JVMFlag::set_intx(intx value) {
183   JVMFlag::Error error = check_writable(value!=get_intx());
184   if (error == JVMFlag::SUCCESS) {
185     *((intx*) _addr) = value;
186   }
187   return error;
188 }
189 
is_uintx() const190 bool JVMFlag::is_uintx() const {
191   return strcmp(_type, "uintx") == 0;
192 }
193 
get_uintx() const194 uintx JVMFlag::get_uintx() const {
195   return *((uintx*) _addr);
196 }
197 
set_uintx(uintx value)198 JVMFlag::Error JVMFlag::set_uintx(uintx value) {
199   JVMFlag::Error error = check_writable(value!=get_uintx());
200   if (error == JVMFlag::SUCCESS) {
201     *((uintx*) _addr) = value;
202   }
203   return error;
204 }
205 
is_uint64_t() const206 bool JVMFlag::is_uint64_t() const {
207   return strcmp(_type, "uint64_t") == 0;
208 }
209 
get_uint64_t() const210 uint64_t JVMFlag::get_uint64_t() const {
211   return *((uint64_t*) _addr);
212 }
213 
set_uint64_t(uint64_t value)214 JVMFlag::Error JVMFlag::set_uint64_t(uint64_t value) {
215   JVMFlag::Error error = check_writable(value!=get_uint64_t());
216   if (error == JVMFlag::SUCCESS) {
217     *((uint64_t*) _addr) = value;
218   }
219   return error;
220 }
221 
is_size_t() const222 bool JVMFlag::is_size_t() const {
223   return strcmp(_type, "size_t") == 0;
224 }
225 
get_size_t() const226 size_t JVMFlag::get_size_t() const {
227   return *((size_t*) _addr);
228 }
229 
set_size_t(size_t value)230 JVMFlag::Error JVMFlag::set_size_t(size_t value) {
231   JVMFlag::Error error = check_writable(value!=get_size_t());
232   if (error == JVMFlag::SUCCESS) {
233     *((size_t*) _addr) = value;
234   }
235   return error;
236 }
237 
is_double() const238 bool JVMFlag::is_double() const {
239   return strcmp(_type, "double") == 0;
240 }
241 
get_double() const242 double JVMFlag::get_double() const {
243   return *((double*) _addr);
244 }
245 
set_double(double value)246 JVMFlag::Error JVMFlag::set_double(double value) {
247   JVMFlag::Error error = check_writable(value!=get_double());
248   if (error == JVMFlag::SUCCESS) {
249     *((double*) _addr) = value;
250   }
251   return error;
252 }
253 
is_ccstr() const254 bool JVMFlag::is_ccstr() const {
255   return strcmp(_type, "ccstr") == 0 || strcmp(_type, "ccstrlist") == 0;
256 }
257 
ccstr_accumulates() const258 bool JVMFlag::ccstr_accumulates() const {
259   return strcmp(_type, "ccstrlist") == 0;
260 }
261 
get_ccstr() const262 ccstr JVMFlag::get_ccstr() const {
263   return *((ccstr*) _addr);
264 }
265 
set_ccstr(ccstr value)266 JVMFlag::Error JVMFlag::set_ccstr(ccstr value) {
267   JVMFlag::Error error = check_writable(value!=get_ccstr());
268   if (error == JVMFlag::SUCCESS) {
269     *((ccstr*) _addr) = value;
270   }
271   return error;
272 }
273 
274 
get_origin()275 JVMFlag::Flags JVMFlag::get_origin() {
276   return Flags(_flags & VALUE_ORIGIN_MASK);
277 }
278 
set_origin(Flags origin)279 void JVMFlag::set_origin(Flags origin) {
280   assert((origin & VALUE_ORIGIN_MASK) == origin, "sanity");
281   Flags new_origin = Flags((origin == COMMAND_LINE) ? Flags(origin | ORIG_COMMAND_LINE) : origin);
282   _flags = Flags((_flags & ~VALUE_ORIGIN_MASK) | new_origin);
283 }
284 
is_default()285 bool JVMFlag::is_default() {
286   return (get_origin() == DEFAULT);
287 }
288 
is_ergonomic()289 bool JVMFlag::is_ergonomic() {
290   return (get_origin() == ERGONOMIC);
291 }
292 
is_command_line()293 bool JVMFlag::is_command_line() {
294   return (_flags & ORIG_COMMAND_LINE) != 0;
295 }
296 
is_jimage_resource()297 bool JVMFlag::is_jimage_resource() {
298   return (get_origin() == JIMAGE_RESOURCE);
299 }
300 
set_command_line()301 void JVMFlag::set_command_line() {
302   _flags = Flags(_flags | ORIG_COMMAND_LINE);
303 }
304 
is_product() const305 bool JVMFlag::is_product() const {
306   return (_flags & KIND_PRODUCT) != 0;
307 }
308 
is_manageable() const309 bool JVMFlag::is_manageable() const {
310   return (_flags & KIND_MANAGEABLE) != 0;
311 }
312 
is_diagnostic() const313 bool JVMFlag::is_diagnostic() const {
314   return (_flags & KIND_DIAGNOSTIC) != 0;
315 }
316 
is_experimental() const317 bool JVMFlag::is_experimental() const {
318   return (_flags & KIND_EXPERIMENTAL) != 0;
319 }
320 
is_notproduct() const321 bool JVMFlag::is_notproduct() const {
322   return (_flags & KIND_NOT_PRODUCT) != 0;
323 }
324 
is_develop() const325 bool JVMFlag::is_develop() const {
326   return (_flags & KIND_DEVELOP) != 0;
327 }
328 
is_read_write() const329 bool JVMFlag::is_read_write() const {
330   return (_flags & KIND_READ_WRITE) != 0;
331 }
332 
333 /**
334  * Returns if this flag is a constant in the binary.  Right now this is
335  * true for notproduct and develop flags in product builds.
336  */
is_constant_in_binary() const337 bool JVMFlag::is_constant_in_binary() const {
338 #ifdef PRODUCT
339   return is_notproduct() || is_develop();
340 #else
341   return false;
342 #endif
343 }
344 
is_unlocker() const345 bool JVMFlag::is_unlocker() const {
346   return strcmp(_name, "UnlockDiagnosticVMOptions") == 0     ||
347   strcmp(_name, "UnlockExperimentalVMOptions") == 0   ||
348   is_unlocker_ext();
349 }
350 
is_unlocked() const351 bool JVMFlag::is_unlocked() const {
352   if (is_diagnostic()) {
353     return UnlockDiagnosticVMOptions;
354   }
355   if (is_experimental()) {
356     return UnlockExperimentalVMOptions;
357   }
358   return is_unlocked_ext();
359 }
360 
clear_diagnostic()361 void JVMFlag::clear_diagnostic() {
362   assert(is_diagnostic(), "sanity");
363   _flags = Flags(_flags & ~KIND_DIAGNOSTIC);
364   assert(!is_diagnostic(), "sanity");
365 }
366 
367 // Get custom message for this locked flag, or NULL if
368 // none is available. Returns message type produced.
get_locked_message(char * buf,int buflen) const369 JVMFlag::MsgType JVMFlag::get_locked_message(char* buf, int buflen) const {
370   buf[0] = '\0';
371   if (is_diagnostic() && !is_unlocked()) {
372     jio_snprintf(buf, buflen,
373                  "Error: VM option '%s' is diagnostic and must be enabled via -XX:+UnlockDiagnosticVMOptions.\n"
374                  "Error: The unlock option must precede '%s'.\n",
375                  _name, _name);
376     return JVMFlag::DIAGNOSTIC_FLAG_BUT_LOCKED;
377   }
378   if (is_experimental() && !is_unlocked()) {
379     jio_snprintf(buf, buflen,
380                  "Error: VM option '%s' is experimental and must be enabled via -XX:+UnlockExperimentalVMOptions.\n"
381                  "Error: The unlock option must precede '%s'.\n",
382                  _name, _name);
383     return JVMFlag::EXPERIMENTAL_FLAG_BUT_LOCKED;
384   }
385   if (is_develop() && is_product_build()) {
386     jio_snprintf(buf, buflen, "Error: VM option '%s' is develop and is available only in debug version of VM.\n",
387                  _name);
388     return JVMFlag::DEVELOPER_FLAG_BUT_PRODUCT_BUILD;
389   }
390   if (is_notproduct() && is_product_build()) {
391     jio_snprintf(buf, buflen, "Error: VM option '%s' is notproduct and is available only in debug version of VM.\n",
392                  _name);
393     return JVMFlag::NOTPRODUCT_FLAG_BUT_PRODUCT_BUILD;
394   }
395   return get_locked_message_ext(buf, buflen);
396 }
397 
is_writeable() const398 bool JVMFlag::is_writeable() const {
399   return is_manageable() || (is_product() && is_read_write()) || is_writeable_ext();
400 }
401 
402 // All flags except "manageable" are assumed to be internal flags.
403 // Long term, we need to define a mechanism to specify which flags
404 // are external/stable and change this function accordingly.
is_external() const405 bool JVMFlag::is_external() const {
406   return is_manageable() || is_external_ext();
407 }
408 
409 // Helper function for JVMFlag::print_on().
410 // Fills current line up to requested position.
411 // Should the current position already be past the requested position,
412 // one separator blank is enforced.
fill_to_pos(outputStream * st,unsigned int req_pos)413 void fill_to_pos(outputStream* st, unsigned int req_pos) {
414   if ((unsigned int)st->position() < req_pos) {
415     st->fill_to(req_pos);  // need to fill with blanks to reach req_pos
416   } else {
417     st->print(" ");        // enforce blank separation. Previous field too long.
418   }
419 }
420 
print_on(outputStream * st,bool withComments,bool printRanges)421 void JVMFlag::print_on(outputStream* st, bool withComments, bool printRanges) {
422   // Don't print notproduct and develop flags in a product build.
423   if (is_constant_in_binary()) {
424     return;
425   }
426 
427   if (!printRanges) {
428     // The command line options -XX:+PrintFlags* cause this function to be called
429     // for each existing flag to print information pertinent to this flag. The data
430     // is displayed in columnar form, with the following layout:
431     //  col1 - data type, right-justified
432     //  col2 - name,      left-justified
433     //  col3 - ' ='       double-char, leading space to align with possible '+='
434     //  col4 - value      left-justified
435     //  col5 - kind       right-justified
436     //  col6 - origin     left-justified
437     //  col7 - comments   left-justified
438     //
439     //  The column widths are fixed. They are defined such that, for most cases,
440     //  an eye-pleasing tabular output is created.
441     //
442     //  Sample output:
443     //       bool CMSScavengeBeforeRemark                  = false                                     {product} {default}
444     //      uintx CMSScheduleRemarkEdenPenetration         = 50                                        {product} {default}
445     //     size_t CMSScheduleRemarkEdenSizeThreshold       = 2097152                                   {product} {default}
446     //      uintx CMSScheduleRemarkSamplingRatio           = 5                                         {product} {default}
447     //     double CMSSmallCoalSurplusPercent               = 1.050000                                  {product} {default}
448     //      ccstr CompileCommandFile                       = MyFile.cmd                                {product} {command line}
449     //  ccstrlist CompileOnly                              = Method1
450     //            CompileOnly                             += Method2                                   {product} {command line}
451     //  |         |                                       |  |                              |                    |               |
452     //  |         |                                       |  |                              |                    |               +-- col7
453     //  |         |                                       |  |                              |                    +-- col6
454     //  |         |                                       |  |                              +-- col5
455     //  |         |                                       |  +-- col4
456     //  |         |                                       +-- col3
457     //  |         +-- col2
458     //  +-- col1
459 
460     const unsigned int col_spacing = 1;
461     const unsigned int col1_pos    = 0;
462     const unsigned int col1_width  = 9;
463     const unsigned int col2_pos    = col1_pos + col1_width + col_spacing;
464     const unsigned int col2_width  = 39;
465     const unsigned int col3_pos    = col2_pos + col2_width + col_spacing;
466     const unsigned int col3_width  = 2;
467     const unsigned int col4_pos    = col3_pos + col3_width + col_spacing;
468     const unsigned int col4_width  = 30;
469     const unsigned int col5_pos    = col4_pos + col4_width + col_spacing;
470     const unsigned int col5_width  = 20;
471     const unsigned int col6_pos    = col5_pos + col5_width + col_spacing;
472     const unsigned int col6_width  = 15;
473     const unsigned int col7_pos    = col6_pos + col6_width + col_spacing;
474     const unsigned int col7_width  = 1;
475 
476     st->fill_to(col1_pos);
477     st->print("%*s", col1_width, _type);  // right-justified, therefore width is required.
478 
479     fill_to_pos(st, col2_pos);
480     st->print("%s", _name);
481 
482     fill_to_pos(st, col3_pos);
483     st->print(" =");  // use " =" for proper alignment with multiline ccstr output.
484 
485     fill_to_pos(st, col4_pos);
486     if (is_bool()) {
487       st->print("%s", get_bool() ? "true" : "false");
488     } else if (is_int()) {
489       st->print("%d", get_int());
490     } else if (is_uint()) {
491       st->print("%u", get_uint());
492     } else if (is_intx()) {
493       st->print(INTX_FORMAT, get_intx());
494     } else if (is_uintx()) {
495       st->print(UINTX_FORMAT, get_uintx());
496     } else if (is_uint64_t()) {
497       st->print(UINT64_FORMAT, get_uint64_t());
498     } else if (is_size_t()) {
499       st->print(SIZE_FORMAT, get_size_t());
500     } else if (is_double()) {
501       st->print("%f", get_double());
502     } else if (is_ccstr()) {
503       // Honor <newline> characters in ccstr: print multiple lines.
504       const char* cp = get_ccstr();
505       if (cp != NULL) {
506         const char* eol;
507         while ((eol = strchr(cp, '\n')) != NULL) {
508           size_t llen = pointer_delta(eol, cp, sizeof(char));
509           st->print("%.*s", (int)llen, cp);
510           st->cr();
511           cp = eol+1;
512           fill_to_pos(st, col2_pos);
513           st->print("%s", _name);
514           fill_to_pos(st, col3_pos);
515           st->print("+=");
516           fill_to_pos(st, col4_pos);
517         }
518         st->print("%s", cp);
519       }
520     } else {
521       st->print("unhandled  type %s", _type);
522       st->cr();
523       return;
524     }
525 
526     fill_to_pos(st, col5_pos);
527     print_kind(st, col5_width);
528 
529     fill_to_pos(st, col6_pos);
530     print_origin(st, col6_width);
531 
532 #ifndef PRODUCT
533     if (withComments) {
534       fill_to_pos(st, col7_pos);
535       st->print("%s", _doc);
536     }
537 #endif
538     st->cr();
539   } else if (!is_bool() && !is_ccstr()) {
540     // The command line options -XX:+PrintFlags* cause this function to be called
541     // for each existing flag to print information pertinent to this flag. The data
542     // is displayed in columnar form, with the following layout:
543     //  col1 - data type, right-justified
544     //  col2 - name,      left-justified
545     //  col4 - range      [ min ... max]
546     //  col5 - kind       right-justified
547     //  col6 - origin     left-justified
548     //  col7 - comments   left-justified
549     //
550     //  The column widths are fixed. They are defined such that, for most cases,
551     //  an eye-pleasing tabular output is created.
552     //
553     //  Sample output:
554     //       intx MinPassesBeforeFlush                               [ 0                         ...       9223372036854775807 ]                         {diagnostic} {default}
555     //      uintx MinRAMFraction                                     [ 1                         ...      18446744073709551615 ]                            {product} {default}
556     //     double MinRAMPercentage                                   [ 0.000                     ...                   100.000 ]                            {product} {default}
557     //      uintx MinSurvivorRatio                                   [ 3                         ...      18446744073709551615 ]                            {product} {default}
558     //     size_t MinTLABSize                                        [ 1                         ...       9223372036854775807 ]                            {product} {default}
559     //       intx MonitorBound                                       [ 0                         ...                2147483647 ]                            {product} {default}
560     //  |         |                                                  |                                                           |                                    |               |
561     //  |         |                                                  |                                                           |                                    |               +-- col7
562     //  |         |                                                  |                                                           |                                    +-- col6
563     //  |         |                                                  |                                                           +-- col5
564     //  |         |                                                  +-- col4
565     //  |         +-- col2
566     //  +-- col1
567 
568     const unsigned int col_spacing = 1;
569     const unsigned int col1_pos    = 0;
570     const unsigned int col1_width  = 9;
571     const unsigned int col2_pos    = col1_pos + col1_width + col_spacing;
572     const unsigned int col2_width  = 49;
573     const unsigned int col3_pos    = col2_pos + col2_width + col_spacing;
574     const unsigned int col3_width  = 0;
575     const unsigned int col4_pos    = col3_pos + col3_width + col_spacing;
576     const unsigned int col4_width  = 60;
577     const unsigned int col5_pos    = col4_pos + col4_width + col_spacing;
578     const unsigned int col5_width  = 35;
579     const unsigned int col6_pos    = col5_pos + col5_width + col_spacing;
580     const unsigned int col6_width  = 15;
581     const unsigned int col7_pos    = col6_pos + col6_width + col_spacing;
582     const unsigned int col7_width  = 1;
583 
584     st->fill_to(col1_pos);
585     st->print("%*s", col1_width, _type);  // right-justified, therefore width is required.
586 
587     fill_to_pos(st, col2_pos);
588     st->print("%s", _name);
589 
590     fill_to_pos(st, col4_pos);
591     RangeStrFunc func = NULL;
592     if (is_int()) {
593       func = JVMFlag::get_int_default_range_str;
594     } else if (is_uint()) {
595       func = JVMFlag::get_uint_default_range_str;
596     } else if (is_intx()) {
597       func = JVMFlag::get_intx_default_range_str;
598     } else if (is_uintx()) {
599       func = JVMFlag::get_uintx_default_range_str;
600     } else if (is_uint64_t()) {
601       func = JVMFlag::get_uint64_t_default_range_str;
602     } else if (is_size_t()) {
603       func = JVMFlag::get_size_t_default_range_str;
604     } else if (is_double()) {
605       func = JVMFlag::get_double_default_range_str;
606     } else {
607       st->print("unhandled  type %s", _type);
608       st->cr();
609       return;
610     }
611     JVMFlagRangeList::print(st, _name, func);
612 
613     fill_to_pos(st, col5_pos);
614     print_kind(st, col5_width);
615 
616     fill_to_pos(st, col6_pos);
617     print_origin(st, col6_width);
618 
619 #ifndef PRODUCT
620     if (withComments) {
621       fill_to_pos(st, col7_pos);
622       st->print("%s", _doc);
623     }
624 #endif
625     st->cr();
626   }
627 }
628 
print_kind(outputStream * st,unsigned int width)629 void JVMFlag::print_kind(outputStream* st, unsigned int width) {
630   struct Data {
631     int flag;
632     const char* name;
633   };
634 
635   Data data[] = {
636     { KIND_JVMCI, "JVMCI" },
637     { KIND_C1, "C1" },
638     { KIND_C2, "C2" },
639     { KIND_ARCH, "ARCH" },
640     { KIND_PLATFORM_DEPENDENT, "pd" },
641     { KIND_PRODUCT, "product" },
642     { KIND_MANAGEABLE, "manageable" },
643     { KIND_DIAGNOSTIC, "diagnostic" },
644     { KIND_EXPERIMENTAL, "experimental" },
645     { KIND_NOT_PRODUCT, "notproduct" },
646     { KIND_DEVELOP, "develop" },
647     { KIND_LP64_PRODUCT, "lp64_product" },
648     { KIND_READ_WRITE, "rw" },
649     { -1, "" }
650   };
651 
652   if ((_flags & KIND_MASK) != 0) {
653     bool is_first = true;
654     const size_t buffer_size = 64;
655     size_t buffer_used = 0;
656     char kind[buffer_size];
657 
658     jio_snprintf(kind, buffer_size, "{");
659     buffer_used++;
660     for (int i = 0; data[i].flag != -1; i++) {
661       Data d = data[i];
662       if ((_flags & d.flag) != 0) {
663         if (is_first) {
664           is_first = false;
665         } else {
666           assert(buffer_used + 1 < buffer_size, "Too small buffer");
667           jio_snprintf(kind + buffer_used, buffer_size - buffer_used, " ");
668           buffer_used++;
669         }
670         size_t length = strlen(d.name);
671         assert(buffer_used + length < buffer_size, "Too small buffer");
672         jio_snprintf(kind + buffer_used, buffer_size - buffer_used, "%s", d.name);
673         buffer_used += length;
674       }
675     }
676     assert(buffer_used + 2 <= buffer_size, "Too small buffer");
677     jio_snprintf(kind + buffer_used, buffer_size - buffer_used, "}");
678     st->print("%*s", width, kind);
679   }
680 }
681 
print_origin(outputStream * st,unsigned int width)682 void JVMFlag::print_origin(outputStream* st, unsigned int width) {
683   int origin = _flags & VALUE_ORIGIN_MASK;
684   st->print("{");
685   switch(origin) {
686     case DEFAULT:
687       st->print("default"); break;
688     case COMMAND_LINE:
689       st->print("command line"); break;
690     case ENVIRON_VAR:
691       st->print("environment"); break;
692     case CONFIG_FILE:
693       st->print("config file"); break;
694     case MANAGEMENT:
695       st->print("management"); break;
696     case ERGONOMIC:
697       if (_flags & ORIG_COMMAND_LINE) {
698         st->print("command line, ");
699       }
700       st->print("ergonomic"); break;
701     case ATTACH_ON_DEMAND:
702       st->print("attach"); break;
703     case INTERNAL:
704       st->print("internal"); break;
705     case JIMAGE_RESOURCE:
706       st->print("jimage"); break;
707   }
708   st->print("}");
709 }
710 
print_as_flag(outputStream * st)711 void JVMFlag::print_as_flag(outputStream* st) {
712   if (is_bool()) {
713     st->print("-XX:%s%s", get_bool() ? "+" : "-", _name);
714   } else if (is_int()) {
715     st->print("-XX:%s=%d", _name, get_int());
716   } else if (is_uint()) {
717     st->print("-XX:%s=%u", _name, get_uint());
718   } else if (is_intx()) {
719     st->print("-XX:%s=" INTX_FORMAT, _name, get_intx());
720   } else if (is_uintx()) {
721     st->print("-XX:%s=" UINTX_FORMAT, _name, get_uintx());
722   } else if (is_uint64_t()) {
723     st->print("-XX:%s=" UINT64_FORMAT, _name, get_uint64_t());
724   } else if (is_size_t()) {
725     st->print("-XX:%s=" SIZE_FORMAT, _name, get_size_t());
726   } else if (is_double()) {
727     st->print("-XX:%s=%f", _name, get_double());
728   } else if (is_ccstr()) {
729     st->print("-XX:%s=", _name);
730     const char* cp = get_ccstr();
731     if (cp != NULL) {
732       // Need to turn embedded '\n's back into separate arguments
733       // Not so efficient to print one character at a time,
734       // but the choice is to do the transformation to a buffer
735       // and print that.  And this need not be efficient.
736       for (; *cp != '\0'; cp += 1) {
737         switch (*cp) {
738           default:
739             st->print("%c", *cp);
740             break;
741           case '\n':
742             st->print(" -XX:%s=", _name);
743             break;
744         }
745       }
746     }
747   } else {
748     ShouldNotReachHere();
749   }
750 }
751 
flag_error_str(JVMFlag::Error error)752 const char* JVMFlag::flag_error_str(JVMFlag::Error error) {
753   switch (error) {
754     case JVMFlag::MISSING_NAME: return "MISSING_NAME";
755     case JVMFlag::MISSING_VALUE: return "MISSING_VALUE";
756     case JVMFlag::NON_WRITABLE: return "NON_WRITABLE";
757     case JVMFlag::OUT_OF_BOUNDS: return "OUT_OF_BOUNDS";
758     case JVMFlag::VIOLATES_CONSTRAINT: return "VIOLATES_CONSTRAINT";
759     case JVMFlag::INVALID_FLAG: return "INVALID_FLAG";
760     case JVMFlag::ERR_OTHER: return "ERR_OTHER";
761     case JVMFlag::SUCCESS: return "SUCCESS";
762     default: ShouldNotReachHere(); return "NULL";
763   }
764 }
765 
766 // 4991491 do not "optimize out" the was_set false values: omitting them
767 // tickles a Microsoft compiler bug causing flagTable to be malformed
768 
769 #define RUNTIME_PRODUCT_FLAG_STRUCT(     type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_PRODUCT) },
770 #define RUNTIME_PD_PRODUCT_FLAG_STRUCT(  type, name,        doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_PRODUCT | JVMFlag::KIND_PLATFORM_DEPENDENT) },
771 #define RUNTIME_DIAGNOSTIC_FLAG_STRUCT(  type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_DIAGNOSTIC) },
772 #define RUNTIME_PD_DIAGNOSTIC_FLAG_STRUCT(type, name,       doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_DIAGNOSTIC | JVMFlag::KIND_PLATFORM_DEPENDENT) },
773 #define RUNTIME_EXPERIMENTAL_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_EXPERIMENTAL) },
774 #define RUNTIME_MANAGEABLE_FLAG_STRUCT(  type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_MANAGEABLE) },
775 #define RUNTIME_PRODUCT_RW_FLAG_STRUCT(  type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_PRODUCT | JVMFlag::KIND_READ_WRITE) },
776 #define RUNTIME_DEVELOP_FLAG_STRUCT(     type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_DEVELOP) },
777 #define RUNTIME_PD_DEVELOP_FLAG_STRUCT(  type, name,        doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_DEVELOP | JVMFlag::KIND_PLATFORM_DEPENDENT) },
778 #define RUNTIME_NOTPRODUCT_FLAG_STRUCT(  type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_NOT_PRODUCT) },
779 
780 #define JVMCI_PRODUCT_FLAG_STRUCT(       type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_PRODUCT) },
781 #define JVMCI_PD_PRODUCT_FLAG_STRUCT(    type, name,        doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_PRODUCT | JVMFlag::KIND_PLATFORM_DEPENDENT) },
782 #define JVMCI_DIAGNOSTIC_FLAG_STRUCT(    type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_DIAGNOSTIC) },
783 #define JVMCI_PD_DIAGNOSTIC_FLAG_STRUCT( type, name,        doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_DIAGNOSTIC | JVMFlag::KIND_PLATFORM_DEPENDENT) },
784 #define JVMCI_EXPERIMENTAL_FLAG_STRUCT(  type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_EXPERIMENTAL) },
785 #define JVMCI_DEVELOP_FLAG_STRUCT(       type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_DEVELOP) },
786 #define JVMCI_PD_DEVELOP_FLAG_STRUCT(    type, name,        doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_DEVELOP | JVMFlag::KIND_PLATFORM_DEPENDENT) },
787 #define JVMCI_NOTPRODUCT_FLAG_STRUCT(    type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_JVMCI | JVMFlag::KIND_NOT_PRODUCT) },
788 
789 #ifdef _LP64
790 #define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_LP64_PRODUCT) },
791 #else
792 #define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) /* flag is constant */
793 #endif // _LP64
794 
795 #define C1_PRODUCT_FLAG_STRUCT(          type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_PRODUCT) },
796 #define C1_PD_PRODUCT_FLAG_STRUCT(       type, name,        doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_PRODUCT | JVMFlag::KIND_PLATFORM_DEPENDENT) },
797 #define C1_DIAGNOSTIC_FLAG_STRUCT(       type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_DIAGNOSTIC) },
798 #define C1_PD_DIAGNOSTIC_FLAG_STRUCT(    type, name,        doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_DIAGNOSTIC | JVMFlag::KIND_PLATFORM_DEPENDENT) },
799 #define C1_DEVELOP_FLAG_STRUCT(          type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_DEVELOP) },
800 #define C1_PD_DEVELOP_FLAG_STRUCT(       type, name,        doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_DEVELOP | JVMFlag::KIND_PLATFORM_DEPENDENT) },
801 #define C1_NOTPRODUCT_FLAG_STRUCT(       type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C1 | JVMFlag::KIND_NOT_PRODUCT) },
802 
803 #define C2_PRODUCT_FLAG_STRUCT(          type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_PRODUCT) },
804 #define C2_PD_PRODUCT_FLAG_STRUCT(       type, name,        doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_PRODUCT | JVMFlag::KIND_PLATFORM_DEPENDENT) },
805 #define C2_DIAGNOSTIC_FLAG_STRUCT(       type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_DIAGNOSTIC) },
806 #define C2_PD_DIAGNOSTIC_FLAG_STRUCT(    type, name,        doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_DIAGNOSTIC | JVMFlag::KIND_PLATFORM_DEPENDENT) },
807 #define C2_EXPERIMENTAL_FLAG_STRUCT(     type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_EXPERIMENTAL) },
808 #define C2_DEVELOP_FLAG_STRUCT(          type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_DEVELOP) },
809 #define C2_PD_DEVELOP_FLAG_STRUCT(       type, name,        doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_DEVELOP | JVMFlag::KIND_PLATFORM_DEPENDENT) },
810 #define C2_NOTPRODUCT_FLAG_STRUCT(       type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_C2 | JVMFlag::KIND_NOT_PRODUCT) },
811 
812 #define ARCH_PRODUCT_FLAG_STRUCT(        type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_ARCH | JVMFlag::KIND_PRODUCT) },
813 #define ARCH_DIAGNOSTIC_FLAG_STRUCT(     type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_ARCH | JVMFlag::KIND_DIAGNOSTIC) },
814 #define ARCH_EXPERIMENTAL_FLAG_STRUCT(   type, name, value, doc) { #type, XSTR(name), &name,         NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_ARCH | JVMFlag::KIND_EXPERIMENTAL) },
815 #define ARCH_DEVELOP_FLAG_STRUCT(        type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_ARCH | JVMFlag::KIND_DEVELOP) },
816 #define ARCH_NOTPRODUCT_FLAG_STRUCT(     type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) JVMFlag::Flags(JVMFlag::DEFAULT | JVMFlag::KIND_ARCH | JVMFlag::KIND_NOT_PRODUCT) },
817 
818 static JVMFlag flagTable[] = {
819   VM_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, \
820            RUNTIME_PD_DEVELOP_FLAG_STRUCT, \
821            RUNTIME_PRODUCT_FLAG_STRUCT, \
822            RUNTIME_PD_PRODUCT_FLAG_STRUCT, \
823            RUNTIME_DIAGNOSTIC_FLAG_STRUCT, \
824            RUNTIME_PD_DIAGNOSTIC_FLAG_STRUCT, \
825            RUNTIME_EXPERIMENTAL_FLAG_STRUCT, \
826            RUNTIME_NOTPRODUCT_FLAG_STRUCT, \
827            RUNTIME_MANAGEABLE_FLAG_STRUCT, \
828            RUNTIME_PRODUCT_RW_FLAG_STRUCT, \
829            RUNTIME_LP64_PRODUCT_FLAG_STRUCT, \
830            IGNORE_RANGE, \
831            IGNORE_CONSTRAINT, \
832            IGNORE_WRITEABLE)
833 
834   RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, \
835                    RUNTIME_PD_DEVELOP_FLAG_STRUCT, \
836                    RUNTIME_PRODUCT_FLAG_STRUCT, \
837                    RUNTIME_PD_PRODUCT_FLAG_STRUCT, \
838                    RUNTIME_DIAGNOSTIC_FLAG_STRUCT, \
839                    RUNTIME_PD_DIAGNOSTIC_FLAG_STRUCT, \
840                    RUNTIME_NOTPRODUCT_FLAG_STRUCT, \
841                    IGNORE_RANGE, \
842                    IGNORE_CONSTRAINT, \
843                    IGNORE_WRITEABLE)
844 #if INCLUDE_JVMCI
845   JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_STRUCT, \
846               JVMCI_PD_DEVELOP_FLAG_STRUCT, \
847               JVMCI_PRODUCT_FLAG_STRUCT, \
848               JVMCI_PD_PRODUCT_FLAG_STRUCT, \
849               JVMCI_DIAGNOSTIC_FLAG_STRUCT, \
850               JVMCI_PD_DIAGNOSTIC_FLAG_STRUCT, \
851               JVMCI_EXPERIMENTAL_FLAG_STRUCT, \
852               JVMCI_NOTPRODUCT_FLAG_STRUCT, \
853               IGNORE_RANGE, \
854               IGNORE_CONSTRAINT, \
855               IGNORE_WRITEABLE)
856 #endif // INCLUDE_JVMCI
857 #ifdef COMPILER1
858   C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, \
859            C1_PD_DEVELOP_FLAG_STRUCT, \
860            C1_PRODUCT_FLAG_STRUCT, \
861            C1_PD_PRODUCT_FLAG_STRUCT, \
862            C1_DIAGNOSTIC_FLAG_STRUCT, \
863            C1_PD_DIAGNOSTIC_FLAG_STRUCT, \
864            C1_NOTPRODUCT_FLAG_STRUCT, \
865            IGNORE_RANGE, \
866            IGNORE_CONSTRAINT, \
867            IGNORE_WRITEABLE)
868 #endif // COMPILER1
869 #ifdef COMPILER2
870   C2_FLAGS(C2_DEVELOP_FLAG_STRUCT, \
871            C2_PD_DEVELOP_FLAG_STRUCT, \
872            C2_PRODUCT_FLAG_STRUCT, \
873            C2_PD_PRODUCT_FLAG_STRUCT, \
874            C2_DIAGNOSTIC_FLAG_STRUCT, \
875            C2_PD_DIAGNOSTIC_FLAG_STRUCT, \
876            C2_EXPERIMENTAL_FLAG_STRUCT, \
877            C2_NOTPRODUCT_FLAG_STRUCT, \
878            IGNORE_RANGE, \
879            IGNORE_CONSTRAINT, \
880            IGNORE_WRITEABLE)
881 #endif // COMPILER2
882   ARCH_FLAGS(ARCH_DEVELOP_FLAG_STRUCT, \
883              ARCH_PRODUCT_FLAG_STRUCT, \
884              ARCH_DIAGNOSTIC_FLAG_STRUCT, \
885              ARCH_EXPERIMENTAL_FLAG_STRUCT, \
886              ARCH_NOTPRODUCT_FLAG_STRUCT, \
887              IGNORE_RANGE, \
888              IGNORE_CONSTRAINT, \
889              IGNORE_WRITEABLE)
890   FLAGTABLE_EXT
891   {0, NULL, NULL}
892 };
893 
894 JVMFlag* JVMFlag::flags = flagTable;
895 size_t JVMFlag::numFlags = (sizeof(flagTable) / sizeof(JVMFlag));
896 
str_equal(const char * s,size_t s_len,const char * q,size_t q_len)897 inline bool str_equal(const char* s, size_t s_len, const char* q, size_t q_len) {
898   if (s_len != q_len) return false;
899   return memcmp(s, q, q_len) == 0;
900 }
901 
902 // Search the flag table for a named flag
find_flag(const char * name,size_t length,bool allow_locked,bool return_flag)903 JVMFlag* JVMFlag::find_flag(const char* name, size_t length, bool allow_locked, bool return_flag) {
904   for (JVMFlag* current = &flagTable[0]; current->_name != NULL; current++) {
905     if (str_equal(current->_name, current->get_name_length(), name, length)) {
906       // Found a matching entry.
907       // Don't report notproduct and develop flags in product builds.
908       if (current->is_constant_in_binary()) {
909         return (return_flag ? current : NULL);
910       }
911       // Report locked flags only if allowed.
912       if (!(current->is_unlocked() || current->is_unlocker())) {
913         if (!allow_locked) {
914           // disable use of locked flags, e.g. diagnostic, experimental,
915           // etc. until they are explicitly unlocked
916           return NULL;
917         }
918       }
919       return current;
920     }
921   }
922   // JVMFlag name is not in the flag table
923   return NULL;
924 }
925 
926 // Get or compute the flag name length
get_name_length()927 size_t JVMFlag::get_name_length() {
928   if (_name_len == 0) {
929     _name_len = strlen(_name);
930   }
931   return _name_len;
932 }
933 
fuzzy_match(const char * name,size_t length,bool allow_locked)934 JVMFlag* JVMFlag::fuzzy_match(const char* name, size_t length, bool allow_locked) {
935   float VMOptionsFuzzyMatchSimilarity = 0.7f;
936   JVMFlag* match = NULL;
937   float score;
938   float max_score = -1;
939 
940   for (JVMFlag* current = &flagTable[0]; current->_name != NULL; current++) {
941     score = StringUtils::similarity(current->_name, strlen(current->_name), name, length);
942     if (score > max_score) {
943       max_score = score;
944       match = current;
945     }
946   }
947 
948   if (match == NULL) {
949     return NULL;
950   }
951 
952   if (!(match->is_unlocked() || match->is_unlocker())) {
953     if (!allow_locked) {
954       return NULL;
955     }
956   }
957 
958   if (max_score < VMOptionsFuzzyMatchSimilarity) {
959     return NULL;
960   }
961 
962   return match;
963 }
964 
965 // Returns the address of the index'th element
address_of_flag(JVMFlagsWithType flag)966 static JVMFlag* address_of_flag(JVMFlagsWithType flag) {
967   assert((size_t)flag < JVMFlag::numFlags, "bad command line flag index");
968   return &JVMFlag::flags[flag];
969 }
970 
is_default(JVMFlags flag)971 bool JVMFlagEx::is_default(JVMFlags flag) {
972   assert((size_t)flag < JVMFlag::numFlags, "bad command line flag index");
973   JVMFlag* f = &JVMFlag::flags[flag];
974   return f->is_default();
975 }
976 
is_ergo(JVMFlags flag)977 bool JVMFlagEx::is_ergo(JVMFlags flag) {
978   assert((size_t)flag < JVMFlag::numFlags, "bad command line flag index");
979   JVMFlag* f = &JVMFlag::flags[flag];
980   return f->is_ergonomic();
981 }
982 
is_cmdline(JVMFlags flag)983 bool JVMFlagEx::is_cmdline(JVMFlags flag) {
984   assert((size_t)flag < JVMFlag::numFlags, "bad command line flag index");
985   JVMFlag* f = &JVMFlag::flags[flag];
986   return f->is_command_line();
987 }
988 
wasSetOnCmdline(const char * name,bool * value)989 bool JVMFlag::wasSetOnCmdline(const char* name, bool* value) {
990   JVMFlag* result = JVMFlag::find_flag((char*)name, strlen(name));
991   if (result == NULL) return false;
992   *value = result->is_command_line();
993   return true;
994 }
995 
is_jimage_resource(JVMFlags flag)996 bool JVMFlagEx::is_jimage_resource(JVMFlags flag) {
997   assert((size_t)flag < JVMFlag::numFlags, "bad command line flag index");
998   JVMFlag* f = &JVMFlag::flags[flag];
999   return f->is_jimage_resource();
1000 }
1001 
setOnCmdLine(JVMFlagsWithType flag)1002 void JVMFlagEx::setOnCmdLine(JVMFlagsWithType flag) {
1003   JVMFlag* faddr = address_of_flag(flag);
1004   assert(faddr != NULL, "Unknown flag");
1005   faddr->set_command_line();
1006 }
1007 
1008 template<class E, class T>
trace_flag_changed(const char * name,const T old_value,const T new_value,const JVMFlag::Flags origin)1009 static void trace_flag_changed(const char* name, const T old_value, const T new_value, const JVMFlag::Flags origin) {
1010   E e;
1011   e.set_name(name);
1012   e.set_oldValue(old_value);
1013   e.set_newValue(new_value);
1014   e.set_origin(origin);
1015   e.commit();
1016 }
1017 
apply_constraint_and_check_range_bool(const char * name,bool new_value,bool verbose)1018 static JVMFlag::Error apply_constraint_and_check_range_bool(const char* name, bool new_value, bool verbose) {
1019   JVMFlag::Error status = JVMFlag::SUCCESS;
1020   JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
1021   if (constraint != NULL) {
1022     status = constraint->apply_bool(new_value, verbose);
1023   }
1024   return status;
1025 }
1026 
boolAt(const char * name,size_t len,bool * value,bool allow_locked,bool return_flag)1027 JVMFlag::Error JVMFlag::boolAt(const char* name, size_t len, bool* value, bool allow_locked, bool return_flag) {
1028   JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
1029   if (result == NULL) return JVMFlag::INVALID_FLAG;
1030   if (!result->is_bool()) return JVMFlag::WRONG_FORMAT;
1031   *value = result->get_bool();
1032   return JVMFlag::SUCCESS;
1033 }
1034 
boolAtPut(JVMFlag * flag,bool * value,JVMFlag::Flags origin)1035 JVMFlag::Error JVMFlag::boolAtPut(JVMFlag* flag, bool* value, JVMFlag::Flags origin) {
1036   const char* name;
1037   if (flag == NULL) return JVMFlag::INVALID_FLAG;
1038   if (!flag->is_bool()) return JVMFlag::WRONG_FORMAT;
1039   name = flag->_name;
1040   JVMFlag::Error check = apply_constraint_and_check_range_bool(name, *value, !JVMFlagConstraintList::validated_after_ergo());
1041   if (check != JVMFlag::SUCCESS) return check;
1042   bool old_value = flag->get_bool();
1043   trace_flag_changed<EventBooleanFlagChanged, bool>(name, old_value, *value, origin);
1044   check = flag->set_bool(*value);
1045   *value = old_value;
1046   flag->set_origin(origin);
1047   return check;
1048 }
1049 
boolAtPut(const char * name,size_t len,bool * value,JVMFlag::Flags origin)1050 JVMFlag::Error JVMFlag::boolAtPut(const char* name, size_t len, bool* value, JVMFlag::Flags origin) {
1051   JVMFlag* result = JVMFlag::find_flag(name, len);
1052   return boolAtPut(result, value, origin);
1053 }
1054 
boolAtPut(JVMFlagsWithType flag,bool value,JVMFlag::Flags origin)1055 JVMFlag::Error JVMFlagEx::boolAtPut(JVMFlagsWithType flag, bool value, JVMFlag::Flags origin) {
1056   JVMFlag* faddr = address_of_flag(flag);
1057   guarantee(faddr != NULL && faddr->is_bool(), "wrong flag type");
1058   return JVMFlag::boolAtPut(faddr, &value, origin);
1059 }
1060 
apply_constraint_and_check_range_int(const char * name,int new_value,bool verbose)1061 static JVMFlag::Error apply_constraint_and_check_range_int(const char* name, int new_value, bool verbose) {
1062   JVMFlag::Error status = JVMFlag::SUCCESS;
1063   JVMFlagRange* range = JVMFlagRangeList::find(name);
1064   if (range != NULL) {
1065     status = range->check_int(new_value, verbose);
1066   }
1067   if (status == JVMFlag::SUCCESS) {
1068     JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
1069     if (constraint != NULL) {
1070       status = constraint->apply_int(new_value, verbose);
1071     }
1072   }
1073   return status;
1074 }
1075 
intAt(const char * name,size_t len,int * value,bool allow_locked,bool return_flag)1076 JVMFlag::Error JVMFlag::intAt(const char* name, size_t len, int* value, bool allow_locked, bool return_flag) {
1077   JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
1078   if (result == NULL) return JVMFlag::INVALID_FLAG;
1079   if (!result->is_int()) return JVMFlag::WRONG_FORMAT;
1080   *value = result->get_int();
1081   return JVMFlag::SUCCESS;
1082 }
1083 
intAtPut(JVMFlag * flag,int * value,JVMFlag::Flags origin)1084 JVMFlag::Error JVMFlag::intAtPut(JVMFlag* flag, int* value, JVMFlag::Flags origin) {
1085   const char* name;
1086   if (flag == NULL) return JVMFlag::INVALID_FLAG;
1087   if (!flag->is_int()) return JVMFlag::WRONG_FORMAT;
1088   name = flag->_name;
1089   JVMFlag::Error check = apply_constraint_and_check_range_int(name, *value, !JVMFlagConstraintList::validated_after_ergo());
1090   if (check != JVMFlag::SUCCESS) return check;
1091   int old_value = flag->get_int();
1092   trace_flag_changed<EventIntFlagChanged, s4>(name, old_value, *value, origin);
1093   check = flag->set_int(*value);
1094   *value = old_value;
1095   flag->set_origin(origin);
1096   return check;
1097 }
1098 
intAtPut(const char * name,size_t len,int * value,JVMFlag::Flags origin)1099 JVMFlag::Error JVMFlag::intAtPut(const char* name, size_t len, int* value, JVMFlag::Flags origin) {
1100   JVMFlag* result = JVMFlag::find_flag(name, len);
1101   return intAtPut(result, value, origin);
1102 }
1103 
intAtPut(JVMFlagsWithType flag,int value,JVMFlag::Flags origin)1104 JVMFlag::Error JVMFlagEx::intAtPut(JVMFlagsWithType flag, int value, JVMFlag::Flags origin) {
1105   JVMFlag* faddr = address_of_flag(flag);
1106   guarantee(faddr != NULL && faddr->is_int(), "wrong flag type");
1107   return JVMFlag::intAtPut(faddr, &value, origin);
1108 }
1109 
apply_constraint_and_check_range_uint(const char * name,uint new_value,bool verbose)1110 static JVMFlag::Error apply_constraint_and_check_range_uint(const char* name, uint new_value, bool verbose) {
1111   JVMFlag::Error status = JVMFlag::SUCCESS;
1112   JVMFlagRange* range = JVMFlagRangeList::find(name);
1113   if (range != NULL) {
1114     status = range->check_uint(new_value, verbose);
1115   }
1116   if (status == JVMFlag::SUCCESS) {
1117     JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
1118     if (constraint != NULL) {
1119       status = constraint->apply_uint(new_value, verbose);
1120     }
1121   }
1122   return status;
1123 }
1124 
uintAt(const char * name,size_t len,uint * value,bool allow_locked,bool return_flag)1125 JVMFlag::Error JVMFlag::uintAt(const char* name, size_t len, uint* value, bool allow_locked, bool return_flag) {
1126   JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
1127   if (result == NULL) return JVMFlag::INVALID_FLAG;
1128   if (!result->is_uint()) return JVMFlag::WRONG_FORMAT;
1129   *value = result->get_uint();
1130   return JVMFlag::SUCCESS;
1131 }
1132 
uintAtPut(JVMFlag * flag,uint * value,JVMFlag::Flags origin)1133 JVMFlag::Error JVMFlag::uintAtPut(JVMFlag* flag, uint* value, JVMFlag::Flags origin) {
1134   const char* name;
1135   if (flag == NULL) return JVMFlag::INVALID_FLAG;
1136   if (!flag->is_uint()) return JVMFlag::WRONG_FORMAT;
1137   name = flag->_name;
1138   JVMFlag::Error check = apply_constraint_and_check_range_uint(name, *value, !JVMFlagConstraintList::validated_after_ergo());
1139   if (check != JVMFlag::SUCCESS) return check;
1140   uint old_value = flag->get_uint();
1141   trace_flag_changed<EventUnsignedIntFlagChanged, u4>(name, old_value, *value, origin);
1142   check = flag->set_uint(*value);
1143   *value = old_value;
1144   flag->set_origin(origin);
1145   return check;
1146 }
1147 
uintAtPut(const char * name,size_t len,uint * value,JVMFlag::Flags origin)1148 JVMFlag::Error JVMFlag::uintAtPut(const char* name, size_t len, uint* value, JVMFlag::Flags origin) {
1149   JVMFlag* result = JVMFlag::find_flag(name, len);
1150   return uintAtPut(result, value, origin);
1151 }
1152 
uintAtPut(JVMFlagsWithType flag,uint value,JVMFlag::Flags origin)1153 JVMFlag::Error JVMFlagEx::uintAtPut(JVMFlagsWithType flag, uint value, JVMFlag::Flags origin) {
1154   JVMFlag* faddr = address_of_flag(flag);
1155   guarantee(faddr != NULL && faddr->is_uint(), "wrong flag type");
1156   return JVMFlag::uintAtPut(faddr, &value, origin);
1157 }
1158 
intxAt(const char * name,size_t len,intx * value,bool allow_locked,bool return_flag)1159 JVMFlag::Error JVMFlag::intxAt(const char* name, size_t len, intx* value, bool allow_locked, bool return_flag) {
1160   JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
1161   if (result == NULL) return JVMFlag::INVALID_FLAG;
1162   if (!result->is_intx()) return JVMFlag::WRONG_FORMAT;
1163   *value = result->get_intx();
1164   return JVMFlag::SUCCESS;
1165 }
1166 
apply_constraint_and_check_range_intx(const char * name,intx new_value,bool verbose)1167 static JVMFlag::Error apply_constraint_and_check_range_intx(const char* name, intx new_value, bool verbose) {
1168   JVMFlag::Error status = JVMFlag::SUCCESS;
1169   JVMFlagRange* range = JVMFlagRangeList::find(name);
1170   if (range != NULL) {
1171     status = range->check_intx(new_value, verbose);
1172   }
1173   if (status == JVMFlag::SUCCESS) {
1174     JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
1175     if (constraint != NULL) {
1176       status = constraint->apply_intx(new_value, verbose);
1177     }
1178   }
1179   return status;
1180 }
1181 
intxAtPut(JVMFlag * flag,intx * value,JVMFlag::Flags origin)1182 JVMFlag::Error JVMFlag::intxAtPut(JVMFlag* flag, intx* value, JVMFlag::Flags origin) {
1183   const char* name;
1184   if (flag == NULL) return JVMFlag::INVALID_FLAG;
1185   if (!flag->is_intx()) return JVMFlag::WRONG_FORMAT;
1186   name = flag->_name;
1187   JVMFlag::Error check = apply_constraint_and_check_range_intx(name, *value, !JVMFlagConstraintList::validated_after_ergo());
1188   if (check != JVMFlag::SUCCESS) return check;
1189   intx old_value = flag->get_intx();
1190   trace_flag_changed<EventLongFlagChanged, intx>(name, old_value, *value, origin);
1191   check = flag->set_intx(*value);
1192   *value = old_value;
1193   flag->set_origin(origin);
1194   return check;
1195 }
1196 
intxAtPut(const char * name,size_t len,intx * value,JVMFlag::Flags origin)1197 JVMFlag::Error JVMFlag::intxAtPut(const char* name, size_t len, intx* value, JVMFlag::Flags origin) {
1198   JVMFlag* result = JVMFlag::find_flag(name, len);
1199   return intxAtPut(result, value, origin);
1200 }
1201 
intxAtPut(JVMFlagsWithType flag,intx value,JVMFlag::Flags origin)1202 JVMFlag::Error JVMFlagEx::intxAtPut(JVMFlagsWithType flag, intx value, JVMFlag::Flags origin) {
1203   JVMFlag* faddr = address_of_flag(flag);
1204   guarantee(faddr != NULL && faddr->is_intx(), "wrong flag type");
1205   return JVMFlag::intxAtPut(faddr, &value, origin);
1206 }
1207 
uintxAt(const char * name,size_t len,uintx * value,bool allow_locked,bool return_flag)1208 JVMFlag::Error JVMFlag::uintxAt(const char* name, size_t len, uintx* value, bool allow_locked, bool return_flag) {
1209   JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
1210   if (result == NULL) return JVMFlag::INVALID_FLAG;
1211   if (!result->is_uintx()) return JVMFlag::WRONG_FORMAT;
1212   *value = result->get_uintx();
1213   return JVMFlag::SUCCESS;
1214 }
1215 
apply_constraint_and_check_range_uintx(const char * name,uintx new_value,bool verbose)1216 static JVMFlag::Error apply_constraint_and_check_range_uintx(const char* name, uintx new_value, bool verbose) {
1217   JVMFlag::Error status = JVMFlag::SUCCESS;
1218   JVMFlagRange* range = JVMFlagRangeList::find(name);
1219   if (range != NULL) {
1220     status = range->check_uintx(new_value, verbose);
1221   }
1222   if (status == JVMFlag::SUCCESS) {
1223     JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
1224     if (constraint != NULL) {
1225       status = constraint->apply_uintx(new_value, verbose);
1226     }
1227   }
1228   return status;
1229 }
1230 
uintxAtPut(JVMFlag * flag,uintx * value,JVMFlag::Flags origin)1231 JVMFlag::Error JVMFlag::uintxAtPut(JVMFlag* flag, uintx* value, JVMFlag::Flags origin) {
1232   const char* name;
1233   if (flag == NULL) return JVMFlag::INVALID_FLAG;
1234   if (!flag->is_uintx()) return JVMFlag::WRONG_FORMAT;
1235   name = flag->_name;
1236   JVMFlag::Error check = apply_constraint_and_check_range_uintx(name, *value, !JVMFlagConstraintList::validated_after_ergo());
1237   if (check != JVMFlag::SUCCESS) return check;
1238   uintx old_value = flag->get_uintx();
1239   trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
1240   check = flag->set_uintx(*value);
1241   *value = old_value;
1242   flag->set_origin(origin);
1243   return check;
1244 }
1245 
uintxAtPut(const char * name,size_t len,uintx * value,JVMFlag::Flags origin)1246 JVMFlag::Error JVMFlag::uintxAtPut(const char* name, size_t len, uintx* value, JVMFlag::Flags origin) {
1247   JVMFlag* result = JVMFlag::find_flag(name, len);
1248   return uintxAtPut(result, value, origin);
1249 }
1250 
uintxAtPut(JVMFlagsWithType flag,uintx value,JVMFlag::Flags origin)1251 JVMFlag::Error JVMFlagEx::uintxAtPut(JVMFlagsWithType flag, uintx value, JVMFlag::Flags origin) {
1252   JVMFlag* faddr = address_of_flag(flag);
1253   guarantee(faddr != NULL && faddr->is_uintx(), "wrong flag type");
1254   return JVMFlag::uintxAtPut(faddr, &value, origin);
1255 }
1256 
uint64_tAt(const char * name,size_t len,uint64_t * value,bool allow_locked,bool return_flag)1257 JVMFlag::Error JVMFlag::uint64_tAt(const char* name, size_t len, uint64_t* value, bool allow_locked, bool return_flag) {
1258   JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
1259   if (result == NULL) return JVMFlag::INVALID_FLAG;
1260   if (!result->is_uint64_t()) return JVMFlag::WRONG_FORMAT;
1261   *value = result->get_uint64_t();
1262   return JVMFlag::SUCCESS;
1263 }
1264 
apply_constraint_and_check_range_uint64_t(const char * name,uint64_t new_value,bool verbose)1265 static JVMFlag::Error apply_constraint_and_check_range_uint64_t(const char* name, uint64_t new_value, bool verbose) {
1266   JVMFlag::Error status = JVMFlag::SUCCESS;
1267   JVMFlagRange* range = JVMFlagRangeList::find(name);
1268   if (range != NULL) {
1269     status = range->check_uint64_t(new_value, verbose);
1270   }
1271   if (status == JVMFlag::SUCCESS) {
1272     JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
1273     if (constraint != NULL) {
1274       status = constraint->apply_uint64_t(new_value, verbose);
1275     }
1276   }
1277   return status;
1278 }
1279 
uint64_tAtPut(JVMFlag * flag,uint64_t * value,JVMFlag::Flags origin)1280 JVMFlag::Error JVMFlag::uint64_tAtPut(JVMFlag* flag, uint64_t* value, JVMFlag::Flags origin) {
1281   const char* name;
1282   if (flag == NULL) return JVMFlag::INVALID_FLAG;
1283   if (!flag->is_uint64_t()) return JVMFlag::WRONG_FORMAT;
1284   name = flag->_name;
1285   JVMFlag::Error check = apply_constraint_and_check_range_uint64_t(name, *value, !JVMFlagConstraintList::validated_after_ergo());
1286   if (check != JVMFlag::SUCCESS) return check;
1287   uint64_t old_value = flag->get_uint64_t();
1288   trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
1289   check = flag->set_uint64_t(*value);
1290   *value = old_value;
1291   flag->set_origin(origin);
1292   return check;
1293 }
1294 
uint64_tAtPut(const char * name,size_t len,uint64_t * value,JVMFlag::Flags origin)1295 JVMFlag::Error JVMFlag::uint64_tAtPut(const char* name, size_t len, uint64_t* value, JVMFlag::Flags origin) {
1296   JVMFlag* result = JVMFlag::find_flag(name, len);
1297   return uint64_tAtPut(result, value, origin);
1298 }
1299 
uint64_tAtPut(JVMFlagsWithType flag,uint64_t value,JVMFlag::Flags origin)1300 JVMFlag::Error JVMFlagEx::uint64_tAtPut(JVMFlagsWithType flag, uint64_t value, JVMFlag::Flags origin) {
1301   JVMFlag* faddr = address_of_flag(flag);
1302   guarantee(faddr != NULL && faddr->is_uint64_t(), "wrong flag type");
1303   return JVMFlag::uint64_tAtPut(faddr, &value, origin);
1304 }
1305 
size_tAt(const char * name,size_t len,size_t * value,bool allow_locked,bool return_flag)1306 JVMFlag::Error JVMFlag::size_tAt(const char* name, size_t len, size_t* value, bool allow_locked, bool return_flag) {
1307   JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
1308   if (result == NULL) return JVMFlag::INVALID_FLAG;
1309   if (!result->is_size_t()) return JVMFlag::WRONG_FORMAT;
1310   *value = result->get_size_t();
1311   return JVMFlag::SUCCESS;
1312 }
1313 
apply_constraint_and_check_range_size_t(const char * name,size_t new_value,bool verbose)1314 static JVMFlag::Error apply_constraint_and_check_range_size_t(const char* name, size_t new_value, bool verbose) {
1315   JVMFlag::Error status = JVMFlag::SUCCESS;
1316   JVMFlagRange* range = JVMFlagRangeList::find(name);
1317   if (range != NULL) {
1318     status = range->check_size_t(new_value, verbose);
1319   }
1320   if (status == JVMFlag::SUCCESS) {
1321     JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
1322     if (constraint != NULL) {
1323       status = constraint->apply_size_t(new_value, verbose);
1324     }
1325   }
1326   return status;
1327 }
1328 
1329 
size_tAtPut(JVMFlag * flag,size_t * value,JVMFlag::Flags origin)1330 JVMFlag::Error JVMFlag::size_tAtPut(JVMFlag* flag, size_t* value, JVMFlag::Flags origin) {
1331   const char* name;
1332   if (flag == NULL) return JVMFlag::INVALID_FLAG;
1333   if (!flag->is_size_t()) return JVMFlag::WRONG_FORMAT;
1334   name = flag->_name;
1335   JVMFlag::Error check = apply_constraint_and_check_range_size_t(name, *value, !JVMFlagConstraintList::validated_after_ergo());
1336   if (check != JVMFlag::SUCCESS) return check;
1337   size_t old_value = flag->get_size_t();
1338   trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
1339   check = flag->set_size_t(*value);
1340   *value = old_value;
1341   flag->set_origin(origin);
1342   return check;
1343 }
1344 
size_tAtPut(const char * name,size_t len,size_t * value,JVMFlag::Flags origin)1345 JVMFlag::Error JVMFlag::size_tAtPut(const char* name, size_t len, size_t* value, JVMFlag::Flags origin) {
1346   JVMFlag* result = JVMFlag::find_flag(name, len);
1347   return size_tAtPut(result, value, origin);
1348 }
1349 
size_tAtPut(JVMFlagsWithType flag,size_t value,JVMFlag::Flags origin)1350 JVMFlag::Error JVMFlagEx::size_tAtPut(JVMFlagsWithType flag, size_t value, JVMFlag::Flags origin) {
1351   JVMFlag* faddr = address_of_flag(flag);
1352   guarantee(faddr != NULL && faddr->is_size_t(), "wrong flag type");
1353   return JVMFlag::size_tAtPut(faddr, &value, origin);
1354 }
1355 
doubleAt(const char * name,size_t len,double * value,bool allow_locked,bool return_flag)1356 JVMFlag::Error JVMFlag::doubleAt(const char* name, size_t len, double* value, bool allow_locked, bool return_flag) {
1357   JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
1358   if (result == NULL) return JVMFlag::INVALID_FLAG;
1359   if (!result->is_double()) return JVMFlag::WRONG_FORMAT;
1360   *value = result->get_double();
1361   return JVMFlag::SUCCESS;
1362 }
1363 
apply_constraint_and_check_range_double(const char * name,double new_value,bool verbose)1364 static JVMFlag::Error apply_constraint_and_check_range_double(const char* name, double new_value, bool verbose) {
1365   JVMFlag::Error status = JVMFlag::SUCCESS;
1366   JVMFlagRange* range = JVMFlagRangeList::find(name);
1367   if (range != NULL) {
1368     status = range->check_double(new_value, verbose);
1369   }
1370   if (status == JVMFlag::SUCCESS) {
1371     JVMFlagConstraint* constraint = JVMFlagConstraintList::find_if_needs_check(name);
1372     if (constraint != NULL) {
1373       status = constraint->apply_double(new_value, verbose);
1374     }
1375   }
1376   return status;
1377 }
1378 
doubleAtPut(JVMFlag * flag,double * value,JVMFlag::Flags origin)1379 JVMFlag::Error JVMFlag::doubleAtPut(JVMFlag* flag, double* value, JVMFlag::Flags origin) {
1380   const char* name;
1381   if (flag == NULL) return JVMFlag::INVALID_FLAG;
1382   if (!flag->is_double()) return JVMFlag::WRONG_FORMAT;
1383   name = flag->_name;
1384   JVMFlag::Error check = apply_constraint_and_check_range_double(name, *value, !JVMFlagConstraintList::validated_after_ergo());
1385   if (check != JVMFlag::SUCCESS) return check;
1386   double old_value = flag->get_double();
1387   trace_flag_changed<EventDoubleFlagChanged, double>(name, old_value, *value, origin);
1388   check = flag->set_double(*value);
1389   *value = old_value;
1390   flag->set_origin(origin);
1391   return check;
1392 }
1393 
doubleAtPut(const char * name,size_t len,double * value,JVMFlag::Flags origin)1394 JVMFlag::Error JVMFlag::doubleAtPut(const char* name, size_t len, double* value, JVMFlag::Flags origin) {
1395   JVMFlag* result = JVMFlag::find_flag(name, len);
1396   return doubleAtPut(result, value, origin);
1397 }
1398 
doubleAtPut(JVMFlagsWithType flag,double value,JVMFlag::Flags origin)1399 JVMFlag::Error JVMFlagEx::doubleAtPut(JVMFlagsWithType flag, double value, JVMFlag::Flags origin) {
1400   JVMFlag* faddr = address_of_flag(flag);
1401   guarantee(faddr != NULL && faddr->is_double(), "wrong flag type");
1402   return JVMFlag::doubleAtPut(faddr, &value, origin);
1403 }
1404 
ccstrAt(const char * name,size_t len,ccstr * value,bool allow_locked,bool return_flag)1405 JVMFlag::Error JVMFlag::ccstrAt(const char* name, size_t len, ccstr* value, bool allow_locked, bool return_flag) {
1406   JVMFlag* result = JVMFlag::find_flag(name, len, allow_locked, return_flag);
1407   if (result == NULL) return JVMFlag::INVALID_FLAG;
1408   if (!result->is_ccstr()) return JVMFlag::WRONG_FORMAT;
1409   *value = result->get_ccstr();
1410   return JVMFlag::SUCCESS;
1411 }
1412 
ccstrAtPut(const char * name,size_t len,ccstr * value,JVMFlag::Flags origin)1413 JVMFlag::Error JVMFlag::ccstrAtPut(const char* name, size_t len, ccstr* value, JVMFlag::Flags origin) {
1414   JVMFlag* result = JVMFlag::find_flag(name, len);
1415   if (result == NULL) return JVMFlag::INVALID_FLAG;
1416   if (!result->is_ccstr()) return JVMFlag::WRONG_FORMAT;
1417   ccstr old_value = result->get_ccstr();
1418   trace_flag_changed<EventStringFlagChanged, const char*>(name, old_value, *value, origin);
1419   char* new_value = NULL;
1420   if (*value != NULL) {
1421     new_value = os::strdup_check_oom(*value);
1422   }
1423   JVMFlag::Error check = result->set_ccstr(new_value);
1424   if (result->is_default() && old_value != NULL) {
1425     // Prior value is NOT heap allocated, but was a literal constant.
1426     old_value = os::strdup_check_oom(old_value);
1427   }
1428   *value = old_value;
1429   result->set_origin(origin);
1430   return check;
1431 }
1432 
ccstrAtPut(JVMFlagsWithType flag,ccstr value,JVMFlag::Flags origin)1433 JVMFlag::Error JVMFlagEx::ccstrAtPut(JVMFlagsWithType flag, ccstr value, JVMFlag::Flags origin) {
1434   JVMFlag* faddr = address_of_flag(flag);
1435   guarantee(faddr != NULL && faddr->is_ccstr(), "wrong flag type");
1436   ccstr old_value = faddr->get_ccstr();
1437   trace_flag_changed<EventStringFlagChanged, const char*>(faddr->_name, old_value, value, origin);
1438   char* new_value = os::strdup_check_oom(value);
1439   JVMFlag::Error check = faddr->set_ccstr(new_value);
1440   if (!faddr->is_default() && old_value != NULL) {
1441     // Prior value is heap allocated so free it.
1442     FREE_C_HEAP_ARRAY(char, old_value);
1443   }
1444   faddr->set_origin(origin);
1445   return check;
1446 }
1447 
1448 extern "C" {
compare_flags(const void * void_a,const void * void_b)1449   static int compare_flags(const void* void_a, const void* void_b) {
1450     return strcmp((*((JVMFlag**) void_a))->_name, (*((JVMFlag**) void_b))->_name);
1451   }
1452 }
1453 
printSetFlags(outputStream * out)1454 void JVMFlag::printSetFlags(outputStream* out) {
1455   // Print which flags were set on the command line
1456   // note: this method is called before the thread structure is in place
1457   //       which means resource allocation cannot be used.
1458 
1459   // The last entry is the null entry.
1460   const size_t length = JVMFlag::numFlags - 1;
1461 
1462   // Sort
1463   JVMFlag** array = NEW_C_HEAP_ARRAY(JVMFlag*, length, mtArguments);
1464   for (size_t i = 0; i < length; i++) {
1465     array[i] = &flagTable[i];
1466   }
1467   qsort(array, length, sizeof(JVMFlag*), compare_flags);
1468 
1469   // Print
1470   for (size_t i = 0; i < length; i++) {
1471     if (array[i]->get_origin() /* naked field! */) {
1472       array[i]->print_as_flag(out);
1473       out->print(" ");
1474     }
1475   }
1476   out->cr();
1477   FREE_C_HEAP_ARRAY(JVMFlag*, array);
1478 }
1479 
1480 #ifndef PRODUCT
1481 
verify()1482 void JVMFlag::verify() {
1483   assert(Arguments::check_vm_args_consistency(), "Some flag settings conflict");
1484 }
1485 
1486 #endif // PRODUCT
1487 
printFlags(outputStream * out,bool withComments,bool printRanges,bool skipDefaults)1488 void JVMFlag::printFlags(outputStream* out, bool withComments, bool printRanges, bool skipDefaults) {
1489   // Print the flags sorted by name
1490   // Note: This method may be called before the thread structure is in place
1491   //       which means resource allocation cannot be used. Also, it may be
1492   //       called as part of error reporting, so handle native OOMs gracefully.
1493 
1494   // The last entry is the null entry.
1495   const size_t length = JVMFlag::numFlags - 1;
1496 
1497   // Print
1498   if (!printRanges) {
1499     out->print_cr("[Global flags]");
1500   } else {
1501     out->print_cr("[Global flags ranges]");
1502   }
1503 
1504   // Sort
1505   JVMFlag** array = NEW_C_HEAP_ARRAY_RETURN_NULL(JVMFlag*, length, mtArguments);
1506   if (array != NULL) {
1507     for (size_t i = 0; i < length; i++) {
1508       array[i] = &flagTable[i];
1509     }
1510     qsort(array, length, sizeof(JVMFlag*), compare_flags);
1511 
1512     for (size_t i = 0; i < length; i++) {
1513       if (array[i]->is_unlocked() && !(skipDefaults && array[i]->is_default())) {
1514         array[i]->print_on(out, withComments, printRanges);
1515       }
1516     }
1517     FREE_C_HEAP_ARRAY(JVMFlag*, array);
1518   } else {
1519     // OOM? Print unsorted.
1520     for (size_t i = 0; i < length; i++) {
1521       if (flagTable[i].is_unlocked() && !(skipDefaults && flagTable[i].is_default())) {
1522         flagTable[i].print_on(out, withComments, printRanges);
1523       }
1524     }
1525   }
1526 }
1527 
printError(bool verbose,const char * msg,...)1528 void JVMFlag::printError(bool verbose, const char* msg, ...) {
1529   if (verbose) {
1530     va_list listPointer;
1531     va_start(listPointer, msg);
1532     jio_vfprintf(defaultStream::error_stream(), msg, listPointer);
1533     va_end(listPointer);
1534   }
1535 }
1536 
1537