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