1 /*
   2  * Copyright (c) 2015, 2020, 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/jvmFlagConstraintsGC.hpp"
  29 #include "runtime/arguments.hpp"
  30 #include "runtime/flags/jvmFlag.hpp"
  31 #include "runtime/flags/jvmFlagConstraintList.hpp"
  32 #include "runtime/flags/jvmFlagConstraintsCompiler.hpp"
  33 #include "runtime/flags/jvmFlagConstraintsRuntime.hpp"
  34 #include "runtime/globals.hpp"
  35 #include "runtime/globals_extension.hpp"
  36 #include "runtime/os.hpp"
  37 #include "utilities/macros.hpp"
  38 
  39 class JVMFlagConstraint_bool : public JVMFlagConstraint {
  40   JVMFlagConstraintFunc_bool _constraint;
  41 
  42 public:
  43   JVMFlagConstraint_bool(const JVMFlag* flag,
  44                          JVMFlagConstraintFunc_bool func,
  45                          ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
  46 
  47   JVMFlag::Error apply(bool verbose) {
  48     return _constraint(_flag->get_bool(), verbose);
  49   }
  50 
  51   JVMFlag::Error apply_bool(bool value, bool verbose) {
  52     return _constraint(value, verbose);
  53   }
  54 };
  55 
  56 class JVMFlagConstraint_int : public JVMFlagConstraint {
  57   JVMFlagConstraintFunc_int _constraint;
  58 
  59 public:
  60   JVMFlagConstraint_int(const JVMFlag* flag,
  61                         JVMFlagConstraintFunc_int func,
  62                         ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
  63 
  64   JVMFlag::Error apply(bool verbose) {
  65     return _constraint(_flag->get_int(), verbose);
  66   }
  67 
  68   JVMFlag::Error apply_int(int value, bool verbose) {
  69     return _constraint(value, verbose);
  70   }
  71 };
  72 
  73 class JVMFlagConstraint_intx : public JVMFlagConstraint {
  74   JVMFlagConstraintFunc_intx _constraint;
  75 
  76 public:
  77   JVMFlagConstraint_intx(const JVMFlag* flag,
  78                          JVMFlagConstraintFunc_intx func,
  79                          ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
  80 
  81   JVMFlag::Error apply(bool verbose) {
  82     return _constraint(_flag->get_intx(), verbose);
  83   }
  84 
  85   JVMFlag::Error apply_intx(intx value, bool verbose) {
  86     return _constraint(value, verbose);
  87   }
  88 };
  89 
  90 class JVMFlagConstraint_uint : public JVMFlagConstraint {
  91   JVMFlagConstraintFunc_uint _constraint;
  92 
  93 public:
  94   JVMFlagConstraint_uint(const JVMFlag* flag,
  95                          JVMFlagConstraintFunc_uint func,
  96                          ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
  97 
  98   JVMFlag::Error apply(bool verbose) {
  99     return _constraint(_flag->get_uint(), verbose);
 100   }
 101 
 102   JVMFlag::Error apply_uint(uint value, bool verbose) {
 103     return _constraint(value, verbose);
 104   }
 105 };
 106 
 107 class JVMFlagConstraint_uintx : public JVMFlagConstraint {
 108   JVMFlagConstraintFunc_uintx _constraint;
 109 
 110 public:
 111   JVMFlagConstraint_uintx(const JVMFlag* flag,
 112                           JVMFlagConstraintFunc_uintx func,
 113                           ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
 114 
 115   JVMFlag::Error apply(bool verbose) {
 116     return _constraint(_flag->get_uintx(), verbose);
 117   }
 118 
 119   JVMFlag::Error apply_uintx(uintx value, bool verbose) {
 120     return _constraint(value, verbose);
 121   }
 122 };
 123 
 124 class JVMFlagConstraint_uint64_t : public JVMFlagConstraint {
 125   JVMFlagConstraintFunc_uint64_t _constraint;
 126 
 127 public:
 128   JVMFlagConstraint_uint64_t(const JVMFlag* flag,
 129                              JVMFlagConstraintFunc_uint64_t func,
 130                              ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
 131 
 132   JVMFlag::Error apply(bool verbose) {
 133     return _constraint(_flag->get_uint64_t(), verbose);
 134   }
 135 
 136   JVMFlag::Error apply_uint64_t(uint64_t value, bool verbose) {
 137     return _constraint(value, verbose);
 138   }
 139 };
 140 
 141 class JVMFlagConstraint_size_t : public JVMFlagConstraint {
 142   JVMFlagConstraintFunc_size_t _constraint;
 143 
 144 public:
 145   JVMFlagConstraint_size_t(const JVMFlag* flag,
 146                            JVMFlagConstraintFunc_size_t func,
 147                            ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
 148 
 149   JVMFlag::Error apply(bool verbose) {
 150     return _constraint(_flag->get_size_t(), verbose);
 151   }
 152 
 153   JVMFlag::Error apply_size_t(size_t value, bool verbose) {
 154     return _constraint(value, verbose);
 155   }
 156 };
 157 
 158 class JVMFlagConstraint_double : public JVMFlagConstraint {
 159   JVMFlagConstraintFunc_double _constraint;
 160 
 161 public:
 162   JVMFlagConstraint_double(const JVMFlag* flag,
 163                            JVMFlagConstraintFunc_double func,
 164                            ConstraintType type) : JVMFlagConstraint(flag, type), _constraint(func) {}
 165 
 166   JVMFlag::Error apply(bool verbose) {
 167     return _constraint(_flag->get_double(), verbose);
 168   }
 169 
 170   JVMFlag::Error apply_double(double value, bool verbose) {
 171     return _constraint(value, verbose);
 172   }
 173 };
 174 
 175 // No constraint emitting
 176 void emit_constraint_no(...)                            { /* NOP */ }
 177 
 178 // No constraint emitting if function argument is NOT provided
 179 void emit_constraint_bool(const JVMFlag* /*flag*/)      { /* NOP */ }
 180 void emit_constraint_ccstr(const JVMFlag* /*flag*/)     { /* NOP */ }
 181 void emit_constraint_ccstrlist(const JVMFlag* /*flag*/) { /* NOP */ }
 182 void emit_constraint_int(const JVMFlag* /*flag*/)       { /* NOP */ }
 183 void emit_constraint_intx(const JVMFlag* /*flag*/)      { /* NOP */ }
 184 void emit_constraint_uint(const JVMFlag* /*flag*/)      { /* NOP */ }
 185 void emit_constraint_uintx(const JVMFlag* /*flag*/)     { /* NOP */ }
 186 void emit_constraint_uint64_t(const JVMFlag* /*flag*/)  { /* NOP */ }
 187 void emit_constraint_size_t(const JVMFlag* /*flag*/)    { /* NOP */ }
 188 void emit_constraint_double(const JVMFlag* /*flag*/)    { /* NOP */ }
 189 
 190 // JVMFlagConstraint emitting code functions if function argument is provided
 191 void emit_constraint_bool(const JVMFlag* flag, JVMFlagConstraintFunc_bool func, JVMFlagConstraint::ConstraintType type) {
 192   JVMFlagConstraintList::add(new JVMFlagConstraint_bool(flag, func, type));
 193 }
 194 void emit_constraint_int(const JVMFlag* flag, JVMFlagConstraintFunc_int func, JVMFlagConstraint::ConstraintType type) {
 195   JVMFlagConstraintList::add(new JVMFlagConstraint_int(flag, func, type));
 196 }
 197 void emit_constraint_intx(const JVMFlag* flag, JVMFlagConstraintFunc_intx func, JVMFlagConstraint::ConstraintType type) {
 198   JVMFlagConstraintList::add(new JVMFlagConstraint_intx(flag, func, type));
 199 }
 200 void emit_constraint_uint(const JVMFlag* flag, JVMFlagConstraintFunc_uint func, JVMFlagConstraint::ConstraintType type) {
 201   JVMFlagConstraintList::add(new JVMFlagConstraint_uint(flag, func, type));
 202 }
 203 void emit_constraint_uintx(const JVMFlag* flag, JVMFlagConstraintFunc_uintx func, JVMFlagConstraint::ConstraintType type) {
 204   JVMFlagConstraintList::add(new JVMFlagConstraint_uintx(flag, func, type));
 205 }
 206 void emit_constraint_uint64_t(const JVMFlag* flag, JVMFlagConstraintFunc_uint64_t func, JVMFlagConstraint::ConstraintType type) {
 207   JVMFlagConstraintList::add(new JVMFlagConstraint_uint64_t(flag, func, type));
 208 }
 209 void emit_constraint_size_t(const JVMFlag* flag, JVMFlagConstraintFunc_size_t func, JVMFlagConstraint::ConstraintType type) {
 210   JVMFlagConstraintList::add(new JVMFlagConstraint_size_t(flag, func, type));
 211 }
 212 void emit_constraint_double(const JVMFlag* flag, JVMFlagConstraintFunc_double func, JVMFlagConstraint::ConstraintType type) {
 213   JVMFlagConstraintList::add(new JVMFlagConstraint_double(flag, func, type));
 214 }
 215 
 216 // Generate code to call emit_constraint_xxx function
 217 #define EMIT_CONSTRAINT_START       (void)(0
 218 #define EMIT_CONSTRAINT(type, name) ); emit_constraint_##type(JVMFlagEx::flag_from_enum(FLAG_MEMBER_ENUM(name))
 219 #define EMIT_CONSTRAINT_NO          ); emit_constraint_no(0
 220 #define EMIT_CONSTRAINT_PRODUCT_FLAG(type, name, value, doc)      EMIT_CONSTRAINT(type, name)
 221 #define EMIT_CONSTRAINT_DIAGNOSTIC_FLAG(type, name, value, doc)   EMIT_CONSTRAINT(type, name)
 222 #define EMIT_CONSTRAINT_EXPERIMENTAL_FLAG(type, name, value, doc) EMIT_CONSTRAINT(type, name)
 223 #define EMIT_CONSTRAINT_MANAGEABLE_FLAG(type, name, value, doc)   EMIT_CONSTRAINT(type, name)
 224 #define EMIT_CONSTRAINT_PRODUCT_RW_FLAG(type, name, value, doc)   EMIT_CONSTRAINT(type, name)
 225 #define EMIT_CONSTRAINT_PD_PRODUCT_FLAG(type, name, doc)          EMIT_CONSTRAINT(type, name)
 226 #define EMIT_CONSTRAINT_PD_DIAGNOSTIC_FLAG(type, name, doc)       EMIT_CONSTRAINT(type, name)
 227 #ifndef PRODUCT
 228 #define EMIT_CONSTRAINT_DEVELOPER_FLAG(type, name, value, doc)    EMIT_CONSTRAINT(type, name)
 229 #define EMIT_CONSTRAINT_PD_DEVELOPER_FLAG(type, name, doc)        EMIT_CONSTRAINT(type, name)
 230 #define EMIT_CONSTRAINT_NOTPRODUCT_FLAG(type, name, value, doc)   EMIT_CONSTRAINT(type, name)
 231 #else
 232 #define EMIT_CONSTRAINT_DEVELOPER_FLAG(type, name, value, doc)    EMIT_CONSTRAINT_NO
 233 #define EMIT_CONSTRAINT_PD_DEVELOPER_FLAG(type, name, doc)        EMIT_CONSTRAINT_NO
 234 #define EMIT_CONSTRAINT_NOTPRODUCT_FLAG(type, name, value, doc)   EMIT_CONSTRAINT_NO
 235 #endif
 236 #ifdef _LP64
 237 #define EMIT_CONSTRAINT_LP64_PRODUCT_FLAG(type, name, value, doc) EMIT_CONSTRAINT(type, name)
 238 #else
 239 #define EMIT_CONSTRAINT_LP64_PRODUCT_FLAG(type, name, value, doc) EMIT_CONSTRAINT_NO
 240 #endif
 241 #define EMIT_CONSTRAINT_END         );
 242 
 243 // Generate func argument to pass into emit_constraint_xxx functions
 244 #define EMIT_CONSTRAINT_CHECK(func, type)                         , func, JVMFlagConstraint::type
 245 
 246 // the "name" argument must be a string literal
 247 #define INITIAL_CONSTRAINTS_SIZE 72
 248 GrowableArray<JVMFlagConstraint*>* JVMFlagConstraintList::_constraints = NULL;
 249 JVMFlagConstraint::ConstraintType JVMFlagConstraintList::_validating_type = JVMFlagConstraint::AtParse;
 250 
 251 // Check the ranges of all flags that have them or print them out and exit if requested
 252 void JVMFlagConstraintList::init(void) {
 253   _constraints = new (ResourceObj::C_HEAP, mtArguments) GrowableArray<JVMFlagConstraint*>(INITIAL_CONSTRAINTS_SIZE, true);
 254 
 255   EMIT_CONSTRAINT_START
 256 
 257   ALL_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
 258             EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
 259             EMIT_CONSTRAINT_PRODUCT_FLAG,
 260             EMIT_CONSTRAINT_PD_PRODUCT_FLAG,
 261             EMIT_CONSTRAINT_DIAGNOSTIC_FLAG,
 262             EMIT_CONSTRAINT_PD_DIAGNOSTIC_FLAG,
 263             EMIT_CONSTRAINT_EXPERIMENTAL_FLAG,
 264             EMIT_CONSTRAINT_NOTPRODUCT_FLAG,
 265             EMIT_CONSTRAINT_MANAGEABLE_FLAG,
 266             EMIT_CONSTRAINT_PRODUCT_RW_FLAG,
 267             EMIT_CONSTRAINT_LP64_PRODUCT_FLAG,
 268             IGNORE_RANGE,
 269             EMIT_CONSTRAINT_CHECK)
 270 
 271   EMIT_CONSTRAINT_END
 272 }
 273 
 274 JVMFlagConstraint* JVMFlagConstraintList::find(const JVMFlag* flag) {
 275   JVMFlagConstraint* found = NULL;
 276   for (int i=0; i<length(); i++) {
 277     JVMFlagConstraint* constraint = at(i);
 278     if (constraint->flag() == flag) {
 279       found = constraint;
 280       break;
 281     }
 282   }
 283   return found;
 284 }
 285 
 286 // Find constraints and return only if found constraint's type is equal or lower than current validating type.
 287 JVMFlagConstraint* JVMFlagConstraintList::find_if_needs_check(const JVMFlag* flag) {
 288   JVMFlagConstraint* found = NULL;
 289   JVMFlagConstraint* constraint = find(flag);
 290   if (constraint != NULL && (constraint->type() <= _validating_type)) {
 291     found = constraint;
 292   }
 293   return found;
 294 }
 295 
 296 // Check constraints for specific constraint type.
 297 bool JVMFlagConstraintList::check_constraints(JVMFlagConstraint::ConstraintType type) {
 298   guarantee(type > _validating_type, "Constraint check is out of order.");
 299   _validating_type = type;
 300 
 301   bool status = true;
 302   for (int i=0; i<length(); i++) {
 303     JVMFlagConstraint* constraint = at(i);
 304     if (type != constraint->type()) continue;
 305     if (constraint->apply(true) != JVMFlag::SUCCESS) status = false;
 306   }
 307   return status;
 308 }