commandLineFlagConstraintList.cpp revision 9173:3f28db271235
1/*
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25#include "precompiled.hpp"
26#include "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/commandLineFlagConstraintsCompiler.hpp"
32#include "runtime/commandLineFlagConstraintsGC.hpp"
33#include "runtime/commandLineFlagConstraintsRuntime.hpp"
34#include "runtime/os.hpp"
35#include "utilities/macros.hpp"
36
37class CommandLineFlagConstraint_bool : public CommandLineFlagConstraint {
38  CommandLineFlagConstraintFunc_bool _constraint;
39
40public:
41  // the "name" argument must be a string literal
42  CommandLineFlagConstraint_bool(const char* name,
43                                 CommandLineFlagConstraintFunc_bool func,
44                                 ConstraintType type) : CommandLineFlagConstraint(name, type) {
45    _constraint=func;
46  }
47
48  Flag::Error apply_bool(bool value, bool verbose) {
49    return _constraint(value, verbose);
50  }
51};
52
53class CommandLineFlagConstraint_int : public CommandLineFlagConstraint {
54  CommandLineFlagConstraintFunc_int _constraint;
55
56public:
57  // the "name" argument must be a string literal
58  CommandLineFlagConstraint_int(const char* name,
59                                CommandLineFlagConstraintFunc_int func,
60                                ConstraintType type) : CommandLineFlagConstraint(name, type) {
61    _constraint=func;
62  }
63
64  Flag::Error apply_int(int value, bool verbose) {
65    return _constraint(value, verbose);
66  }
67};
68
69class CommandLineFlagConstraint_intx : public CommandLineFlagConstraint {
70  CommandLineFlagConstraintFunc_intx _constraint;
71
72public:
73  // the "name" argument must be a string literal
74  CommandLineFlagConstraint_intx(const char* name,
75                                 CommandLineFlagConstraintFunc_intx func,
76                                 ConstraintType type) : CommandLineFlagConstraint(name, type) {
77    _constraint=func;
78  }
79
80  Flag::Error apply_intx(intx value, bool verbose) {
81    return _constraint(value, verbose);
82  }
83};
84
85class CommandLineFlagConstraint_uint : public CommandLineFlagConstraint {
86  CommandLineFlagConstraintFunc_uint _constraint;
87
88public:
89  // the "name" argument must be a string literal
90  CommandLineFlagConstraint_uint(const char* name,
91                                 CommandLineFlagConstraintFunc_uint func,
92                                 ConstraintType type) : CommandLineFlagConstraint(name, type) {
93    _constraint=func;
94  }
95
96  Flag::Error apply_uint(uint value, bool verbose) {
97    return _constraint(value, verbose);
98  }
99};
100
101class CommandLineFlagConstraint_uintx : public CommandLineFlagConstraint {
102  CommandLineFlagConstraintFunc_uintx _constraint;
103
104public:
105  // the "name" argument must be a string literal
106  CommandLineFlagConstraint_uintx(const char* name,
107                                  CommandLineFlagConstraintFunc_uintx func,
108                                  ConstraintType type) : CommandLineFlagConstraint(name, type) {
109    _constraint=func;
110  }
111
112  Flag::Error apply_uintx(uintx value, bool verbose) {
113    return _constraint(value, verbose);
114  }
115};
116
117class CommandLineFlagConstraint_uint64_t : public CommandLineFlagConstraint {
118  CommandLineFlagConstraintFunc_uint64_t _constraint;
119
120public:
121  // the "name" argument must be a string literal
122  CommandLineFlagConstraint_uint64_t(const char* name,
123                                     CommandLineFlagConstraintFunc_uint64_t func,
124                                     ConstraintType type) : CommandLineFlagConstraint(name, type) {
125    _constraint=func;
126  }
127
128  Flag::Error apply_uint64_t(uint64_t value, bool verbose) {
129    return _constraint(value, verbose);
130  }
131};
132
133class CommandLineFlagConstraint_size_t : public CommandLineFlagConstraint {
134  CommandLineFlagConstraintFunc_size_t _constraint;
135
136public:
137  // the "name" argument must be a string literal
138  CommandLineFlagConstraint_size_t(const char* name,
139                                   CommandLineFlagConstraintFunc_size_t func,
140                                   ConstraintType type) : CommandLineFlagConstraint(name, type) {
141    _constraint=func;
142  }
143
144  Flag::Error apply_size_t(size_t value, bool verbose) {
145    return _constraint(value, verbose);
146  }
147};
148
149class CommandLineFlagConstraint_double : public CommandLineFlagConstraint {
150  CommandLineFlagConstraintFunc_double _constraint;
151
152public:
153  // the "name" argument must be a string literal
154  CommandLineFlagConstraint_double(const char* name,
155                                   CommandLineFlagConstraintFunc_double func,
156                                   ConstraintType type) : CommandLineFlagConstraint(name, type) {
157    _constraint=func;
158  }
159
160  Flag::Error apply_double(double value, bool verbose) {
161    return _constraint(value, verbose);
162  }
163};
164
165// No constraint emitting
166void emit_constraint_no(...)                          { /* NOP */ }
167
168// No constraint emitting if function argument is NOT provided
169void emit_constraint_bool(const char* /*name*/)       { /* NOP */ }
170void emit_constraint_ccstr(const char* /*name*/)      { /* NOP */ }
171void emit_constraint_ccstrlist(const char* /*name*/)  { /* NOP */ }
172void emit_constraint_int(const char* /*name*/)        { /* NOP */ }
173void emit_constraint_intx(const char* /*name*/)       { /* NOP */ }
174void emit_constraint_uint(const char* /*name*/)       { /* NOP */ }
175void emit_constraint_uintx(const char* /*name*/)      { /* NOP */ }
176void emit_constraint_uint64_t(const char* /*name*/)   { /* NOP */ }
177void emit_constraint_size_t(const char* /*name*/)     { /* NOP */ }
178void emit_constraint_double(const char* /*name*/)     { /* NOP */ }
179
180// CommandLineFlagConstraint emitting code functions if function argument is provided
181void emit_constraint_bool(const char* name, CommandLineFlagConstraintFunc_bool func, CommandLineFlagConstraint::ConstraintType type) {
182  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_bool(name, func, type));
183}
184void emit_constraint_int(const char* name, CommandLineFlagConstraintFunc_int func, CommandLineFlagConstraint::ConstraintType type) {
185  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_int(name, func, type));
186}
187void emit_constraint_intx(const char* name, CommandLineFlagConstraintFunc_intx func, CommandLineFlagConstraint::ConstraintType type) {
188  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_intx(name, func, type));
189}
190void emit_constraint_uint(const char* name, CommandLineFlagConstraintFunc_uint func, CommandLineFlagConstraint::ConstraintType type) {
191  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uint(name, func, type));
192}
193void emit_constraint_uintx(const char* name, CommandLineFlagConstraintFunc_uintx func, CommandLineFlagConstraint::ConstraintType type) {
194  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uintx(name, func, type));
195}
196void emit_constraint_uint64_t(const char* name, CommandLineFlagConstraintFunc_uint64_t func, CommandLineFlagConstraint::ConstraintType type) {
197  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uint64_t(name, func, type));
198}
199void emit_constraint_size_t(const char* name, CommandLineFlagConstraintFunc_size_t func, CommandLineFlagConstraint::ConstraintType type) {
200  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_size_t(name, func, type));
201}
202void emit_constraint_double(const char* name, CommandLineFlagConstraintFunc_double func, CommandLineFlagConstraint::ConstraintType type) {
203  CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_double(name, func, type));
204}
205
206// Generate code to call emit_constraint_xxx function
207#define EMIT_CONSTRAINT_PRODUCT_FLAG(type, name, value, doc)      ); emit_constraint_##type(#name
208#define EMIT_CONSTRAINT_COMMERCIAL_FLAG(type, name, value, doc)   ); emit_constraint_##type(#name
209#define EMIT_CONSTRAINT_DIAGNOSTIC_FLAG(type, name, value, doc)   ); emit_constraint_##type(#name
210#define EMIT_CONSTRAINT_EXPERIMENTAL_FLAG(type, name, value, doc) ); emit_constraint_##type(#name
211#define EMIT_CONSTRAINT_MANAGEABLE_FLAG(type, name, value, doc)   ); emit_constraint_##type(#name
212#define EMIT_CONSTRAINT_PRODUCT_RW_FLAG(type, name, value, doc)   ); emit_constraint_##type(#name
213#define EMIT_CONSTRAINT_PD_PRODUCT_FLAG(type, name, doc)          ); emit_constraint_##type(#name
214#define EMIT_CONSTRAINT_DEVELOPER_FLAG(type, name, value, doc)    ); emit_constraint_##type(#name
215#define EMIT_CONSTRAINT_PD_DEVELOPER_FLAG(type, name, doc)        ); emit_constraint_##type(#name
216#define EMIT_CONSTRAINT_NOTPRODUCT_FLAG(type, name, value, doc)   ); emit_constraint_##type(#name
217#define EMIT_CONSTRAINT_LP64_PRODUCT_FLAG(type, name, value, doc) ); emit_constraint_##type(#name
218
219// Generate func argument to pass into emit_constraint_xxx functions
220#define EMIT_CONSTRAINT_CHECK(func, type)                               , func, CommandLineFlagConstraint::type
221
222// the "name" argument must be a string literal
223#define INITIAL_CONSTRAINTS_SIZE 45
224GrowableArray<CommandLineFlagConstraint*>* CommandLineFlagConstraintList::_constraints = NULL;
225CommandLineFlagConstraint::ConstraintType CommandLineFlagConstraintList::_validating_type = CommandLineFlagConstraint::AtParse;
226
227// Check the ranges of all flags that have them or print them out and exit if requested
228void CommandLineFlagConstraintList::init(void) {
229  _constraints = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<CommandLineFlagConstraint*>(INITIAL_CONSTRAINTS_SIZE, true);
230
231  emit_constraint_no(NULL RUNTIME_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
232                                        EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
233                                        EMIT_CONSTRAINT_PRODUCT_FLAG,
234                                        EMIT_CONSTRAINT_PD_PRODUCT_FLAG,
235                                        EMIT_CONSTRAINT_DIAGNOSTIC_FLAG,
236                                        EMIT_CONSTRAINT_EXPERIMENTAL_FLAG,
237                                        EMIT_CONSTRAINT_NOTPRODUCT_FLAG,
238                                        EMIT_CONSTRAINT_MANAGEABLE_FLAG,
239                                        EMIT_CONSTRAINT_PRODUCT_RW_FLAG,
240                                        EMIT_CONSTRAINT_LP64_PRODUCT_FLAG,
241                                        IGNORE_RANGE,
242                                        EMIT_CONSTRAINT_CHECK));
243
244  EMIT_CONSTRAINTS_FOR_GLOBALS_EXT
245
246  emit_constraint_no(NULL ARCH_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
247                                     EMIT_CONSTRAINT_PRODUCT_FLAG,
248                                     EMIT_CONSTRAINT_DIAGNOSTIC_FLAG,
249                                     EMIT_CONSTRAINT_EXPERIMENTAL_FLAG,
250                                     EMIT_CONSTRAINT_NOTPRODUCT_FLAG,
251                                     IGNORE_RANGE,
252                                     EMIT_CONSTRAINT_CHECK));
253
254#ifdef COMPILER1
255  emit_constraint_no(NULL C1_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
256                                   EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
257                                   EMIT_CONSTRAINT_PRODUCT_FLAG,
258                                   EMIT_CONSTRAINT_PD_PRODUCT_FLAG,
259                                   EMIT_CONSTRAINT_DIAGNOSTIC_FLAG,
260                                   EMIT_CONSTRAINT_NOTPRODUCT_FLAG,
261                                   IGNORE_RANGE,
262                                   EMIT_CONSTRAINT_CHECK));
263#endif // COMPILER1
264
265#ifdef COMPILER2
266  emit_constraint_no(NULL C2_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
267                                   EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
268                                   EMIT_CONSTRAINT_PRODUCT_FLAG,
269                                   EMIT_CONSTRAINT_PD_PRODUCT_FLAG,
270                                   EMIT_CONSTRAINT_DIAGNOSTIC_FLAG,
271                                   EMIT_CONSTRAINT_EXPERIMENTAL_FLAG,
272                                   EMIT_CONSTRAINT_NOTPRODUCT_FLAG,
273                                   IGNORE_RANGE,
274                                   EMIT_CONSTRAINT_CHECK));
275#endif // COMPILER2
276
277#if INCLUDE_ALL_GCS
278  emit_constraint_no(NULL G1_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
279                                   EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
280                                   EMIT_CONSTRAINT_PRODUCT_FLAG,
281                                   EMIT_CONSTRAINT_PD_PRODUCT_FLAG,
282                                   EMIT_CONSTRAINT_DIAGNOSTIC_FLAG,
283                                   EMIT_CONSTRAINT_EXPERIMENTAL_FLAG,
284                                   EMIT_CONSTRAINT_NOTPRODUCT_FLAG,
285                                   EMIT_CONSTRAINT_MANAGEABLE_FLAG,
286                                   EMIT_CONSTRAINT_PRODUCT_RW_FLAG,
287                                   IGNORE_RANGE,
288                                   EMIT_CONSTRAINT_CHECK));
289#endif // INCLUDE_ALL_GCS
290}
291
292// Find constraints by name and return only if found constraint's type is equal or lower than current validating type.
293CommandLineFlagConstraint* CommandLineFlagConstraintList::find_if_needs_check(const char* name) {
294  CommandLineFlagConstraint* found = NULL;
295  for (int i=0; i<length(); i++) {
296    CommandLineFlagConstraint* constraint = at(i);
297    if ((strcmp(constraint->name(), name) == 0) &&
298        (constraint->type() <= _validating_type)) {
299      found = constraint;
300      break;
301    }
302  }
303  return found;
304}
305
306// Check constraints for specific constraint type.
307bool CommandLineFlagConstraintList::check_constraints(CommandLineFlagConstraint::ConstraintType type) {
308  guarantee(type > _validating_type, "Constraint check is out of order.");
309  _validating_type = type;
310
311  bool status = true;
312  for (int i=0; i<length(); i++) {
313    CommandLineFlagConstraint* constraint = at(i);
314    if (type != constraint->type()) continue;
315    const char* name = constraint->name();
316    Flag* flag = Flag::find_flag(name, strlen(name), true, true);
317    // We must check for NULL here as lp64_product flags on 32 bit architecture
318    // can generate constraint check (despite that they are declared as constants),
319    // but they will not be returned by Flag::find_flag()
320    if (flag != NULL) {
321      if (flag->is_bool()) {
322        bool value = flag->get_bool();
323        if (constraint->apply_bool(value, true) != Flag::SUCCESS) status = false;
324      } else if (flag->is_int()) {
325        int value = flag->get_int();
326        if (constraint->apply_int(value, true) != Flag::SUCCESS) status = false;
327      } else if (flag->is_uint()) {
328        uint value = flag->get_uint();
329        if (constraint->apply_uint(value, true) != Flag::SUCCESS) status = false;
330      } else if (flag->is_intx()) {
331        intx value = flag->get_intx();
332        if (constraint->apply_intx(value, true) != Flag::SUCCESS) status = false;
333      } else if (flag->is_uintx()) {
334        uintx value = flag->get_uintx();
335        if (constraint->apply_uintx(value, true) != Flag::SUCCESS) status = false;
336      } else if (flag->is_uint64_t()) {
337        uint64_t value = flag->get_uint64_t();
338        if (constraint->apply_uint64_t(value, true) != Flag::SUCCESS) status = false;
339      } else if (flag->is_size_t()) {
340        size_t value = flag->get_size_t();
341        if (constraint->apply_size_t(value, true) != Flag::SUCCESS) status = false;
342      } else if (flag->is_double()) {
343        double value = flag->get_double();
344        if (constraint->apply_double(value, true) != Flag::SUCCESS) status = false;
345      }
346    }
347  }
348  return status;
349}
350