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 "memory/referenceProcessor.hpp"
  29 #include "runtime/arguments.hpp"
  30 #include "runtime/commandLineFlagRangeList.hpp"
  31 #include "runtime/os_ext.hpp"
  32 #include "utilities/defaultStream.hpp"
  33 #include "utilities/macros.hpp"
  34 
  35 class CommandLineFlagRange_intx : public CommandLineFlagRange {
  36   intx _min;
  37   intx _max;
  38 
  39 public:
  40   CommandLineFlagRange_intx(const char* name, intx min, intx max) : CommandLineFlagRange(name) {
  41     _min=min, _max=max;
  42   }
  43 
  44   Flag::Error check_intx(intx value, bool verbose = true) {
  45     if ((value < _min) || (value > _max)) {
  46       if (verbose == true) {
  47         jio_fprintf(defaultStream::error_stream(),
  48                     "intx %s=%ld is outside the allowed range [ "INTX_FORMAT" ... "INTX_FORMAT" ]\n",
  49                     _name, value, _min, _max);
  50       }
  51       return Flag::OUT_OF_BOUNDS;
  52     } else {
  53       return Flag::SUCCESS;
  54     }
  55   }
  56 
  57   void print(outputStream* st) {
  58     st->print("[ "INTX_FORMAT_W(-25)" ... "INTX_FORMAT_W(25)" ]", _min, _max);
  59   }
  60 };
  61 
  62 class CommandLineFlagRange_uintx : public CommandLineFlagRange {
  63   uintx _min;
  64   uintx _max;
  65 
  66 public:
  67   CommandLineFlagRange_uintx(const char* name, uintx min, uintx max) : CommandLineFlagRange(name) {
  68     _min=min, _max=max;
  69   }
  70 
  71   Flag::Error check_uintx(uintx value, bool verbose = true) {
  72     if ((value < _min) || (value > _max)) {
  73       if (verbose == true) {
  74         jio_fprintf(defaultStream::error_stream(),
  75                     "uintx %s=%lu is outside the allowed range [ "UINTX_FORMAT" ... "UINTX_FORMAT" ]\n",
  76                     _name, value, _min, _max);
  77       }
  78       return Flag::OUT_OF_BOUNDS;
  79     } else {
  80       return Flag::SUCCESS;
  81     }
  82   }
  83 
  84   void print(outputStream* st) {
  85     st->print("[ "UINTX_FORMAT_W(-25)" ... "UINTX_FORMAT_W(25)" ]", _min, _max);
  86   }
  87 };
  88 
  89 class CommandLineFlagRange_uint64_t : public CommandLineFlagRange {
  90   uint64_t _min;
  91   uint64_t _max;
  92 
  93 public:
  94   CommandLineFlagRange_uint64_t(const char* name, uint64_t min, uint64_t max) : CommandLineFlagRange(name) {
  95     _min=min, _max=max;
  96   }
  97 
  98   Flag::Error check_uint64_t(uint64_t value, bool verbose = true) {
  99     if ((value < _min) || (value > _max)) {
 100       if (verbose == true) {
 101         jio_fprintf(defaultStream::error_stream(),
 102                     "uint64_t %s=%lu is outside the allowed range [ "UINT64_FORMAT" ... "UINT64_FORMAT" ]\n",
 103                     _name, value, _min, _max);
 104       }
 105       return Flag::OUT_OF_BOUNDS;
 106     } else {
 107       return Flag::SUCCESS;
 108     }
 109   }
 110 
 111   void print(outputStream* st) {
 112     st->print("[ "UINT64_FORMAT_W(-25)" ... "UINT64_FORMAT_W(25)" ]", _min, _max);
 113   }
 114 };
 115 
 116 class CommandLineFlagRange_size_t : public CommandLineFlagRange {
 117   size_t _min;
 118   size_t _max;
 119 
 120 public:
 121   CommandLineFlagRange_size_t(const char* name, size_t min, size_t max) : CommandLineFlagRange(name) {
 122     _min=min, _max=max;
 123   }
 124 
 125   Flag::Error check_size_t(size_t value, bool verbose = true) {
 126     if ((value < _min) || (value > _max)) {
 127       if (verbose == true) {
 128         jio_fprintf(defaultStream::error_stream(),
 129                     "size_t %s="SIZE_FORMAT" is outside the allowed range [ "SIZE_FORMAT" ... "SIZE_FORMAT" ]\n",
 130                     _name, value, _min, _max);
 131       }
 132       return Flag::OUT_OF_BOUNDS;
 133     } else {
 134       return Flag::SUCCESS;
 135     }
 136   }
 137 
 138   void print(outputStream* st) {
 139     st->print("[ "SIZE_FORMAT_W(-25)" ... "SIZE_FORMAT_W(25)" ]", _min, _max);
 140   }
 141 };
 142 
 143 class CommandLineFlagRange_double : public CommandLineFlagRange {
 144   double _min;
 145   double _max;
 146 
 147 public:
 148   CommandLineFlagRange_double(const char* name, double min, double max) : CommandLineFlagRange(name) {
 149     _min=min, _max=max;
 150   }
 151 
 152   Flag::Error check_double(double value, bool verbose = true) {
 153     if ((value < _min) || (value > _max)) {
 154       if (verbose == true) {
 155         jio_fprintf(defaultStream::error_stream(),
 156                     "double %s=%f is outside the allowed range [ %f ... %f ]\n",
 157                     _name, value, _min, _max);
 158       }
 159       return Flag::OUT_OF_BOUNDS;
 160     } else {
 161       return Flag::SUCCESS;
 162     }
 163   }
 164 
 165   void print(outputStream* st) {
 166     st->print("[ %-25.3f ... %25.3f ]", _min, _max);
 167   }
 168 };
 169 
 170 // No constraint emitting
 171 void emit_range_no(...)                           { /* NOP */ }
 172 
 173 // No constraint emitting if function argument is NOT provided
 174 void emit_range_bool(const char* name)            { (void)name; /* NOP */ }
 175 void emit_range_ccstr(const char* name)           { (void)name; /* NOP */ }
 176 void emit_range_ccstrlist(const char* name)       { (void)name; /* NOP */ }
 177 void emit_range_intx(const char* name)            { (void)name; /* NOP */ }
 178 void emit_range_uintx(const char* name)           { (void)name; /* NOP */ }
 179 void emit_range_uint64_t(const char* name)        { (void)name; /* NOP */ }
 180 void emit_range_size_t(const char* name)          { (void)name; /* NOP */ }
 181 void emit_range_double(const char* name)          { (void)name; /* NOP */ }
 182 
 183 // CommandLineFlagRange emitting code functions if function argument is provided
 184 void emit_range_intx(const char* name, intx min, intx max) {
 185   CommandLineFlagRangeList::add(new CommandLineFlagRange_intx(name, min, max));
 186 }
 187 void emit_range_uintx(const char* name, uintx min, uintx max) {
 188   CommandLineFlagRangeList::add(new CommandLineFlagRange_uintx(name, min, max));
 189 }
 190 void emit_range_uint64_t(const char* name, uint64_t min, uint64_t max) {
 191   CommandLineFlagRangeList::add(new CommandLineFlagRange_uint64_t(name, min, max));
 192 }
 193 void emit_range_size_t(const char* name, size_t min, size_t max) {
 194   CommandLineFlagRangeList::add(new CommandLineFlagRange_size_t(name, min, max));
 195 }
 196 void emit_range_double(const char* name, double min, double max) {
 197   CommandLineFlagRangeList::add(new CommandLineFlagRange_double(name, min, max));
 198 }
 199 
 200 // Generate code to call emit_range_xxx function
 201 #define EMIT_RANGE_PRODUCT_FLAG(type, name, value, doc)      ); emit_range_##type(#name
 202 #define EMIT_RANGE_COMMERCIAL_FLAG(type, name, value, doc)   ); emit_range_##type(#name
 203 #define EMIT_RANGE_DIAGNOSTIC_FLAG(type, name, value, doc)   ); emit_range_##type(#name
 204 #define EMIT_RANGE_EXPERIMENTAL_FLAG(type, name, value, doc) ); emit_range_##type(#name
 205 #define EMIT_RANGE_MANAGEABLE_FLAG(type, name, value, doc)   ); emit_range_##type(#name
 206 #define EMIT_RANGE_PRODUCT_RW_FLAG(type, name, value, doc)   ); emit_range_##type(#name
 207 #define EMIT_RANGE_PD_PRODUCT_FLAG(type, name, doc)          ); emit_range_##type(#name
 208 #define EMIT_RANGE_DEVELOPER_FLAG(type, name, value, doc)    ); emit_range_##type(#name
 209 #define EMIT_RANGE_PD_DEVELOPER_FLAG(type, name, doc)        ); emit_range_##type(#name
 210 #define EMIT_RANGE_NOTPRODUCT_FLAG(type, name, value, doc)   ); emit_range_##type(#name
 211 #define EMIT_RANGE_LP64_PRODUCT_FLAG(type, name, value, doc) ); emit_range_##type(#name
 212 
 213 // Generate func argument to pass into emit_range_xxx functions
 214 #define EMIT_RANGE_CHECK(a, b)                               , a, b
 215 
 216 #define INITIAL_RANGES_SIZE 128
 217 GrowableArray<CommandLineFlagRange*>* CommandLineFlagRangeList::_ranges = NULL;
 218 
 219 // Check the ranges of all flags that have them
 220 void CommandLineFlagRangeList::init(void) {
 221 
 222   _ranges = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<CommandLineFlagRange*>(INITIAL_RANGES_SIZE, true);
 223 
 224   emit_range_no(NULL RUNTIME_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
 225                                    EMIT_RANGE_PD_DEVELOPER_FLAG,
 226                                    EMIT_RANGE_PRODUCT_FLAG,
 227                                    EMIT_RANGE_PD_PRODUCT_FLAG,
 228                                    EMIT_RANGE_DIAGNOSTIC_FLAG,
 229                                    EMIT_RANGE_EXPERIMENTAL_FLAG,
 230                                    EMIT_RANGE_NOTPRODUCT_FLAG,
 231                                    EMIT_RANGE_MANAGEABLE_FLAG,
 232                                    EMIT_RANGE_PRODUCT_RW_FLAG,
 233                                    EMIT_RANGE_LP64_PRODUCT_FLAG,
 234                                    EMIT_RANGE_CHECK,
 235                                    IGNORE_CONSTRAINT) );
 236   
 237   EMIT_RANGES_FOR_GLOBALS_EXT
 238 
 239   emit_range_no(NULL ARCH_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
 240                                      EMIT_RANGE_PRODUCT_FLAG,
 241                                      EMIT_RANGE_DIAGNOSTIC_FLAG,
 242                                      EMIT_RANGE_EXPERIMENTAL_FLAG,
 243                                      EMIT_RANGE_NOTPRODUCT_FLAG,
 244                                      EMIT_RANGE_CHECK,
 245                                      IGNORE_CONSTRAINT));
 246 
 247 #ifdef COMPILER1
 248   emit_range_no(NULL C1_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
 249                                    EMIT_RANGE_PD_DEVELOPER_FLAG,
 250                                    EMIT_RANGE_PRODUCT_FLAG,
 251                                    EMIT_RANGE_PD_PRODUCT_FLAG,
 252                                    EMIT_RANGE_DIAGNOSTIC_FLAG,
 253                                    EMIT_RANGE_NOTPRODUCT_FLAG,
 254                                    EMIT_RANGE_CHECK,
 255                                    IGNORE_CONSTRAINT));
 256 #endif // COMPILER1
 257 
 258 #ifdef COMPILER2
 259   emit_range_no(NULL C2_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
 260                                    EMIT_RANGE_PD_DEVELOPER_FLAG,
 261                                    EMIT_RANGE_PRODUCT_FLAG,
 262                                    EMIT_RANGE_PD_PRODUCT_FLAG,
 263                                    EMIT_RANGE_DIAGNOSTIC_FLAG,
 264                                    EMIT_RANGE_EXPERIMENTAL_FLAG,
 265                                    EMIT_RANGE_NOTPRODUCT_FLAG,
 266                                    EMIT_RANGE_CHECK,
 267                                    IGNORE_CONSTRAINT));
 268 #endif // COMPILER2
 269 
 270 #if INCLUDE_ALL_GCS
 271   emit_range_no(NULL G1_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
 272                                    EMIT_RANGE_PD_DEVELOPER_FLAG,
 273                                    EMIT_RANGE_PRODUCT_FLAG,
 274                                    EMIT_RANGE_PD_PRODUCT_FLAG,
 275                                    EMIT_RANGE_DIAGNOSTIC_FLAG,
 276                                    EMIT_RANGE_EXPERIMENTAL_FLAG,
 277                                    EMIT_RANGE_NOTPRODUCT_FLAG,
 278                                    EMIT_RANGE_MANAGEABLE_FLAG,
 279                                    EMIT_RANGE_PRODUCT_RW_FLAG,
 280                                    EMIT_RANGE_CHECK,
 281                                    IGNORE_CONSTRAINT));
 282 #endif // INCLUDE_ALL_GCS
 283 }
 284 
 285 CommandLineFlagRange* CommandLineFlagRangeList::find(const char* name) {
 286   CommandLineFlagRange* found = NULL;
 287   for (int i=0; i<length(); i++) {
 288     CommandLineFlagRange* range = at(i);
 289     if (strcmp(range->_name, name) == 0) {
 290       found = range;
 291       break;
 292     }
 293   }
 294   return found;
 295 }
 296 
 297 void CommandLineFlagRangeList::print(const char* name, outputStream* st, bool unspecified) {
 298   CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
 299   if (range != NULL) {
 300     range->print(st);
 301   } else if (unspecified == true) {
 302     st->print("[                           ...                           ]");
 303   }
 304 }