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