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 #if INCLUDE_JVMCI 37 #include "jvmci/commandLineFlagConstraintsJVMCI.hpp" 38 #endif 39 40 class CommandLineFlagConstraint_bool : public CommandLineFlagConstraint { 41 CommandLineFlagConstraintFunc_bool _constraint; 42 43 public: 44 // the "name" argument must be a string literal 45 CommandLineFlagConstraint_bool(const char* name, 46 CommandLineFlagConstraintFunc_bool func, 47 ConstraintType type) : CommandLineFlagConstraint(name, type) { 48 _constraint=func; 49 } 50 51 Flag::Error apply_bool(bool value, bool verbose) { 52 return _constraint(value, verbose); 53 } 54 }; 55 56 class CommandLineFlagConstraint_int : public CommandLineFlagConstraint { 57 CommandLineFlagConstraintFunc_int _constraint; 58 59 public: 60 // the "name" argument must be a string literal 61 CommandLineFlagConstraint_int(const char* name, 62 CommandLineFlagConstraintFunc_int func, 63 ConstraintType type) : CommandLineFlagConstraint(name, type) { 64 _constraint=func; 65 } 66 67 Flag::Error apply_int(int value, bool verbose) { 68 return _constraint(value, verbose); 69 } 70 }; 71 72 class CommandLineFlagConstraint_intx : public CommandLineFlagConstraint { 73 CommandLineFlagConstraintFunc_intx _constraint; 74 75 public: 76 // the "name" argument must be a string literal 77 CommandLineFlagConstraint_intx(const char* name, 78 CommandLineFlagConstraintFunc_intx func, 79 ConstraintType type) : CommandLineFlagConstraint(name, type) { 80 _constraint=func; 81 } 82 83 Flag::Error apply_intx(intx value, bool verbose) { 84 return _constraint(value, verbose); 85 } 86 }; 87 88 class CommandLineFlagConstraint_uint : public CommandLineFlagConstraint { 89 CommandLineFlagConstraintFunc_uint _constraint; 90 91 public: 92 // the "name" argument must be a string literal 93 CommandLineFlagConstraint_uint(const char* name, 94 CommandLineFlagConstraintFunc_uint func, 95 ConstraintType type) : CommandLineFlagConstraint(name, type) { 96 _constraint=func; 97 } 98 99 Flag::Error apply_uint(uint value, bool verbose) { 100 return _constraint(value, verbose); 101 } 102 }; 103 104 class CommandLineFlagConstraint_uintx : public CommandLineFlagConstraint { 105 CommandLineFlagConstraintFunc_uintx _constraint; 106 107 public: 108 // the "name" argument must be a string literal 109 CommandLineFlagConstraint_uintx(const char* name, 110 CommandLineFlagConstraintFunc_uintx func, 111 ConstraintType type) : CommandLineFlagConstraint(name, type) { 112 _constraint=func; 113 } 114 115 Flag::Error apply_uintx(uintx value, bool verbose) { 116 return _constraint(value, verbose); 117 } 118 }; 119 120 class CommandLineFlagConstraint_uint64_t : public CommandLineFlagConstraint { 121 CommandLineFlagConstraintFunc_uint64_t _constraint; 122 123 public: 124 // the "name" argument must be a string literal 125 CommandLineFlagConstraint_uint64_t(const char* name, 126 CommandLineFlagConstraintFunc_uint64_t func, 127 ConstraintType type) : CommandLineFlagConstraint(name, type) { 128 _constraint=func; 129 } 130 131 Flag::Error apply_uint64_t(uint64_t value, bool verbose) { 132 return _constraint(value, verbose); 133 } 134 }; 135 136 class CommandLineFlagConstraint_size_t : public CommandLineFlagConstraint { 137 CommandLineFlagConstraintFunc_size_t _constraint; 138 139 public: 140 // the "name" argument must be a string literal 141 CommandLineFlagConstraint_size_t(const char* name, 142 CommandLineFlagConstraintFunc_size_t func, 143 ConstraintType type) : CommandLineFlagConstraint(name, type) { 144 _constraint=func; 145 } 146 147 Flag::Error apply_size_t(size_t value, bool verbose) { 148 return _constraint(value, verbose); 149 } 150 }; 151 152 class CommandLineFlagConstraint_double : public CommandLineFlagConstraint { 153 CommandLineFlagConstraintFunc_double _constraint; 154 155 public: 156 // the "name" argument must be a string literal 157 CommandLineFlagConstraint_double(const char* name, 158 CommandLineFlagConstraintFunc_double func, 159 ConstraintType type) : CommandLineFlagConstraint(name, type) { 160 _constraint=func; 161 } 162 163 Flag::Error apply_double(double value, bool verbose) { 164 return _constraint(value, verbose); 165 } 166 }; 167 168 // No constraint emitting 169 void emit_constraint_no(...) { /* NOP */ } 170 171 // No constraint emitting if function argument is NOT provided 172 void emit_constraint_bool(const char* /*name*/) { /* NOP */ } 173 void emit_constraint_ccstr(const char* /*name*/) { /* NOP */ } 174 void emit_constraint_ccstrlist(const char* /*name*/) { /* NOP */ } 175 void emit_constraint_int(const char* /*name*/) { /* NOP */ } 176 void emit_constraint_intx(const char* /*name*/) { /* NOP */ } 177 void emit_constraint_uint(const char* /*name*/) { /* NOP */ } 178 void emit_constraint_uintx(const char* /*name*/) { /* NOP */ } 179 void emit_constraint_uint64_t(const char* /*name*/) { /* NOP */ } 180 void emit_constraint_size_t(const char* /*name*/) { /* NOP */ } 181 void emit_constraint_double(const char* /*name*/) { /* NOP */ } 182 183 // CommandLineFlagConstraint emitting code functions if function argument is provided 184 void emit_constraint_bool(const char* name, CommandLineFlagConstraintFunc_bool func, CommandLineFlagConstraint::ConstraintType type) { 185 CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_bool(name, func, type)); 186 } 187 void emit_constraint_int(const char* name, CommandLineFlagConstraintFunc_int func, CommandLineFlagConstraint::ConstraintType type) { 188 CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_int(name, func, type)); 189 } 190 void emit_constraint_intx(const char* name, CommandLineFlagConstraintFunc_intx func, CommandLineFlagConstraint::ConstraintType type) { 191 CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_intx(name, func, type)); 192 } 193 void emit_constraint_uint(const char* name, CommandLineFlagConstraintFunc_uint func, CommandLineFlagConstraint::ConstraintType type) { 194 CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uint(name, func, type)); 195 } 196 void emit_constraint_uintx(const char* name, CommandLineFlagConstraintFunc_uintx func, CommandLineFlagConstraint::ConstraintType type) { 197 CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uintx(name, func, type)); 198 } 199 void emit_constraint_uint64_t(const char* name, CommandLineFlagConstraintFunc_uint64_t func, CommandLineFlagConstraint::ConstraintType type) { 200 CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uint64_t(name, func, type)); 201 } 202 void emit_constraint_size_t(const char* name, CommandLineFlagConstraintFunc_size_t func, CommandLineFlagConstraint::ConstraintType type) { 203 CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_size_t(name, func, type)); 204 } 205 void emit_constraint_double(const char* name, CommandLineFlagConstraintFunc_double func, CommandLineFlagConstraint::ConstraintType type) { 206 CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_double(name, func, type)); 207 } 208 209 // Generate code to call emit_constraint_xxx function 210 #define EMIT_CONSTRAINT_PRODUCT_FLAG(type, name, value, doc) ); emit_constraint_##type(#name 211 #define EMIT_CONSTRAINT_COMMERCIAL_FLAG(type, name, value, doc) ); emit_constraint_##type(#name 212 #define EMIT_CONSTRAINT_DIAGNOSTIC_FLAG(type, name, value, doc) ); emit_constraint_##type(#name 213 #define EMIT_CONSTRAINT_EXPERIMENTAL_FLAG(type, name, value, doc) ); emit_constraint_##type(#name 214 #define EMIT_CONSTRAINT_MANAGEABLE_FLAG(type, name, value, doc) ); emit_constraint_##type(#name 215 #define EMIT_CONSTRAINT_PRODUCT_RW_FLAG(type, name, value, doc) ); emit_constraint_##type(#name 216 #define EMIT_CONSTRAINT_PD_PRODUCT_FLAG(type, name, doc) ); emit_constraint_##type(#name 217 #define EMIT_CONSTRAINT_DEVELOPER_FLAG(type, name, value, doc) ); emit_constraint_##type(#name 218 #define EMIT_CONSTRAINT_PD_DEVELOPER_FLAG(type, name, doc) ); emit_constraint_##type(#name 219 #define EMIT_CONSTRAINT_NOTPRODUCT_FLAG(type, name, value, doc) ); emit_constraint_##type(#name 220 #define EMIT_CONSTRAINT_LP64_PRODUCT_FLAG(type, name, value, doc) ); emit_constraint_##type(#name 221 222 // Generate func argument to pass into emit_constraint_xxx functions 223 #define EMIT_CONSTRAINT_CHECK(func, type) , func, CommandLineFlagConstraint::type 224 225 // the "name" argument must be a string literal 226 #define INITIAL_CONSTRAINTS_SIZE 69 227 GrowableArray<CommandLineFlagConstraint*>* CommandLineFlagConstraintList::_constraints = NULL; 228 CommandLineFlagConstraint::ConstraintType CommandLineFlagConstraintList::_validating_type = CommandLineFlagConstraint::AtParse; 229 230 // Check the ranges of all flags that have them or print them out and exit if requested 231 void CommandLineFlagConstraintList::init(void) { 232 _constraints = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<CommandLineFlagConstraint*>(INITIAL_CONSTRAINTS_SIZE, true); 233 234 emit_constraint_no(NULL RUNTIME_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG, 235 EMIT_CONSTRAINT_PD_DEVELOPER_FLAG, 236 EMIT_CONSTRAINT_PRODUCT_FLAG, 237 EMIT_CONSTRAINT_PD_PRODUCT_FLAG, 238 EMIT_CONSTRAINT_DIAGNOSTIC_FLAG, 239 EMIT_CONSTRAINT_EXPERIMENTAL_FLAG, 240 EMIT_CONSTRAINT_NOTPRODUCT_FLAG, 241 EMIT_CONSTRAINT_MANAGEABLE_FLAG, 242 EMIT_CONSTRAINT_PRODUCT_RW_FLAG, 243 EMIT_CONSTRAINT_LP64_PRODUCT_FLAG, 244 IGNORE_RANGE, 245 EMIT_CONSTRAINT_CHECK)); 246 247 EMIT_CONSTRAINTS_FOR_GLOBALS_EXT 248 249 emit_constraint_no(NULL ARCH_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG, 250 EMIT_CONSTRAINT_PRODUCT_FLAG, 251 EMIT_CONSTRAINT_DIAGNOSTIC_FLAG, 252 EMIT_CONSTRAINT_EXPERIMENTAL_FLAG, 253 EMIT_CONSTRAINT_NOTPRODUCT_FLAG, 254 IGNORE_RANGE, 255 EMIT_CONSTRAINT_CHECK)); 256 257 #if INCLUDE_JVMCI 258 emit_constraint_no(NULL JVMCI_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG, 259 EMIT_CONSTRAINT_PD_DEVELOPER_FLAG, 260 EMIT_CONSTRAINT_PRODUCT_FLAG, 261 EMIT_CONSTRAINT_PD_PRODUCT_FLAG, 262 EMIT_CONSTRAINT_DIAGNOSTIC_FLAG, 263 EMIT_CONSTRAINT_EXPERIMENTAL_FLAG, 264 EMIT_CONSTRAINT_NOTPRODUCT_FLAG, 265 IGNORE_RANGE, 266 EMIT_CONSTRAINT_CHECK)); 267 #endif // INCLUDE_JVMCI 268 269 #ifdef COMPILER1 270 emit_constraint_no(NULL C1_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG, 271 EMIT_CONSTRAINT_PD_DEVELOPER_FLAG, 272 EMIT_CONSTRAINT_PRODUCT_FLAG, 273 EMIT_CONSTRAINT_PD_PRODUCT_FLAG, 274 EMIT_CONSTRAINT_DIAGNOSTIC_FLAG, 275 EMIT_CONSTRAINT_NOTPRODUCT_FLAG, 276 IGNORE_RANGE, 277 EMIT_CONSTRAINT_CHECK)); 278 #endif // COMPILER1 279 280 #ifdef COMPILER2 281 emit_constraint_no(NULL C2_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG, 282 EMIT_CONSTRAINT_PD_DEVELOPER_FLAG, 283 EMIT_CONSTRAINT_PRODUCT_FLAG, 284 EMIT_CONSTRAINT_PD_PRODUCT_FLAG, 285 EMIT_CONSTRAINT_DIAGNOSTIC_FLAG, 286 EMIT_CONSTRAINT_EXPERIMENTAL_FLAG, 287 EMIT_CONSTRAINT_NOTPRODUCT_FLAG, 288 IGNORE_RANGE, 289 EMIT_CONSTRAINT_CHECK)); 290 #endif // COMPILER2 291 292 #if INCLUDE_ALL_GCS 293 emit_constraint_no(NULL G1_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG, 294 EMIT_CONSTRAINT_PD_DEVELOPER_FLAG, 295 EMIT_CONSTRAINT_PRODUCT_FLAG, 296 EMIT_CONSTRAINT_PD_PRODUCT_FLAG, 297 EMIT_CONSTRAINT_DIAGNOSTIC_FLAG, 298 EMIT_CONSTRAINT_EXPERIMENTAL_FLAG, 299 EMIT_CONSTRAINT_NOTPRODUCT_FLAG, 300 EMIT_CONSTRAINT_MANAGEABLE_FLAG, 301 EMIT_CONSTRAINT_PRODUCT_RW_FLAG, 302 IGNORE_RANGE, 303 EMIT_CONSTRAINT_CHECK)); 304 #endif // INCLUDE_ALL_GCS 305 } 306 307 // Find constraints by name and return only if found constraint's type is equal or lower than current validating type. 308 CommandLineFlagConstraint* CommandLineFlagConstraintList::find_if_needs_check(const char* name) { 309 CommandLineFlagConstraint* found = NULL; 310 for (int i=0; i<length(); i++) { 311 CommandLineFlagConstraint* constraint = at(i); 312 if ((strcmp(constraint->name(), name) == 0) && 313 (constraint->type() <= _validating_type)) { 314 found = constraint; 315 break; 316 } 317 } 318 return found; 319 } 320 321 // Check constraints for specific constraint type. 322 bool CommandLineFlagConstraintList::check_constraints(CommandLineFlagConstraint::ConstraintType type) { 323 guarantee(type > _validating_type, "Constraint check is out of order."); 324 _validating_type = type; 325 326 bool status = true; 327 for (int i=0; i<length(); i++) { 328 CommandLineFlagConstraint* constraint = at(i); 329 if (type != constraint->type()) continue; 330 const char* name = constraint->name(); 331 Flag* flag = Flag::find_flag(name, strlen(name), true, true); 332 // We must check for NULL here as lp64_product flags on 32 bit architecture 333 // can generate constraint check (despite that they are declared as constants), 334 // but they will not be returned by Flag::find_flag() 335 if (flag != NULL) { 336 if (flag->is_bool()) { 337 bool value = flag->get_bool(); 338 if (constraint->apply_bool(value, true) != Flag::SUCCESS) status = false; 339 } else if (flag->is_int()) { 340 int value = flag->get_int(); 341 if (constraint->apply_int(value, true) != Flag::SUCCESS) status = false; 342 } else if (flag->is_uint()) { 343 uint value = flag->get_uint(); 344 if (constraint->apply_uint(value, true) != Flag::SUCCESS) status = false; 345 } else if (flag->is_intx()) { 346 intx value = flag->get_intx(); 347 if (constraint->apply_intx(value, true) != Flag::SUCCESS) status = false; 348 } else if (flag->is_uintx()) { 349 uintx value = flag->get_uintx(); 350 if (constraint->apply_uintx(value, true) != Flag::SUCCESS) status = false; 351 } else if (flag->is_uint64_t()) { 352 uint64_t value = flag->get_uint64_t(); 353 if (constraint->apply_uint64_t(value, true) != Flag::SUCCESS) status = false; 354 } else if (flag->is_size_t()) { 355 size_t value = flag->get_size_t(); 356 if (constraint->apply_size_t(value, true) != Flag::SUCCESS) status = false; 357 } else if (flag->is_double()) { 358 double value = flag->get_double(); 359 if (constraint->apply_double(value, true) != Flag::SUCCESS) status = false; 360 } 361 } 362 } 363 return status; 364 }