commandLineFlagRangeList.cpp revision 9679:9689c3d3e2f8
1284990Scy/*
2284990Scy * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3284990Scy * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4284990Scy *
5284990Scy * This code is free software; you can redistribute it and/or modify it
6284990Scy * under the terms of the GNU General Public License version 2 only, as
7284990Scy * published by the Free Software Foundation.
8284990Scy *
9284990Scy * This code is distributed in the hope that it will be useful, but WITHOUT
10284990Scy * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11284990Scy * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12284990Scy * version 2 for more details (a copy is included in the LICENSE file that
13284990Scy * accompanied this code).
14284990Scy *
15284990Scy * You should have received a copy of the GNU General Public License version
16284990Scy * 2 along with this work; if not, write to the Free Software Foundation,
17284990Scy * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18284990Scy *
19284990Scy * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20284990Scy * or visit www.oracle.com if you need additional information or have any
21284990Scy * questions.
22284990Scy *
23284990Scy */
24284990Scy
25284990Scy#include "precompiled.hpp"
26284990Scy#include "classfile/stringTable.hpp"
27284990Scy#include "classfile/symbolTable.hpp"
28284990Scy#include "gc/shared/referenceProcessor.hpp"
29284990Scy#include "runtime/arguments.hpp"
30284990Scy#include "runtime/commandLineFlagRangeList.hpp"
31284990Scy#include "runtime/os.hpp"
32284990Scy#include "runtime/task.hpp"
33284990Scy#include "utilities/defaultStream.hpp"
34284990Scy#include "utilities/macros.hpp"
35284990Scy
36284990Scyvoid CommandLineError::print(bool verbose, const char* msg, ...) {
37284990Scy  if (verbose) {
38284990Scy    va_list listPointer;
39284990Scy    va_start(listPointer, msg);
40284990Scy    jio_vfprintf(defaultStream::error_stream(), msg, listPointer);
41284990Scy    va_end(listPointer);
42284990Scy  }
43284990Scy}
44284990Scy
45284990Scyclass CommandLineFlagRange_int : public CommandLineFlagRange {
46284990Scy  int _min;
47284990Scy  int _max;
48284990Scy
49284990Scypublic:
50284990Scy  // the "name" argument must be a string literal
51284990Scy  CommandLineFlagRange_int(const char* name, int min, int max) : CommandLineFlagRange(name) {
52284990Scy    _min=min, _max=max;
53284990Scy  }
54284990Scy
55284990Scy  Flag::Error check_int(int value, bool verbose = true) {
56284990Scy    if ((value < _min) || (value > _max)) {
57284990Scy      CommandLineError::print(verbose,
58284990Scy                              "int %s=%d is outside the allowed range "
59284990Scy                              "[ %d ... %d ]\n",
60284990Scy                              name(), value, _min, _max);
61284990Scy      return Flag::OUT_OF_BOUNDS;
62284990Scy    } else {
63284990Scy      return Flag::SUCCESS;
64284990Scy    }
65284990Scy  }
66284990Scy
67284990Scy  void print(outputStream* st) {
68284990Scy    st->print("[ %-25d ... %25d ]", _min, _max);
69284990Scy  }
70284990Scy};
71284990Scy
72284990Scyclass CommandLineFlagRange_intx : public CommandLineFlagRange {
73284990Scy  intx _min;
74284990Scy  intx _max;
75284990Scy
76284990Scypublic:
77284990Scy  // the "name" argument must be a string literal
78284990Scy  CommandLineFlagRange_intx(const char* name, intx min, intx max) : CommandLineFlagRange(name) {
79284990Scy    _min=min, _max=max;
80284990Scy  }
81284990Scy
82284990Scy  Flag::Error check_intx(intx value, bool verbose = true) {
83284990Scy    if ((value < _min) || (value > _max)) {
84284990Scy      CommandLineError::print(verbose,
85284990Scy                              "intx %s=" INTX_FORMAT " is outside the allowed range "
86284990Scy                              "[ " INTX_FORMAT " ... " INTX_FORMAT " ]\n",
87284990Scy                              name(), value, _min, _max);
88284990Scy      return Flag::OUT_OF_BOUNDS;
89284990Scy    } else {
90284990Scy      return Flag::SUCCESS;
91284990Scy    }
92284990Scy  }
93284990Scy
94284990Scy  void print(outputStream* st) {
95284990Scy    st->print("[ " INTX_FORMAT_W(-25) " ... " INTX_FORMAT_W(25) " ]", _min, _max);
96284990Scy  }
97284990Scy};
98284990Scy
99284990Scyclass CommandLineFlagRange_uint : public CommandLineFlagRange {
100284990Scy  uint _min;
101284990Scy  uint _max;
102284990Scy
103284990Scypublic:
104284990Scy  // the "name" argument must be a string literal
105284990Scy  CommandLineFlagRange_uint(const char* name, uint min, uint max) : CommandLineFlagRange(name) {
106284990Scy    _min=min, _max=max;
107284990Scy  }
108284990Scy
109284990Scy  Flag::Error check_uint(uint value, bool verbose = true) {
110284990Scy    if ((value < _min) || (value > _max)) {
111284990Scy      CommandLineError::print(verbose,
112284990Scy                              "uint %s=%u is outside the allowed range "
113284990Scy                              "[ %u ... %u ]\n",
114284990Scy                              name(), value, _min, _max);
115284990Scy      return Flag::OUT_OF_BOUNDS;
116284990Scy    } else {
117284990Scy      return Flag::SUCCESS;
118284990Scy    }
119284990Scy  }
120284990Scy
121284990Scy  void print(outputStream* st) {
122284990Scy    st->print("[ %-25u ... %25u ]", _min, _max);
123284990Scy  }
124284990Scy};
125284990Scy
126284990Scyclass CommandLineFlagRange_uintx : public CommandLineFlagRange {
127284990Scy  uintx _min;
128284990Scy  uintx _max;
129284990Scy
130284990Scypublic:
131284990Scy  // the "name" argument must be a string literal
132284990Scy  CommandLineFlagRange_uintx(const char* name, uintx min, uintx max) : CommandLineFlagRange(name) {
133284990Scy    _min=min, _max=max;
134284990Scy  }
135284990Scy
136284990Scy  Flag::Error check_uintx(uintx value, bool verbose = true) {
137284990Scy    if ((value < _min) || (value > _max)) {
138284990Scy      CommandLineError::print(verbose,
139284990Scy                              "uintx %s=" UINTX_FORMAT " is outside the allowed range "
140284990Scy                              "[ " UINTX_FORMAT " ... " UINTX_FORMAT " ]\n",
141284990Scy                              name(), value, _min, _max);
142284990Scy      return Flag::OUT_OF_BOUNDS;
143284990Scy    } else {
144284990Scy      return Flag::SUCCESS;
145284990Scy    }
146284990Scy  }
147284990Scy
148284990Scy  void print(outputStream* st) {
149284990Scy    st->print("[ " UINTX_FORMAT_W(-25) " ... " UINTX_FORMAT_W(25) " ]", _min, _max);
150284990Scy  }
151284990Scy};
152284990Scy
153284990Scyclass CommandLineFlagRange_uint64_t : public CommandLineFlagRange {
154284990Scy  uint64_t _min;
155284990Scy  uint64_t _max;
156284990Scy
157284990Scypublic:
158284990Scy  // the "name" argument must be a string literal
159284990Scy  CommandLineFlagRange_uint64_t(const char* name, uint64_t min, uint64_t max) : CommandLineFlagRange(name) {
160284990Scy    _min=min, _max=max;
161284990Scy  }
162284990Scy
163284990Scy  Flag::Error check_uint64_t(uint64_t value, bool verbose = true) {
164284990Scy    if ((value < _min) || (value > _max)) {
165284990Scy      CommandLineError::print(verbose,
166284990Scy                              "uint64_t %s=" UINT64_FORMAT " is outside the allowed range "
167284990Scy                              "[ " UINT64_FORMAT " ... " UINT64_FORMAT " ]\n",
168284990Scy                              name(), value, _min, _max);
169284990Scy      return Flag::OUT_OF_BOUNDS;
170284990Scy    } else {
171284990Scy      return Flag::SUCCESS;
172284990Scy    }
173284990Scy  }
174284990Scy
175284990Scy  void print(outputStream* st) {
176284990Scy    st->print("[ " UINT64_FORMAT_W(-25) " ... " UINT64_FORMAT_W(25) " ]", _min, _max);
177284990Scy  }
178284990Scy};
179284990Scy
180284990Scyclass CommandLineFlagRange_size_t : public CommandLineFlagRange {
181284990Scy  size_t _min;
182284990Scy  size_t _max;
183284990Scy
184284990Scypublic:
185284990Scy  // the "name" argument must be a string literal
186284990Scy  CommandLineFlagRange_size_t(const char* name, size_t min, size_t max) : CommandLineFlagRange(name) {
187284990Scy    _min=min, _max=max;
188284990Scy  }
189284990Scy
190284990Scy  Flag::Error check_size_t(size_t value, bool verbose = true) {
191284990Scy    if ((value < _min) || (value > _max)) {
192284990Scy      CommandLineError::print(verbose,
193284990Scy                              "size_t %s=" SIZE_FORMAT " is outside the allowed range "
194284990Scy                              "[ " SIZE_FORMAT " ... " SIZE_FORMAT " ]\n",
195284990Scy                              name(), value, _min, _max);
196284990Scy      return Flag::OUT_OF_BOUNDS;
197284990Scy    } else {
198284990Scy      return Flag::SUCCESS;
199284990Scy    }
200284990Scy  }
201284990Scy
202284990Scy  void print(outputStream* st) {
203284990Scy    st->print("[ " SIZE_FORMAT_W(-25) " ... " SIZE_FORMAT_W(25) " ]", _min, _max);
204284990Scy  }
205284990Scy};
206284990Scy
207284990Scyclass CommandLineFlagRange_double : public CommandLineFlagRange {
208284990Scy  double _min;
209284990Scy  double _max;
210284990Scy
211284990Scypublic:
212284990Scy  // the "name" argument must be a string literal
213284990Scy  CommandLineFlagRange_double(const char* name, double min, double max) : CommandLineFlagRange(name) {
214284990Scy    _min=min, _max=max;
215284990Scy  }
216284990Scy
217284990Scy  Flag::Error check_double(double value, bool verbose = true) {
218284990Scy    if ((value < _min) || (value > _max)) {
219284990Scy      CommandLineError::print(verbose,
220                              "double %s=%f is outside the allowed range "
221                              "[ %f ... %f ]\n",
222                              name(), value, _min, _max);
223      return Flag::OUT_OF_BOUNDS;
224    } else {
225      return Flag::SUCCESS;
226    }
227  }
228
229  void print(outputStream* st) {
230    st->print("[ %-25.3f ... %25.3f ]", _min, _max);
231  }
232};
233
234// No constraint emitting
235void emit_range_no(...)                         { /* NOP */ }
236
237// No constraint emitting if function argument is NOT provided
238void emit_range_bool(const char* /*name*/)      { /* NOP */ }
239void emit_range_ccstr(const char* /*name*/)     { /* NOP */ }
240void emit_range_ccstrlist(const char* /*name*/) { /* NOP */ }
241void emit_range_int(const char* /*name*/)       { /* NOP */ }
242void emit_range_intx(const char* /*name*/)      { /* NOP */ }
243void emit_range_uint(const char* /*name*/)      { /* NOP */ }
244void emit_range_uintx(const char* /*name*/)     { /* NOP */ }
245void emit_range_uint64_t(const char* /*name*/)  { /* NOP */ }
246void emit_range_size_t(const char* /*name*/)    { /* NOP */ }
247void emit_range_double(const char* /*name*/)    { /* NOP */ }
248
249// CommandLineFlagRange emitting code functions if range arguments are provided
250void emit_range_intx(const char* name, intx min, intx max) {
251  CommandLineFlagRangeList::add(new CommandLineFlagRange_intx(name, min, max));
252}
253void emit_range_uint(const char* name, uint min, uint max) {
254  CommandLineFlagRangeList::add(new CommandLineFlagRange_uint(name, min, max));
255}
256void emit_range_uintx(const char* name, uintx min, uintx max) {
257  CommandLineFlagRangeList::add(new CommandLineFlagRange_uintx(name, min, max));
258}
259void emit_range_uint64_t(const char* name, uint64_t min, uint64_t max) {
260  CommandLineFlagRangeList::add(new CommandLineFlagRange_uint64_t(name, min, max));
261}
262void emit_range_size_t(const char* name, size_t min, size_t max) {
263  CommandLineFlagRangeList::add(new CommandLineFlagRange_size_t(name, min, max));
264}
265void emit_range_double(const char* name, double min, double max) {
266  CommandLineFlagRangeList::add(new CommandLineFlagRange_double(name, min, max));
267}
268
269// Generate code to call emit_range_xxx function
270#define EMIT_RANGE_PRODUCT_FLAG(type, name, value, doc)      ); emit_range_##type(#name
271#define EMIT_RANGE_COMMERCIAL_FLAG(type, name, value, doc)   ); emit_range_##type(#name
272#define EMIT_RANGE_DIAGNOSTIC_FLAG(type, name, value, doc)   ); emit_range_##type(#name
273#define EMIT_RANGE_EXPERIMENTAL_FLAG(type, name, value, doc) ); emit_range_##type(#name
274#define EMIT_RANGE_MANAGEABLE_FLAG(type, name, value, doc)   ); emit_range_##type(#name
275#define EMIT_RANGE_PRODUCT_RW_FLAG(type, name, value, doc)   ); emit_range_##type(#name
276#define EMIT_RANGE_PD_PRODUCT_FLAG(type, name, doc)          ); emit_range_##type(#name
277#define EMIT_RANGE_DEVELOPER_FLAG(type, name, value, doc)    ); emit_range_##type(#name
278#define EMIT_RANGE_PD_DEVELOPER_FLAG(type, name, doc)        ); emit_range_##type(#name
279#define EMIT_RANGE_NOTPRODUCT_FLAG(type, name, value, doc)   ); emit_range_##type(#name
280#define EMIT_RANGE_LP64_PRODUCT_FLAG(type, name, value, doc) ); emit_range_##type(#name
281
282// Generate func argument to pass into emit_range_xxx functions
283#define EMIT_RANGE_CHECK(a, b)                               , a, b
284
285#define INITIAL_RANGES_SIZE 379
286GrowableArray<CommandLineFlagRange*>* CommandLineFlagRangeList::_ranges = NULL;
287
288// Check the ranges of all flags that have them
289void CommandLineFlagRangeList::init(void) {
290
291  _ranges = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<CommandLineFlagRange*>(INITIAL_RANGES_SIZE, true);
292
293  emit_range_no(NULL RUNTIME_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
294                                   EMIT_RANGE_PD_DEVELOPER_FLAG,
295                                   EMIT_RANGE_PRODUCT_FLAG,
296                                   EMIT_RANGE_PD_PRODUCT_FLAG,
297                                   EMIT_RANGE_DIAGNOSTIC_FLAG,
298                                   EMIT_RANGE_EXPERIMENTAL_FLAG,
299                                   EMIT_RANGE_NOTPRODUCT_FLAG,
300                                   EMIT_RANGE_MANAGEABLE_FLAG,
301                                   EMIT_RANGE_PRODUCT_RW_FLAG,
302                                   EMIT_RANGE_LP64_PRODUCT_FLAG,
303                                   EMIT_RANGE_CHECK,
304                                   IGNORE_CONSTRAINT) );
305
306  EMIT_RANGES_FOR_GLOBALS_EXT
307
308  emit_range_no(NULL ARCH_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
309                                EMIT_RANGE_PRODUCT_FLAG,
310                                EMIT_RANGE_DIAGNOSTIC_FLAG,
311                                EMIT_RANGE_EXPERIMENTAL_FLAG,
312                                EMIT_RANGE_NOTPRODUCT_FLAG,
313                                EMIT_RANGE_CHECK,
314                                IGNORE_CONSTRAINT));
315
316#if INCLUDE_JVMCI
317  emit_range_no(NULL JVMCI_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
318                                 EMIT_RANGE_PD_DEVELOPER_FLAG,
319                                 EMIT_RANGE_PRODUCT_FLAG,
320                                 EMIT_RANGE_PD_PRODUCT_FLAG,
321                                 EMIT_RANGE_DIAGNOSTIC_FLAG,
322                                 EMIT_RANGE_EXPERIMENTAL_FLAG,
323                                 EMIT_RANGE_NOTPRODUCT_FLAG,
324                                 EMIT_RANGE_CHECK,
325                                 IGNORE_CONSTRAINT));
326#endif // INCLUDE_JVMCI
327
328#ifdef COMPILER1
329  emit_range_no(NULL C1_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
330                              EMIT_RANGE_PD_DEVELOPER_FLAG,
331                              EMIT_RANGE_PRODUCT_FLAG,
332                              EMIT_RANGE_PD_PRODUCT_FLAG,
333                              EMIT_RANGE_DIAGNOSTIC_FLAG,
334                              EMIT_RANGE_NOTPRODUCT_FLAG,
335                              EMIT_RANGE_CHECK,
336                              IGNORE_CONSTRAINT));
337#endif // COMPILER1
338
339#ifdef COMPILER2
340  emit_range_no(NULL C2_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
341                              EMIT_RANGE_PD_DEVELOPER_FLAG,
342                              EMIT_RANGE_PRODUCT_FLAG,
343                              EMIT_RANGE_PD_PRODUCT_FLAG,
344                              EMIT_RANGE_DIAGNOSTIC_FLAG,
345                              EMIT_RANGE_EXPERIMENTAL_FLAG,
346                              EMIT_RANGE_NOTPRODUCT_FLAG,
347                              EMIT_RANGE_CHECK,
348                              IGNORE_CONSTRAINT));
349#endif // COMPILER2
350
351#if INCLUDE_ALL_GCS
352  emit_range_no(NULL G1_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_EXPERIMENTAL_FLAG,
358                              EMIT_RANGE_NOTPRODUCT_FLAG,
359                              EMIT_RANGE_MANAGEABLE_FLAG,
360                              EMIT_RANGE_PRODUCT_RW_FLAG,
361                              EMIT_RANGE_CHECK,
362                              IGNORE_CONSTRAINT));
363#endif // INCLUDE_ALL_GCS
364}
365
366CommandLineFlagRange* CommandLineFlagRangeList::find(const char* name) {
367  CommandLineFlagRange* found = NULL;
368  for (int i=0; i<length(); i++) {
369    CommandLineFlagRange* range = at(i);
370    if (strcmp(range->name(), name) == 0) {
371      found = range;
372      break;
373    }
374  }
375  return found;
376}
377
378void CommandLineFlagRangeList::print(const char* name, outputStream* st, bool unspecified) {
379  CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
380  if (range != NULL) {
381    range->print(st);
382  } else if (unspecified == true) {
383    st->print("[                           ...                           ]");
384  }
385}
386
387bool CommandLineFlagRangeList::check_ranges() {
388  // Check ranges.
389  bool status = true;
390  for (int i=0; i<length(); i++) {
391    CommandLineFlagRange* range = at(i);
392    const char* name = range->name();
393    Flag* flag = Flag::find_flag(name, strlen(name), true, true);
394    // We must check for NULL here as lp64_product flags on 32 bit architecture
395    // can generate range check (despite that they are declared as constants),
396    // but they will not be returned by Flag::find_flag()
397    if (flag != NULL) {
398      if (flag->is_int()) {
399        int value = flag->get_int();
400        if (range->check_int(value, true) != Flag::SUCCESS) status = false;
401      } else if (flag->is_uint()) {
402        uint value = flag->get_uint();
403        if (range->check_uint(value, true) != Flag::SUCCESS) status = false;
404      } else if (flag->is_intx()) {
405        intx value = flag->get_intx();
406        if (range->check_intx(value, true) != Flag::SUCCESS) status = false;
407      } else if (flag->is_uintx()) {
408        uintx value = flag->get_uintx();
409        if (range->check_uintx(value, true) != Flag::SUCCESS) status = false;
410      } else if (flag->is_uint64_t()) {
411        uint64_t value = flag->get_uint64_t();
412        if (range->check_uint64_t(value, true) != Flag::SUCCESS) status = false;
413      } else if (flag->is_size_t()) {
414        size_t value = flag->get_size_t();
415        if (range->check_size_t(value, true) != Flag::SUCCESS) status = false;
416      } else if (flag->is_double()) {
417        double value = flag->get_double();
418        if (range->check_double(value, true) != Flag::SUCCESS) status = false;
419      }
420    }
421  }
422  return status;
423}
424