commandLineFlagRangeList.cpp revision 11390:9789c3ca3a3d
1/*
2 * Copyright (c) 2015, 2016, 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 "classfile/stringTable.hpp"
27#include "classfile/symbolTable.hpp"
28#include "gc/shared/referenceProcessor.hpp"
29#include "runtime/arguments.hpp"
30#include "runtime/commandLineFlagConstraintList.hpp"
31#include "runtime/commandLineFlagRangeList.hpp"
32#include "runtime/os.hpp"
33#include "runtime/task.hpp"
34#include "utilities/defaultStream.hpp"
35#include "utilities/macros.hpp"
36
37void CommandLineError::print(bool verbose, const char* msg, ...) {
38  if (verbose) {
39    va_list listPointer;
40    va_start(listPointer, msg);
41    jio_vfprintf(defaultStream::error_stream(), msg, listPointer);
42    va_end(listPointer);
43  }
44}
45
46class CommandLineFlagRange_int : public CommandLineFlagRange {
47  int _min;
48  int _max;
49
50public:
51  // the "name" argument must be a string literal
52  CommandLineFlagRange_int(const char* name, int min, int max) : CommandLineFlagRange(name) {
53    _min=min, _max=max;
54  }
55
56  Flag::Error check_int(int value, bool verbose = true) {
57    if ((value < _min) || (value > _max)) {
58      CommandLineError::print(verbose,
59                              "int %s=%d is outside the allowed range "
60                              "[ %d ... %d ]\n",
61                              name(), value, _min, _max);
62      return Flag::OUT_OF_BOUNDS;
63    } else {
64      return Flag::SUCCESS;
65    }
66  }
67
68  void print(outputStream* st) {
69    st->print("[ %-25d ... %25d ]", _min, _max);
70  }
71};
72
73class CommandLineFlagRange_intx : public CommandLineFlagRange {
74  intx _min;
75  intx _max;
76
77public:
78  // the "name" argument must be a string literal
79  CommandLineFlagRange_intx(const char* name, intx min, intx max) : CommandLineFlagRange(name) {
80    _min=min, _max=max;
81  }
82
83  Flag::Error check_intx(intx value, bool verbose = true) {
84    if ((value < _min) || (value > _max)) {
85      CommandLineError::print(verbose,
86                              "intx %s=" INTX_FORMAT " is outside the allowed range "
87                              "[ " INTX_FORMAT " ... " INTX_FORMAT " ]\n",
88                              name(), value, _min, _max);
89      return Flag::OUT_OF_BOUNDS;
90    } else {
91      return Flag::SUCCESS;
92    }
93  }
94
95  void print(outputStream* st) {
96    st->print("[ " INTX_FORMAT_W(-25) " ... " INTX_FORMAT_W(25) " ]", _min, _max);
97  }
98};
99
100class CommandLineFlagRange_uint : public CommandLineFlagRange {
101  uint _min;
102  uint _max;
103
104public:
105  // the "name" argument must be a string literal
106  CommandLineFlagRange_uint(const char* name, uint min, uint max) : CommandLineFlagRange(name) {
107    _min=min, _max=max;
108  }
109
110  Flag::Error check_uint(uint value, bool verbose = true) {
111    if ((value < _min) || (value > _max)) {
112      CommandLineError::print(verbose,
113                              "uint %s=%u is outside the allowed range "
114                              "[ %u ... %u ]\n",
115                              name(), value, _min, _max);
116      return Flag::OUT_OF_BOUNDS;
117    } else {
118      return Flag::SUCCESS;
119    }
120  }
121
122  void print(outputStream* st) {
123    st->print("[ %-25u ... %25u ]", _min, _max);
124  }
125};
126
127class CommandLineFlagRange_uintx : public CommandLineFlagRange {
128  uintx _min;
129  uintx _max;
130
131public:
132  // the "name" argument must be a string literal
133  CommandLineFlagRange_uintx(const char* name, uintx min, uintx max) : CommandLineFlagRange(name) {
134    _min=min, _max=max;
135  }
136
137  Flag::Error check_uintx(uintx value, bool verbose = true) {
138    if ((value < _min) || (value > _max)) {
139      CommandLineError::print(verbose,
140                              "uintx %s=" UINTX_FORMAT " is outside the allowed range "
141                              "[ " UINTX_FORMAT " ... " UINTX_FORMAT " ]\n",
142                              name(), value, _min, _max);
143      return Flag::OUT_OF_BOUNDS;
144    } else {
145      return Flag::SUCCESS;
146    }
147  }
148
149  void print(outputStream* st) {
150    st->print("[ " UINTX_FORMAT_W(-25) " ... " UINTX_FORMAT_W(25) " ]", _min, _max);
151  }
152};
153
154class CommandLineFlagRange_uint64_t : public CommandLineFlagRange {
155  uint64_t _min;
156  uint64_t _max;
157
158public:
159  // the "name" argument must be a string literal
160  CommandLineFlagRange_uint64_t(const char* name, uint64_t min, uint64_t max) : CommandLineFlagRange(name) {
161    _min=min, _max=max;
162  }
163
164  Flag::Error check_uint64_t(uint64_t value, bool verbose = true) {
165    if ((value < _min) || (value > _max)) {
166      CommandLineError::print(verbose,
167                              "uint64_t %s=" UINT64_FORMAT " is outside the allowed range "
168                              "[ " UINT64_FORMAT " ... " UINT64_FORMAT " ]\n",
169                              name(), value, _min, _max);
170      return Flag::OUT_OF_BOUNDS;
171    } else {
172      return Flag::SUCCESS;
173    }
174  }
175
176  void print(outputStream* st) {
177    st->print("[ " UINT64_FORMAT_W(-25) " ... " UINT64_FORMAT_W(25) " ]", _min, _max);
178  }
179};
180
181class CommandLineFlagRange_size_t : public CommandLineFlagRange {
182  size_t _min;
183  size_t _max;
184
185public:
186  // the "name" argument must be a string literal
187  CommandLineFlagRange_size_t(const char* name, size_t min, size_t max) : CommandLineFlagRange(name) {
188    _min=min, _max=max;
189  }
190
191  Flag::Error check_size_t(size_t value, bool verbose = true) {
192    if ((value < _min) || (value > _max)) {
193      CommandLineError::print(verbose,
194                              "size_t %s=" SIZE_FORMAT " is outside the allowed range "
195                              "[ " SIZE_FORMAT " ... " SIZE_FORMAT " ]\n",
196                              name(), value, _min, _max);
197      return Flag::OUT_OF_BOUNDS;
198    } else {
199      return Flag::SUCCESS;
200    }
201  }
202
203  void print(outputStream* st) {
204    st->print("[ " SIZE_FORMAT_W(-25) " ... " SIZE_FORMAT_W(25) " ]", _min, _max);
205  }
206};
207
208class CommandLineFlagRange_double : public CommandLineFlagRange {
209  double _min;
210  double _max;
211
212public:
213  // the "name" argument must be a string literal
214  CommandLineFlagRange_double(const char* name, double min, double max) : CommandLineFlagRange(name) {
215    _min=min, _max=max;
216  }
217
218  Flag::Error check_double(double value, bool verbose = true) {
219    if ((value < _min) || (value > _max)) {
220      CommandLineError::print(verbose,
221                              "double %s=%f is outside the allowed range "
222                              "[ %f ... %f ]\n",
223                              name(), value, _min, _max);
224      return Flag::OUT_OF_BOUNDS;
225    } else {
226      return Flag::SUCCESS;
227    }
228  }
229
230  void print(outputStream* st) {
231    st->print("[ %-25.3f ... %25.3f ]", _min, _max);
232  }
233};
234
235// No constraint emitting
236void emit_range_no(...)                         { /* NOP */ }
237
238// No constraint emitting if function argument is NOT provided
239void emit_range_bool(const char* /*name*/)      { /* NOP */ }
240void emit_range_ccstr(const char* /*name*/)     { /* NOP */ }
241void emit_range_ccstrlist(const char* /*name*/) { /* NOP */ }
242void emit_range_int(const char* /*name*/)       { /* NOP */ }
243void emit_range_intx(const char* /*name*/)      { /* NOP */ }
244void emit_range_uint(const char* /*name*/)      { /* NOP */ }
245void emit_range_uintx(const char* /*name*/)     { /* NOP */ }
246void emit_range_uint64_t(const char* /*name*/)  { /* NOP */ }
247void emit_range_size_t(const char* /*name*/)    { /* NOP */ }
248void emit_range_double(const char* /*name*/)    { /* NOP */ }
249
250// CommandLineFlagRange emitting code functions if range arguments are provided
251void emit_range_int(const char* name, int min, int max)       {
252  CommandLineFlagRangeList::add(new CommandLineFlagRange_int(name, min, max));
253}
254void emit_range_intx(const char* name, intx min, intx max) {
255  CommandLineFlagRangeList::add(new CommandLineFlagRange_intx(name, min, max));
256}
257void emit_range_uint(const char* name, uint min, uint max) {
258  CommandLineFlagRangeList::add(new CommandLineFlagRange_uint(name, min, max));
259}
260void emit_range_uintx(const char* name, uintx min, uintx max) {
261  CommandLineFlagRangeList::add(new CommandLineFlagRange_uintx(name, min, max));
262}
263void emit_range_uint64_t(const char* name, uint64_t min, uint64_t max) {
264  CommandLineFlagRangeList::add(new CommandLineFlagRange_uint64_t(name, min, max));
265}
266void emit_range_size_t(const char* name, size_t min, size_t max) {
267  CommandLineFlagRangeList::add(new CommandLineFlagRange_size_t(name, min, max));
268}
269void emit_range_double(const char* name, double min, double max) {
270  CommandLineFlagRangeList::add(new CommandLineFlagRange_double(name, min, max));
271}
272
273// Generate code to call emit_range_xxx function
274#define EMIT_RANGE_PRODUCT_FLAG(type, name, value, doc)      ); emit_range_##type(#name
275#define EMIT_RANGE_COMMERCIAL_FLAG(type, name, value, doc)   ); emit_range_##type(#name
276#define EMIT_RANGE_DIAGNOSTIC_FLAG(type, name, value, doc)   ); emit_range_##type(#name
277#define EMIT_RANGE_EXPERIMENTAL_FLAG(type, name, value, doc) ); emit_range_##type(#name
278#define EMIT_RANGE_MANAGEABLE_FLAG(type, name, value, doc)   ); emit_range_##type(#name
279#define EMIT_RANGE_PRODUCT_RW_FLAG(type, name, value, doc)   ); emit_range_##type(#name
280#define EMIT_RANGE_PD_PRODUCT_FLAG(type, name, doc)          ); emit_range_##type(#name
281#define EMIT_RANGE_PD_DIAGNOSTIC_FLAG(type, name, doc)       ); emit_range_##type(#name
282#define EMIT_RANGE_DEVELOPER_FLAG(type, name, value, doc)    ); emit_range_##type(#name
283#define EMIT_RANGE_PD_DEVELOPER_FLAG(type, name, doc)        ); emit_range_##type(#name
284#define EMIT_RANGE_NOTPRODUCT_FLAG(type, name, value, doc)   ); emit_range_##type(#name
285#define EMIT_RANGE_LP64_PRODUCT_FLAG(type, name, value, doc) ); emit_range_##type(#name
286
287// Generate func argument to pass into emit_range_xxx functions
288#define EMIT_RANGE_CHECK(a, b)                               , a, b
289
290#define INITIAL_RANGES_SIZE 379
291GrowableArray<CommandLineFlagRange*>* CommandLineFlagRangeList::_ranges = NULL;
292
293// Check the ranges of all flags that have them
294void CommandLineFlagRangeList::init(void) {
295
296  _ranges = new (ResourceObj::C_HEAP, mtArguments) GrowableArray<CommandLineFlagRange*>(INITIAL_RANGES_SIZE, true);
297
298  emit_range_no(NULL RUNTIME_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
299                                   EMIT_RANGE_PD_DEVELOPER_FLAG,
300                                   EMIT_RANGE_PRODUCT_FLAG,
301                                   EMIT_RANGE_PD_PRODUCT_FLAG,
302                                   EMIT_RANGE_DIAGNOSTIC_FLAG,
303                                   EMIT_RANGE_PD_DIAGNOSTIC_FLAG,
304                                   EMIT_RANGE_EXPERIMENTAL_FLAG,
305                                   EMIT_RANGE_NOTPRODUCT_FLAG,
306                                   EMIT_RANGE_MANAGEABLE_FLAG,
307                                   EMIT_RANGE_PRODUCT_RW_FLAG,
308                                   EMIT_RANGE_LP64_PRODUCT_FLAG,
309                                   EMIT_RANGE_CHECK,
310                                   IGNORE_CONSTRAINT,
311                                   IGNORE_WRITEABLE));
312
313  EMIT_RANGES_FOR_GLOBALS_EXT
314
315  emit_range_no(NULL ARCH_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
316                                EMIT_RANGE_PRODUCT_FLAG,
317                                EMIT_RANGE_DIAGNOSTIC_FLAG,
318                                EMIT_RANGE_EXPERIMENTAL_FLAG,
319                                EMIT_RANGE_NOTPRODUCT_FLAG,
320                                EMIT_RANGE_CHECK,
321                                IGNORE_CONSTRAINT,
322                                IGNORE_WRITEABLE));
323
324#if INCLUDE_JVMCI
325  emit_range_no(NULL JVMCI_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
326                                 EMIT_RANGE_PD_DEVELOPER_FLAG,
327                                 EMIT_RANGE_PRODUCT_FLAG,
328                                 EMIT_RANGE_PD_PRODUCT_FLAG,
329                                 EMIT_RANGE_DIAGNOSTIC_FLAG,
330                                 EMIT_RANGE_PD_DIAGNOSTIC_FLAG,
331                                 EMIT_RANGE_EXPERIMENTAL_FLAG,
332                                 EMIT_RANGE_NOTPRODUCT_FLAG,
333                                 EMIT_RANGE_CHECK,
334                                 IGNORE_CONSTRAINT,
335                                 IGNORE_WRITEABLE));
336#endif // INCLUDE_JVMCI
337
338#ifdef COMPILER1
339  emit_range_no(NULL C1_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
340                              EMIT_RANGE_PD_DEVELOPER_FLAG,
341                              EMIT_RANGE_PRODUCT_FLAG,
342                              EMIT_RANGE_PD_PRODUCT_FLAG,
343                              EMIT_RANGE_DIAGNOSTIC_FLAG,
344                              EMIT_RANGE_PD_DIAGNOSTIC_FLAG,
345                              EMIT_RANGE_NOTPRODUCT_FLAG,
346                              EMIT_RANGE_CHECK,
347                              IGNORE_CONSTRAINT,
348                              IGNORE_WRITEABLE));
349#endif // COMPILER1
350
351#ifdef COMPILER2
352  emit_range_no(NULL C2_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
353                              EMIT_RANGE_PD_DEVELOPER_FLAG,
354                              EMIT_RANGE_PRODUCT_FLAG,
355                              EMIT_RANGE_PD_PRODUCT_FLAG,
356                              EMIT_RANGE_DIAGNOSTIC_FLAG,
357                              EMIT_RANGE_PD_DIAGNOSTIC_FLAG,
358                              EMIT_RANGE_EXPERIMENTAL_FLAG,
359                              EMIT_RANGE_NOTPRODUCT_FLAG,
360                              EMIT_RANGE_CHECK,
361                              IGNORE_CONSTRAINT,
362                              IGNORE_WRITEABLE));
363#endif // COMPILER2
364
365#if INCLUDE_ALL_GCS
366  emit_range_no(NULL G1_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
367                              EMIT_RANGE_PD_DEVELOPER_FLAG,
368                              EMIT_RANGE_PRODUCT_FLAG,
369                              EMIT_RANGE_PD_PRODUCT_FLAG,
370                              EMIT_RANGE_DIAGNOSTIC_FLAG,
371                              EMIT_RANGE_PD_DIAGNOSTIC_FLAG,
372                              EMIT_RANGE_EXPERIMENTAL_FLAG,
373                              EMIT_RANGE_NOTPRODUCT_FLAG,
374                              EMIT_RANGE_MANAGEABLE_FLAG,
375                              EMIT_RANGE_PRODUCT_RW_FLAG,
376                              EMIT_RANGE_CHECK,
377                              IGNORE_CONSTRAINT,
378                              IGNORE_WRITEABLE));
379#endif // INCLUDE_ALL_GCS
380}
381
382CommandLineFlagRange* CommandLineFlagRangeList::find(const char* name) {
383  CommandLineFlagRange* found = NULL;
384  for (int i=0; i<length(); i++) {
385    CommandLineFlagRange* range = at(i);
386    if (strcmp(range->name(), name) == 0) {
387      found = range;
388      break;
389    }
390  }
391  return found;
392}
393
394void CommandLineFlagRangeList::print(outputStream* st, const char* name, RangeStrFunc default_range_str_func) {
395  CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
396  if (range != NULL) {
397    range->print(st);
398  } else {
399    CommandLineFlagConstraint* constraint = CommandLineFlagConstraintList::find(name);
400    if (constraint != NULL) {
401      assert(default_range_str_func!=NULL, "default_range_str_func must be provided");
402      st->print("%s", default_range_str_func());
403    } else {
404      st->print("[                           ...                           ]");
405    }
406  }
407}
408
409bool CommandLineFlagRangeList::check_ranges() {
410  // Check ranges.
411  bool status = true;
412  for (int i=0; i<length(); i++) {
413    CommandLineFlagRange* range = at(i);
414    const char* name = range->name();
415    Flag* flag = Flag::find_flag(name, strlen(name), true, true);
416    // We must check for NULL here as lp64_product flags on 32 bit architecture
417    // can generate range check (despite that they are declared as constants),
418    // but they will not be returned by Flag::find_flag()
419    if (flag != NULL) {
420      if (flag->is_int()) {
421        int value = flag->get_int();
422        if (range->check_int(value, true) != Flag::SUCCESS) status = false;
423      } else if (flag->is_uint()) {
424        uint value = flag->get_uint();
425        if (range->check_uint(value, true) != Flag::SUCCESS) status = false;
426      } else if (flag->is_intx()) {
427        intx value = flag->get_intx();
428        if (range->check_intx(value, true) != Flag::SUCCESS) status = false;
429      } else if (flag->is_uintx()) {
430        uintx value = flag->get_uintx();
431        if (range->check_uintx(value, true) != Flag::SUCCESS) status = false;
432      } else if (flag->is_uint64_t()) {
433        uint64_t value = flag->get_uint64_t();
434        if (range->check_uint64_t(value, true) != Flag::SUCCESS) status = false;
435      } else if (flag->is_size_t()) {
436        size_t value = flag->get_size_t();
437        if (range->check_size_t(value, true) != Flag::SUCCESS) status = false;
438      } else if (flag->is_double()) {
439        double value = flag->get_double();
440        if (range->check_double(value, true) != Flag::SUCCESS) status = false;
441      }
442    }
443  }
444  return status;
445}
446