1 /*
2  * Copyright (c) 2015, 2020, 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/jvmFlagConstraintsGC.hpp"
29 #include "runtime/arguments.hpp"
30 #include "runtime/flags/jvmFlag.hpp"
31 #include "runtime/flags/jvmFlagConstraintList.hpp"
32 #include "runtime/flags/jvmFlagConstraintsCompiler.hpp"
33 #include "runtime/flags/jvmFlagConstraintsRuntime.hpp"
34 #include "runtime/globals.hpp"
35 #include "runtime/globals_extension.hpp"
36 #include "runtime/os.hpp"
37 #include "utilities/macros.hpp"
38 
39 class JVMFlagConstraint_bool : public JVMFlagConstraint {
40   JVMFlagConstraintFunc_bool _constraint;
41 
42 public:
JVMFlagConstraint_bool(const JVMFlag * flag,JVMFlagConstraintFunc_bool func,ConstraintType type)43   JVMFlagConstraint_bool(const JVMFlag* flag,
44                          JVMFlagConstraintFunc_bool func,
45                          ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
46 
apply(bool verbose)47   JVMFlag::Error apply(bool verbose) {
48     return _constraint(_flag->get_bool(), verbose);
49   }
50 
apply_bool(bool value,bool verbose)51   JVMFlag::Error apply_bool(bool value, bool verbose) {
52     return _constraint(value, verbose);
53   }
54 };
55 
56 class JVMFlagConstraint_int : public JVMFlagConstraint {
57   JVMFlagConstraintFunc_int _constraint;
58 
59 public:
JVMFlagConstraint_int(const JVMFlag * flag,JVMFlagConstraintFunc_int func,ConstraintType type)60   JVMFlagConstraint_int(const JVMFlag* flag,
61                         JVMFlagConstraintFunc_int func,
62                         ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
63 
apply(bool verbose)64   JVMFlag::Error apply(bool verbose) {
65     return _constraint(_flag->get_int(), verbose);
66   }
67 
apply_int(int value,bool verbose)68   JVMFlag::Error apply_int(int value, bool verbose) {
69     return _constraint(value, verbose);
70   }
71 };
72 
73 class JVMFlagConstraint_intx : public JVMFlagConstraint {
74   JVMFlagConstraintFunc_intx _constraint;
75 
76 public:
JVMFlagConstraint_intx(const JVMFlag * flag,JVMFlagConstraintFunc_intx func,ConstraintType type)77   JVMFlagConstraint_intx(const JVMFlag* flag,
78                          JVMFlagConstraintFunc_intx func,
79                          ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
80 
apply(bool verbose)81   JVMFlag::Error apply(bool verbose) {
82     return _constraint(_flag->get_intx(), verbose);
83   }
84 
apply_intx(intx value,bool verbose)85   JVMFlag::Error apply_intx(intx value, bool verbose) {
86     return _constraint(value, verbose);
87   }
88 };
89 
90 class JVMFlagConstraint_uint : public JVMFlagConstraint {
91   JVMFlagConstraintFunc_uint _constraint;
92 
93 public:
JVMFlagConstraint_uint(const JVMFlag * flag,JVMFlagConstraintFunc_uint func,ConstraintType type)94   JVMFlagConstraint_uint(const JVMFlag* flag,
95                          JVMFlagConstraintFunc_uint func,
96                          ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
97 
apply(bool verbose)98   JVMFlag::Error apply(bool verbose) {
99     return _constraint(_flag->get_uint(), verbose);
100   }
101 
apply_uint(uint value,bool verbose)102   JVMFlag::Error apply_uint(uint value, bool verbose) {
103     return _constraint(value, verbose);
104   }
105 };
106 
107 class JVMFlagConstraint_uintx : public JVMFlagConstraint {
108   JVMFlagConstraintFunc_uintx _constraint;
109 
110 public:
JVMFlagConstraint_uintx(const JVMFlag * flag,JVMFlagConstraintFunc_uintx func,ConstraintType type)111   JVMFlagConstraint_uintx(const JVMFlag* flag,
112                           JVMFlagConstraintFunc_uintx func,
113                           ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
114 
apply(bool verbose)115   JVMFlag::Error apply(bool verbose) {
116     return _constraint(_flag->get_uintx(), verbose);
117   }
118 
apply_uintx(uintx value,bool verbose)119   JVMFlag::Error apply_uintx(uintx value, bool verbose) {
120     return _constraint(value, verbose);
121   }
122 };
123 
124 class JVMFlagConstraint_uint64_t : public JVMFlagConstraint {
125   JVMFlagConstraintFunc_uint64_t _constraint;
126 
127 public:
JVMFlagConstraint_uint64_t(const JVMFlag * flag,JVMFlagConstraintFunc_uint64_t func,ConstraintType type)128   JVMFlagConstraint_uint64_t(const JVMFlag* flag,
129                              JVMFlagConstraintFunc_uint64_t func,
130                              ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
131 
apply(bool verbose)132   JVMFlag::Error apply(bool verbose) {
133     return _constraint(_flag->get_uint64_t(), verbose);
134   }
135 
apply_uint64_t(uint64_t value,bool verbose)136   JVMFlag::Error apply_uint64_t(uint64_t value, bool verbose) {
137     return _constraint(value, verbose);
138   }
139 };
140 
141 class JVMFlagConstraint_size_t : public JVMFlagConstraint {
142   JVMFlagConstraintFunc_size_t _constraint;
143 
144 public:
JVMFlagConstraint_size_t(const JVMFlag * flag,JVMFlagConstraintFunc_size_t func,ConstraintType type)145   JVMFlagConstraint_size_t(const JVMFlag* flag,
146                            JVMFlagConstraintFunc_size_t func,
147                            ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
148 
apply(bool verbose)149   JVMFlag::Error apply(bool verbose) {
150     return _constraint(_flag->get_size_t(), verbose);
151   }
152 
apply_size_t(size_t value,bool verbose)153   JVMFlag::Error apply_size_t(size_t value, bool verbose) {
154     return _constraint(value, verbose);
155   }
156 };
157 
158 class JVMFlagConstraint_double : public JVMFlagConstraint {
159   JVMFlagConstraintFunc_double _constraint;
160 
161 public:
JVMFlagConstraint_double(const JVMFlag * flag,JVMFlagConstraintFunc_double func,ConstraintType type)162   JVMFlagConstraint_double(const JVMFlag* flag,
163                            JVMFlagConstraintFunc_double func,
164                            ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
165 
apply(bool verbose)166   JVMFlag::Error apply(bool verbose) {
167     return _constraint(_flag->get_double(), verbose);
168   }
169 
apply_double(double value,bool verbose)170   JVMFlag::Error apply_double(double value, bool verbose) {
171     return _constraint(value, verbose);
172   }
173 };
174 
175 // No constraint emitting
emit_constraint_no(...)176 void emit_constraint_no(...)                            { /* NOP */ }
177 
178 // No constraint emitting if function argument is NOT provided
emit_constraint_bool(const JVMFlag *)179 void emit_constraint_bool(const JVMFlag* /*flag*/)      { /* NOP */ }
emit_constraint_ccstr(const JVMFlag *)180 void emit_constraint_ccstr(const JVMFlag* /*flag*/)     { /* NOP */ }
emit_constraint_ccstrlist(const JVMFlag *)181 void emit_constraint_ccstrlist(const JVMFlag* /*flag*/) { /* NOP */ }
emit_constraint_int(const JVMFlag *)182 void emit_constraint_int(const JVMFlag* /*flag*/)       { /* NOP */ }
emit_constraint_intx(const JVMFlag *)183 void emit_constraint_intx(const JVMFlag* /*flag*/)      { /* NOP */ }
emit_constraint_uint(const JVMFlag *)184 void emit_constraint_uint(const JVMFlag* /*flag*/)      { /* NOP */ }
emit_constraint_uintx(const JVMFlag *)185 void emit_constraint_uintx(const JVMFlag* /*flag*/)     { /* NOP */ }
emit_constraint_uint64_t(const JVMFlag *)186 void emit_constraint_uint64_t(const JVMFlag* /*flag*/)  { /* NOP */ }
emit_constraint_size_t(const JVMFlag *)187 void emit_constraint_size_t(const JVMFlag* /*flag*/)    { /* NOP */ }
emit_constraint_double(const JVMFlag *)188 void emit_constraint_double(const JVMFlag* /*flag*/)    { /* NOP */ }
189 
190 // JVMFlagConstraint emitting code functions if function argument is provided
emit_constraint_bool(const JVMFlag * flag,JVMFlagConstraintFunc_bool func,JVMFlagConstraint::ConstraintType type)191 void emit_constraint_bool(const JVMFlag* flag, JVMFlagConstraintFunc_bool func, JVMFlagConstraint::ConstraintType type) {
192   JVMFlagConstraintList::add(new JVMFlagConstraint_bool(flag, func, type));
193 }
emit_constraint_int(const JVMFlag * flag,JVMFlagConstraintFunc_int func,JVMFlagConstraint::ConstraintType type)194 void emit_constraint_int(const JVMFlag* flag, JVMFlagConstraintFunc_int func, JVMFlagConstraint::ConstraintType type) {
195   JVMFlagConstraintList::add(new JVMFlagConstraint_int(flag, func, type));
196 }
emit_constraint_intx(const JVMFlag * flag,JVMFlagConstraintFunc_intx func,JVMFlagConstraint::ConstraintType type)197 void emit_constraint_intx(const JVMFlag* flag, JVMFlagConstraintFunc_intx func, JVMFlagConstraint::ConstraintType type) {
198   JVMFlagConstraintList::add(new JVMFlagConstraint_intx(flag, func, type));
199 }
emit_constraint_uint(const JVMFlag * flag,JVMFlagConstraintFunc_uint func,JVMFlagConstraint::ConstraintType type)200 void emit_constraint_uint(const JVMFlag* flag, JVMFlagConstraintFunc_uint func, JVMFlagConstraint::ConstraintType type) {
201   JVMFlagConstraintList::add(new JVMFlagConstraint_uint(flag, func, type));
202 }
emit_constraint_uintx(const JVMFlag * flag,JVMFlagConstraintFunc_uintx func,JVMFlagConstraint::ConstraintType type)203 void emit_constraint_uintx(const JVMFlag* flag, JVMFlagConstraintFunc_uintx func, JVMFlagConstraint::ConstraintType type) {
204   JVMFlagConstraintList::add(new JVMFlagConstraint_uintx(flag, func, type));
205 }
emit_constraint_uint64_t(const JVMFlag * flag,JVMFlagConstraintFunc_uint64_t func,JVMFlagConstraint::ConstraintType type)206 void emit_constraint_uint64_t(const JVMFlag* flag, JVMFlagConstraintFunc_uint64_t func, JVMFlagConstraint::ConstraintType type) {
207   JVMFlagConstraintList::add(new JVMFlagConstraint_uint64_t(flag, func, type));
208 }
emit_constraint_size_t(const JVMFlag * flag,JVMFlagConstraintFunc_size_t func,JVMFlagConstraint::ConstraintType type)209 void emit_constraint_size_t(const JVMFlag* flag, JVMFlagConstraintFunc_size_t func, JVMFlagConstraint::ConstraintType type) {
210   JVMFlagConstraintList::add(new JVMFlagConstraint_size_t(flag, func, type));
211 }
emit_constraint_double(const JVMFlag * flag,JVMFlagConstraintFunc_double func,JVMFlagConstraint::ConstraintType type)212 void emit_constraint_double(const JVMFlag* flag, JVMFlagConstraintFunc_double func, JVMFlagConstraint::ConstraintType type) {
213   JVMFlagConstraintList::add(new JVMFlagConstraint_double(flag, func, type));
214 }
215 
216 // Generate code to call emit_constraint_xxx function
217 #define EMIT_CONSTRAINT_START       (void)(0
218 #define EMIT_CONSTRAINT(type, name) ); emit_constraint_##type(JVMFlagEx::flag_from_enum(FLAG_MEMBER_ENUM(name))
219 #define EMIT_CONSTRAINT_NO          ); emit_constraint_no(0
220 #define EMIT_CONSTRAINT_PRODUCT_FLAG(type, name, value, doc)      EMIT_CONSTRAINT(type, name)
221 #define EMIT_CONSTRAINT_DIAGNOSTIC_FLAG(type, name, value, doc)   EMIT_CONSTRAINT(type, name)
222 #define EMIT_CONSTRAINT_EXPERIMENTAL_FLAG(type, name, value, doc) EMIT_CONSTRAINT(type, name)
223 #define EMIT_CONSTRAINT_MANAGEABLE_FLAG(type, name, value, doc)   EMIT_CONSTRAINT(type, name)
224 #define EMIT_CONSTRAINT_PRODUCT_RW_FLAG(type, name, value, doc)   EMIT_CONSTRAINT(type, name)
225 #define EMIT_CONSTRAINT_PD_PRODUCT_FLAG(type, name, doc)          EMIT_CONSTRAINT(type, name)
226 #define EMIT_CONSTRAINT_PD_DIAGNOSTIC_FLAG(type, name, doc)       EMIT_CONSTRAINT(type, name)
227 #ifndef PRODUCT
228 #define EMIT_CONSTRAINT_DEVELOPER_FLAG(type, name, value, doc)    EMIT_CONSTRAINT(type, name)
229 #define EMIT_CONSTRAINT_PD_DEVELOPER_FLAG(type, name, doc)        EMIT_CONSTRAINT(type, name)
230 #define EMIT_CONSTRAINT_NOTPRODUCT_FLAG(type, name, value, doc)   EMIT_CONSTRAINT(type, name)
231 #else
232 #define EMIT_CONSTRAINT_DEVELOPER_FLAG(type, name, value, doc)    EMIT_CONSTRAINT_NO
233 #define EMIT_CONSTRAINT_PD_DEVELOPER_FLAG(type, name, doc)        EMIT_CONSTRAINT_NO
234 #define EMIT_CONSTRAINT_NOTPRODUCT_FLAG(type, name, value, doc)   EMIT_CONSTRAINT_NO
235 #endif
236 #ifdef _LP64
237 #define EMIT_CONSTRAINT_LP64_PRODUCT_FLAG(type, name, value, doc) EMIT_CONSTRAINT(type, name)
238 #else
239 #define EMIT_CONSTRAINT_LP64_PRODUCT_FLAG(type, name, value, doc) EMIT_CONSTRAINT_NO
240 #endif
241 #define EMIT_CONSTRAINT_END         );
242 
243 // Generate func argument to pass into emit_constraint_xxx functions
244 #define EMIT_CONSTRAINT_CHECK(func, type)                         , func, JVMFlagConstraint::type
245 
246 // the "name" argument must be a string literal
247 #define INITIAL_CONSTRAINTS_SIZE 72
248 GrowableArray<JVMFlagConstraint*>* JVMFlagConstraintList::_constraints = NULL;
249 JVMFlagConstraint::ConstraintType JVMFlagConstraintList::_validating_type = JVMFlagConstraint::AtParse;
250 
251 // Check the ranges of all flags that have them or print them out and exit if requested
init(void)252 void JVMFlagConstraintList::init(void) {
253   _constraints = new (ResourceObj::C_HEAP, mtArguments) GrowableArray<JVMFlagConstraint*>(INITIAL_CONSTRAINTS_SIZE, true);
254 
255   EMIT_CONSTRAINT_START
256 
257   ALL_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
258             EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
259             EMIT_CONSTRAINT_PRODUCT_FLAG,
260             EMIT_CONSTRAINT_PD_PRODUCT_FLAG,
261             EMIT_CONSTRAINT_DIAGNOSTIC_FLAG,
262             EMIT_CONSTRAINT_PD_DIAGNOSTIC_FLAG,
263             EMIT_CONSTRAINT_EXPERIMENTAL_FLAG,
264             EMIT_CONSTRAINT_NOTPRODUCT_FLAG,
265             EMIT_CONSTRAINT_MANAGEABLE_FLAG,
266             EMIT_CONSTRAINT_PRODUCT_RW_FLAG,
267             EMIT_CONSTRAINT_LP64_PRODUCT_FLAG,
268             IGNORE_RANGE,
269             EMIT_CONSTRAINT_CHECK)
270 
271   EMIT_CONSTRAINT_END
272 }
273 
find(const JVMFlag * flag)274 JVMFlagConstraint* JVMFlagConstraintList::find(const JVMFlag* flag) {
275   JVMFlagConstraint* found = NULL;
276   for (int i=0; i<length(); i++) {
277     JVMFlagConstraint* constraint = at(i);
278     if (constraint->flag() == flag) {
279       found = constraint;
280       break;
281     }
282   }
283   return found;
284 }
285 
286 // Find constraints and return only if found constraint's type is equal or lower than current validating type.
find_if_needs_check(const JVMFlag * flag)287 JVMFlagConstraint* JVMFlagConstraintList::find_if_needs_check(const JVMFlag* flag) {
288   JVMFlagConstraint* found = NULL;
289   JVMFlagConstraint* constraint = find(flag);
290   if (constraint != NULL && (constraint->type() <= _validating_type)) {
291     found = constraint;
292   }
293   return found;
294 }
295 
296 // Check constraints for specific constraint type.
check_constraints(JVMFlagConstraint::ConstraintType type)297 bool JVMFlagConstraintList::check_constraints(JVMFlagConstraint::ConstraintType type) {
298   guarantee(type > _validating_type, "Constraint check is out of order.");
299   _validating_type = type;
300 
301   bool status = true;
302   for (int i=0; i<length(); i++) {
303     JVMFlagConstraint* constraint = at(i);
304     if (type != constraint->type()) continue;
305     if (constraint->apply(true) != JVMFlag::SUCCESS) status = false;
306   }
307   return status;
308 }
309