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 37 class CommandLineFlagConstraint_bool : public CommandLineFlagConstraint { 38 CommandLineFlagConstraintFunc_bool _constraint; 39 40 public: 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(verbose, value); 50 } 51 }; 52 53 class CommandLineFlagConstraint_int : public CommandLineFlagConstraint { 54 CommandLineFlagConstraintFunc_int _constraint; 55 56 public: 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(verbose, value); 66 } 67 }; 68 69 class CommandLineFlagConstraint_intx : public CommandLineFlagConstraint { 70 CommandLineFlagConstraintFunc_intx _constraint; 71 72 public: 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(verbose, value); 82 } 83 }; 84 85 class CommandLineFlagConstraint_uint : public CommandLineFlagConstraint { 86 CommandLineFlagConstraintFunc_uint _constraint; 87 88 public: 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(verbose, value); 98 } 99 }; 100 101 class CommandLineFlagConstraint_uintx : public CommandLineFlagConstraint { 102 CommandLineFlagConstraintFunc_uintx _constraint; 103 104 public: 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(verbose, value); 114 } 115 }; 116 117 class CommandLineFlagConstraint_uint64_t : public CommandLineFlagConstraint { 118 CommandLineFlagConstraintFunc_uint64_t _constraint; 119 120 public: 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(verbose, value); 130 } 131 }; 132 133 class CommandLineFlagConstraint_size_t : public CommandLineFlagConstraint { 134 CommandLineFlagConstraintFunc_size_t _constraint; 135 136 public: 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(verbose, value); 146 } 147 }; 148 149 class CommandLineFlagConstraint_double : public CommandLineFlagConstraint { 150 CommandLineFlagConstraintFunc_double _constraint; 151 152 public: 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(verbose, value); 162 } 163 }; 164 165 // No constraint emitting 166 void emit_constraint_no(...) { /* NOP */ } 167 168 // No constraint emitting if function argument is NOT provided 169 void emit_constraint_bool(const char* /*name*/) { /* NOP */ } 170 void emit_constraint_ccstr(const char* /*name*/) { /* NOP */ } 171 void emit_constraint_ccstrlist(const char* /*name*/) { /* NOP */ } 172 void emit_constraint_int(const char* /*name*/) { /* NOP */ } 173 void emit_constraint_intx(const char* /*name*/) { /* NOP */ } 174 void emit_constraint_uint(const char* /*name*/) { /* NOP */ } 175 void emit_constraint_uintx(const char* /*name*/) { /* NOP */ } 176 void emit_constraint_uint64_t(const char* /*name*/) { /* NOP */ } 177 void emit_constraint_size_t(const char* /*name*/) { /* NOP */ } 178 void emit_constraint_double(const char* /*name*/) { /* NOP */ } 179 180 // CommandLineFlagConstraint emitting code functions if function argument is provided 181 void emit_constraint_bool(const char* name, CommandLineFlagConstraintFunc_bool func, CommandLineFlagConstraint::ConstraintType type) { 182 CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_bool(name, func, type)); 183 } 184 void emit_constraint_int(const char* name, CommandLineFlagConstraintFunc_int func, CommandLineFlagConstraint::ConstraintType type) { 185 CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_int(name, func, type)); 186 } 187 void emit_constraint_intx(const char* name, CommandLineFlagConstraintFunc_intx func, CommandLineFlagConstraint::ConstraintType type) { 188 CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_intx(name, func, type)); 189 } 190 void emit_constraint_uint(const char* name, CommandLineFlagConstraintFunc_uint func, CommandLineFlagConstraint::ConstraintType type) { 191 CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uint(name, func, type)); 192 } 193 void emit_constraint_uintx(const char* name, CommandLineFlagConstraintFunc_uintx func, CommandLineFlagConstraint::ConstraintType type) { 194 CommandLineFlagConstraintList::add(new CommandLineFlagConstraint_uintx(name, func, type)); 195 } 196 void 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 } 199 void 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 } 202 void 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 16 224 GrowableArray<CommandLineFlagConstraint*>* CommandLineFlagConstraintList::_constraints = NULL; 225 CommandLineFlagConstraint::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 228 void CommandLineFlagConstraintList::init(void) { 229 230 _constraints = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<CommandLineFlagConstraint*>(INITIAL_CONSTRAINTS_SIZE, true); 231 232 emit_constraint_no(NULL RUNTIME_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG, 233 EMIT_CONSTRAINT_PD_DEVELOPER_FLAG, 234 EMIT_CONSTRAINT_PRODUCT_FLAG, 235 EMIT_CONSTRAINT_PD_PRODUCT_FLAG, 236 EMIT_CONSTRAINT_DIAGNOSTIC_FLAG, 237 EMIT_CONSTRAINT_EXPERIMENTAL_FLAG, 238 EMIT_CONSTRAINT_NOTPRODUCT_FLAG, 239 EMIT_CONSTRAINT_MANAGEABLE_FLAG, 240 EMIT_CONSTRAINT_PRODUCT_RW_FLAG, 241 EMIT_CONSTRAINT_LP64_PRODUCT_FLAG, 242 IGNORE_RANGE, 243 EMIT_CONSTRAINT_CHECK)); 244 245 EMIT_CONSTRAINTS_FOR_GLOBALS_EXT 246 247 emit_constraint_no(NULL ARCH_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG, 248 EMIT_CONSTRAINT_PRODUCT_FLAG, 249 EMIT_CONSTRAINT_DIAGNOSTIC_FLAG, 250 EMIT_CONSTRAINT_EXPERIMENTAL_FLAG, 251 EMIT_CONSTRAINT_NOTPRODUCT_FLAG, 252 IGNORE_RANGE, 253 EMIT_CONSTRAINT_CHECK)); 254 255 #ifdef COMPILER1 256 emit_constraint_no(NULL C1_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG, 257 EMIT_CONSTRAINT_PD_DEVELOPER_FLAG, 258 EMIT_CONSTRAINT_PRODUCT_FLAG, 259 EMIT_CONSTRAINT_PD_PRODUCT_FLAG, 260 EMIT_CONSTRAINT_DIAGNOSTIC_FLAG, 261 EMIT_CONSTRAINT_NOTPRODUCT_FLAG, 262 IGNORE_RANGE, 263 EMIT_CONSTRAINT_CHECK)); 264 #endif // COMPILER1 265 266 #ifdef COMPILER2 267 emit_constraint_no(NULL C2_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG, 268 EMIT_CONSTRAINT_PD_DEVELOPER_FLAG, 269 EMIT_CONSTRAINT_PRODUCT_FLAG, 270 EMIT_CONSTRAINT_PD_PRODUCT_FLAG, 271 EMIT_CONSTRAINT_DIAGNOSTIC_FLAG, 272 EMIT_CONSTRAINT_EXPERIMENTAL_FLAG, 273 EMIT_CONSTRAINT_NOTPRODUCT_FLAG, 274 IGNORE_RANGE, 275 EMIT_CONSTRAINT_CHECK)); 276 #endif // COMPILER2 277 278 #ifndef INCLUDE_ALL_GCS 279 emit_constraint_no(NULL G1_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG, 280 EMIT_CONSTRAINT_PD_DEVELOPER_FLAG, 281 EMIT_CONSTRAINT_PRODUCT_FLAG, 282 EMIT_CONSTRAINT_PD_PRODUCT_FLAG, 283 EMIT_CONSTRAINT_DIAGNOSTIC_FLAG, 284 EMIT_CONSTRAINT_EXPERIMENTAL_FLAG, 285 EMIT_CONSTRAINT_NOTPRODUCT_FLAG, 286 EMIT_CONSTRAINT_MANAGEABLE_FLAG, 287 EMIT_CONSTRAINT_PRODUCT_RW_FLAG, 288 IGNORE_RANGE, 289 EMIT_CONSTRAINT_CHECK)); 290 #endif // INCLUDE_ALL_GCS 291 } 292 293 // Find constraints by name and return only if found constraint's type is equal or lower than current validating type. 294 CommandLineFlagConstraint* CommandLineFlagConstraintList::find_if_needs_check(const char* name) { 295 CommandLineFlagConstraint* found = NULL; 296 for (int i=0; i<length(); i++) { 297 CommandLineFlagConstraint* constraint = at(i); 298 if ((strcmp(constraint->name(), name) == 0) && 299 (constraint->type() <= _validating_type)) { 300 found = constraint; 301 break; 302 } 303 } 304 return found; 305 } 306 307 // Check constraints for specific constraint type. 308 bool CommandLineFlagConstraintList::check_constraints(CommandLineFlagConstraint::ConstraintType type) { 309 //#define PRINT_CONSTRAINTS_SIZES 310 #ifdef PRINT_CONSTRAINTS_SIZES 311 { 312 size_t size_constraints = sizeof(CommandLineFlagConstraintList); 313 for (int i=0; i<length(); i++) { 314 size_constraints += sizeof(CommandLineFlagConstraint); 315 CommandLineFlagConstraint* constraint = at(i); 316 const char* name = constraint->name(); 317 Flag* flag = Flag::find_flag(name, strlen(name), true, true); 318 if (flag->is_bool()) { 319 size_constraints += sizeof(CommandLineFlagConstraintFunc_bool); 320 size_constraints += sizeof(CommandLineFlagConstraint*); 321 } else if (flag->is_intx()) { 322 size_constraints += sizeof(CommandLineFlagConstraintFunc_intx); 323 size_constraints += sizeof(CommandLineFlagConstraint*); 324 } else if (flag->is_uintx()) { 325 size_constraints += sizeof(CommandLineFlagConstraintFunc_uintx); 326 size_constraints += sizeof(CommandLineFlagConstraint*); 327 } else if (flag->is_uint64_t()) { 328 size_constraints += sizeof(CommandLineFlagConstraintFunc_uint64_t); 329 size_constraints += sizeof(CommandLineFlagConstraint*); 330 } else if (flag->is_size_t()) { 331 size_constraints += sizeof(CommandLineFlagConstraintFunc_size_t); 332 size_constraints += sizeof(CommandLineFlagConstraint*); 333 } else if (flag->is_double()) { 334 size_constraints += sizeof(CommandLineFlagConstraintFunc_double); 335 size_constraints += sizeof(CommandLineFlagConstraint*); 336 } 337 } 338 fprintf(stderr, "Size of %d constraints: " SIZE_FORMAT " bytes\n", 339 length(), size_constraints); 340 } 341 #endif // PRINT_CONSTRAINTS_SIZES 342 343 // First check will be for 'AfterErgo' and initial value of '_validating_type' is 'AtParse'. 344 guarantee(type > _validating_type, "Constraint check is out of order."); 345 _validating_type = type; 346 347 bool status = true; 348 for (int i=0; i<length(); i++) { 349 CommandLineFlagConstraint* constraint = at(i); 350 if (type != constraint->type()) continue; 351 const char*name = constraint->name(); 352 Flag* flag = Flag::find_flag(name, strlen(name), true, true); 353 if (flag != NULL) { 354 if (flag->is_bool()) { 355 bool value = flag->get_bool(); 356 if (constraint->apply_bool(&value, true) != Flag::SUCCESS) status = false; 357 } else if (flag->is_intx()) { 358 intx value = flag->get_intx(); 359 if (constraint->apply_intx(&value, true) != Flag::SUCCESS) status = false; 360 } else if (flag->is_uintx()) { 361 uintx value = flag->get_uintx(); 362 if (constraint->apply_uintx(&value, true) != Flag::SUCCESS) status = false; 363 } else if (flag->is_uint64_t()) { 364 uint64_t value = flag->get_uint64_t(); 365 if (constraint->apply_uint64_t(&value, true) != Flag::SUCCESS) status = false; 366 } else if (flag->is_size_t()) { 367 size_t value = flag->get_size_t(); 368 if (constraint->apply_size_t(&value, true) != Flag::SUCCESS) status = false; 369 } else if (flag->is_double()) { 370 double value = flag->get_double(); 371 if (constraint->apply_double(&value, true) != Flag::SUCCESS) status = false; 372 } 373 } 374 } 375 return status; 376 }