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/commandLineFlagRangeList.hpp" 31 #include "runtime/os.hpp" 32 #include "runtime/task.hpp" 33 #include "utilities/defaultStream.hpp" 34 #include "utilities/macros.hpp" 35 36 void CommandLineError::print(bool verbose, const char* msg, ...) { 37 if (verbose) { 38 va_list listPointer; 39 va_start(listPointer, msg); 40 jio_vfprintf(defaultStream::error_stream(), msg, listPointer); 41 va_end(listPointer); 42 } 43 } 44 45 class CommandLineFlagRange_int : public CommandLineFlagRange { 46 int _min; 47 int _max; 48 49 public: 50 // the "name" argument must be a string literal 51 CommandLineFlagRange_int(const char* name, int min, int max) : CommandLineFlagRange(name) { 52 _min=min, _max=max; 53 } 54 55 Flag::Error check_int(int value, bool verbose = true) { 56 if ((value < _min) || (value > _max)) { 57 CommandLineError::print(verbose, 58 "int %s=%d is outside the allowed range " 59 "[ %d ... %d ]\n", 60 name(), value, _min, _max); 61 return Flag::OUT_OF_BOUNDS; 62 } else { 63 return Flag::SUCCESS; 64 } 65 } 66 67 void print(outputStream* st) { 68 st->print("[ %-25d ... %25d ]", _min, _max); 69 } 70 }; 71 72 class CommandLineFlagRange_intx : public CommandLineFlagRange { 73 intx _min; 74 intx _max; 75 76 public: 77 // the "name" argument must be a string literal 78 CommandLineFlagRange_intx(const char* name, intx min, intx max) : CommandLineFlagRange(name) { 79 _min=min, _max=max; 80 } 81 82 Flag::Error check_intx(intx value, bool verbose = true) { 83 if ((value < _min) || (value > _max)) { 84 CommandLineError::print(verbose, 85 "intx %s=" INTX_FORMAT " is outside the allowed range " 86 "[ " INTX_FORMAT " ... " INTX_FORMAT " ]\n", 87 name(), value, _min, _max); 88 return Flag::OUT_OF_BOUNDS; 89 } else { 90 return Flag::SUCCESS; 91 } 92 } 93 94 void print(outputStream* st) { 95 st->print("[ " INTX_FORMAT_W(-25) " ... " INTX_FORMAT_W(25) " ]", _min, _max); 96 } 97 }; 98 99 class CommandLineFlagRange_uint : public CommandLineFlagRange { 100 uint _min; 101 uint _max; 102 103 public: 104 // the "name" argument must be a string literal 105 CommandLineFlagRange_uint(const char* name, uint min, uint max) : CommandLineFlagRange(name) { 106 _min=min, _max=max; 107 } 108 109 Flag::Error check_uint(uint value, bool verbose = true) { 110 if ((value < _min) || (value > _max)) { 111 CommandLineError::print(verbose, 112 "uint %s=%u is outside the allowed range " 113 "[ %u ... %u ]\n", 114 name(), value, _min, _max); 115 return Flag::OUT_OF_BOUNDS; 116 } else { 117 return Flag::SUCCESS; 118 } 119 } 120 121 void print(outputStream* st) { 122 st->print("[ %-25u ... %25u ]", _min, _max); 123 } 124 }; 125 126 class CommandLineFlagRange_uintx : public CommandLineFlagRange { 127 uintx _min; 128 uintx _max; 129 130 public: 131 // the "name" argument must be a string literal 132 CommandLineFlagRange_uintx(const char* name, uintx min, uintx max) : CommandLineFlagRange(name) { 133 _min=min, _max=max; 134 } 135 136 Flag::Error check_uintx(uintx value, bool verbose = true) { 137 if ((value < _min) || (value > _max)) { 138 CommandLineError::print(verbose, 139 "uintx %s=" UINTX_FORMAT " is outside the allowed range " 140 "[ " UINTX_FORMAT " ... " UINTX_FORMAT " ]\n", 141 name(), value, _min, _max); 142 return Flag::OUT_OF_BOUNDS; 143 } else { 144 return Flag::SUCCESS; 145 } 146 } 147 148 void print(outputStream* st) { 149 st->print("[ " UINTX_FORMAT_W(-25) " ... " UINTX_FORMAT_W(25) " ]", _min, _max); 150 } 151 }; 152 153 class CommandLineFlagRange_uint64_t : public CommandLineFlagRange { 154 uint64_t _min; 155 uint64_t _max; 156 157 public: 158 // the "name" argument must be a string literal 159 CommandLineFlagRange_uint64_t(const char* name, uint64_t min, uint64_t max) : CommandLineFlagRange(name) { 160 _min=min, _max=max; 161 } 162 163 Flag::Error check_uint64_t(uint64_t value, bool verbose = true) { 164 if ((value < _min) || (value > _max)) { 165 CommandLineError::print(verbose, 166 "uint64_t %s=" UINT64_FORMAT " is outside the allowed range " 167 "[ " UINT64_FORMAT " ... " UINT64_FORMAT " ]\n", 168 name(), value, _min, _max); 169 return Flag::OUT_OF_BOUNDS; 170 } else { 171 return Flag::SUCCESS; 172 } 173 } 174 175 void print(outputStream* st) { 176 st->print("[ " UINT64_FORMAT_W(-25) " ... " UINT64_FORMAT_W(25) " ]", _min, _max); 177 } 178 }; 179 180 class CommandLineFlagRange_size_t : public CommandLineFlagRange { 181 size_t _min; 182 size_t _max; 183 184 public: 185 // the "name" argument must be a string literal 186 CommandLineFlagRange_size_t(const char* name, size_t min, size_t max) : CommandLineFlagRange(name) { 187 _min=min, _max=max; 188 } 189 190 Flag::Error check_size_t(size_t value, bool verbose = true) { 191 if ((value < _min) || (value > _max)) { 192 CommandLineError::print(verbose, 193 "size_t %s=" SIZE_FORMAT " is outside the allowed range " 194 "[ " SIZE_FORMAT " ... " SIZE_FORMAT " ]\n", 195 name(), value, _min, _max); 196 return Flag::OUT_OF_BOUNDS; 197 } else { 198 return Flag::SUCCESS; 199 } 200 } 201 202 void print(outputStream* st) { 203 st->print("[ " SIZE_FORMAT_W(-25) " ... " SIZE_FORMAT_W(25) " ]", _min, _max); 204 } 205 }; 206 207 class CommandLineFlagRange_double : public CommandLineFlagRange { 208 double _min; 209 double _max; 210 211 public: 212 // the "name" argument must be a string literal 213 CommandLineFlagRange_double(const char* name, double min, double max) : CommandLineFlagRange(name) { 214 _min=min, _max=max; 215 } 216 217 Flag::Error check_double(double value, bool verbose = true) { 218 if ((value < _min) || (value > _max)) { 219 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 235 void emit_range_no(...) { /* NOP */ } 236 237 // No constraint emitting if function argument is NOT provided 238 void emit_range_bool(const char* /*name*/) { /* NOP */ } 239 void emit_range_ccstr(const char* /*name*/) { /* NOP */ } 240 void emit_range_ccstrlist(const char* /*name*/) { /* NOP */ } 241 void emit_range_int(const char* /*name*/) { /* NOP */ } 242 void emit_range_intx(const char* /*name*/) { /* NOP */ } 243 void emit_range_uint(const char* /*name*/) { /* NOP */ } 244 void emit_range_uintx(const char* /*name*/) { /* NOP */ } 245 void emit_range_uint64_t(const char* /*name*/) { /* NOP */ } 246 void emit_range_size_t(const char* /*name*/) { /* NOP */ } 247 void emit_range_double(const char* /*name*/) { /* NOP */ } 248 249 // CommandLineFlagRange emitting code functions if range arguments are provided 250 void emit_range_intx(const char* name, intx min, intx max) { 251 CommandLineFlagRangeList::add(new CommandLineFlagRange_intx(name, min, max)); 252 } 253 void emit_range_uintx(const char* name, uintx min, uintx max) { 254 CommandLineFlagRangeList::add(new CommandLineFlagRange_uintx(name, min, max)); 255 } 256 void emit_range_uint64_t(const char* name, uint64_t min, uint64_t max) { 257 CommandLineFlagRangeList::add(new CommandLineFlagRange_uint64_t(name, min, max)); 258 } 259 void emit_range_size_t(const char* name, size_t min, size_t max) { 260 CommandLineFlagRangeList::add(new CommandLineFlagRange_size_t(name, min, max)); 261 } 262 void emit_range_double(const char* name, double min, double max) { 263 CommandLineFlagRangeList::add(new CommandLineFlagRange_double(name, min, max)); 264 } 265 266 // Generate code to call emit_range_xxx function 267 #define EMIT_RANGE_PRODUCT_FLAG(type, name, value, doc) ); emit_range_##type(#name 268 #define EMIT_RANGE_COMMERCIAL_FLAG(type, name, value, doc) ); emit_range_##type(#name 269 #define EMIT_RANGE_DIAGNOSTIC_FLAG(type, name, value, doc) ); emit_range_##type(#name 270 #define EMIT_RANGE_EXPERIMENTAL_FLAG(type, name, value, doc) ); emit_range_##type(#name 271 #define EMIT_RANGE_MANAGEABLE_FLAG(type, name, value, doc) ); emit_range_##type(#name 272 #define EMIT_RANGE_PRODUCT_RW_FLAG(type, name, value, doc) ); emit_range_##type(#name 273 #define EMIT_RANGE_PD_PRODUCT_FLAG(type, name, doc) ); emit_range_##type(#name 274 #define EMIT_RANGE_DEVELOPER_FLAG(type, name, value, doc) ); emit_range_##type(#name 275 #define EMIT_RANGE_PD_DEVELOPER_FLAG(type, name, doc) ); emit_range_##type(#name 276 #define EMIT_RANGE_NOTPRODUCT_FLAG(type, name, value, doc) ); emit_range_##type(#name 277 #define EMIT_RANGE_LP64_PRODUCT_FLAG(type, name, value, doc) ); emit_range_##type(#name 278 279 // Generate func argument to pass into emit_range_xxx functions 280 #define EMIT_RANGE_CHECK(a, b) , a, b 281 282 #define INITIAL_RANGES_SIZE 319 283 GrowableArray<CommandLineFlagRange*>* CommandLineFlagRangeList::_ranges = NULL; 284 285 // Check the ranges of all flags that have them 286 void CommandLineFlagRangeList::init(void) { 287 288 _ranges = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<CommandLineFlagRange*>(INITIAL_RANGES_SIZE, true); 289 290 emit_range_no(NULL RUNTIME_FLAGS(EMIT_RANGE_DEVELOPER_FLAG, 291 EMIT_RANGE_PD_DEVELOPER_FLAG, 292 EMIT_RANGE_PRODUCT_FLAG, 293 EMIT_RANGE_PD_PRODUCT_FLAG, 294 EMIT_RANGE_DIAGNOSTIC_FLAG, 295 EMIT_RANGE_EXPERIMENTAL_FLAG, 296 EMIT_RANGE_NOTPRODUCT_FLAG, 297 EMIT_RANGE_MANAGEABLE_FLAG, 298 EMIT_RANGE_PRODUCT_RW_FLAG, 299 EMIT_RANGE_LP64_PRODUCT_FLAG, 300 EMIT_RANGE_CHECK, 301 IGNORE_CONSTRAINT) ); 302 303 EMIT_RANGES_FOR_GLOBALS_EXT 304 305 emit_range_no(NULL ARCH_FLAGS(EMIT_RANGE_DEVELOPER_FLAG, 306 EMIT_RANGE_PRODUCT_FLAG, 307 EMIT_RANGE_DIAGNOSTIC_FLAG, 308 EMIT_RANGE_EXPERIMENTAL_FLAG, 309 EMIT_RANGE_NOTPRODUCT_FLAG, 310 EMIT_RANGE_CHECK, 311 IGNORE_CONSTRAINT)); 312 313 #if INCLUDE_JVMCI 314 emit_range_no(NULL JVMCI_FLAGS(EMIT_RANGE_DEVELOPER_FLAG, 315 EMIT_RANGE_PD_DEVELOPER_FLAG, 316 EMIT_RANGE_PRODUCT_FLAG, 317 EMIT_RANGE_PD_PRODUCT_FLAG, 318 EMIT_RANGE_DIAGNOSTIC_FLAG, 319 EMIT_RANGE_EXPERIMENTAL_FLAG, 320 EMIT_RANGE_NOTPRODUCT_FLAG, 321 EMIT_RANGE_CHECK, 322 IGNORE_CONSTRAINT)); 323 #endif // INCLUDE_JVMCI 324 325 #ifdef COMPILER1 326 emit_range_no(NULL C1_FLAGS(EMIT_RANGE_DEVELOPER_FLAG, 327 EMIT_RANGE_PD_DEVELOPER_FLAG, 328 EMIT_RANGE_PRODUCT_FLAG, 329 EMIT_RANGE_PD_PRODUCT_FLAG, 330 EMIT_RANGE_DIAGNOSTIC_FLAG, 331 EMIT_RANGE_NOTPRODUCT_FLAG, 332 EMIT_RANGE_CHECK, 333 IGNORE_CONSTRAINT)); 334 #endif // COMPILER1 335 336 #ifdef COMPILER2 337 emit_range_no(NULL C2_FLAGS(EMIT_RANGE_DEVELOPER_FLAG, 338 EMIT_RANGE_PD_DEVELOPER_FLAG, 339 EMIT_RANGE_PRODUCT_FLAG, 340 EMIT_RANGE_PD_PRODUCT_FLAG, 341 EMIT_RANGE_DIAGNOSTIC_FLAG, 342 EMIT_RANGE_EXPERIMENTAL_FLAG, 343 EMIT_RANGE_NOTPRODUCT_FLAG, 344 EMIT_RANGE_CHECK, 345 IGNORE_CONSTRAINT)); 346 #endif // COMPILER2 347 348 #if INCLUDE_ALL_GCS 349 emit_range_no(NULL G1_FLAGS(EMIT_RANGE_DEVELOPER_FLAG, 350 EMIT_RANGE_PD_DEVELOPER_FLAG, 351 EMIT_RANGE_PRODUCT_FLAG, 352 EMIT_RANGE_PD_PRODUCT_FLAG, 353 EMIT_RANGE_DIAGNOSTIC_FLAG, 354 EMIT_RANGE_EXPERIMENTAL_FLAG, 355 EMIT_RANGE_NOTPRODUCT_FLAG, 356 EMIT_RANGE_MANAGEABLE_FLAG, 357 EMIT_RANGE_PRODUCT_RW_FLAG, 358 EMIT_RANGE_CHECK, 359 IGNORE_CONSTRAINT)); 360 #endif // INCLUDE_ALL_GCS 361 } 362 363 CommandLineFlagRange* CommandLineFlagRangeList::find(const char* name) { 364 CommandLineFlagRange* found = NULL; 365 for (int i=0; i<length(); i++) { 366 CommandLineFlagRange* range = at(i); 367 if (strcmp(range->name(), name) == 0) { 368 found = range; 369 break; 370 } 371 } 372 return found; 373 } 374 375 void CommandLineFlagRangeList::print(const char* name, outputStream* st, bool unspecified) { 376 CommandLineFlagRange* range = CommandLineFlagRangeList::find(name); 377 if (range != NULL) { 378 range->print(st); 379 } else if (unspecified == true) { 380 st->print("[ ... ]"); 381 } 382 } 383 384 bool CommandLineFlagRangeList::check_ranges() { 385 // Check ranges. 386 bool status = true; 387 for (int i=0; i<length(); i++) { 388 CommandLineFlagRange* range = at(i); 389 const char* name = range->name(); 390 Flag* flag = Flag::find_flag(name, strlen(name), true, true); 391 // We must check for NULL here as lp64_product flags on 32 bit architecture 392 // can generate range check (despite that they are declared as constants), 393 // but they will not be returned by Flag::find_flag() 394 if (flag != NULL) { 395 if (flag->is_int()) { 396 int value = flag->get_int(); 397 if (range->check_int(value, true) != Flag::SUCCESS) status = false; 398 } else if (flag->is_uint()) { 399 uint value = flag->get_uint(); 400 if (range->check_uint(value, true) != Flag::SUCCESS) status = false; 401 } else if (flag->is_intx()) { 402 intx value = flag->get_intx(); 403 if (range->check_intx(value, true) != Flag::SUCCESS) status = false; 404 } else if (flag->is_uintx()) { 405 uintx value = flag->get_uintx(); 406 if (range->check_uintx(value, true) != Flag::SUCCESS) status = false; 407 } else if (flag->is_uint64_t()) { 408 uint64_t value = flag->get_uint64_t(); 409 if (range->check_uint64_t(value, true) != Flag::SUCCESS) status = false; 410 } else if (flag->is_size_t()) { 411 size_t value = flag->get_size_t(); 412 if (range->check_size_t(value, true) != Flag::SUCCESS) status = false; 413 } else if (flag->is_double()) { 414 double value = flag->get_double(); 415 if (range->check_double(value, true) != Flag::SUCCESS) status = false; 416 } 417 } 418 } 419 return status; 420 }