Path: blob/master/src/hotspot/share/runtime/flags/jvmFlag.hpp
40957 views
/*1* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_RUNTIME_FLAGS_JVMFLAG_HPP25#define SHARE_RUNTIME_FLAGS_JVMFLAG_HPP2627#include "utilities/globalDefinitions.hpp"28#include "utilities/enumIterator.hpp"29#include "utilities/macros.hpp"30#include "utilities/vmEnums.hpp"31#include <type_traits>3233class outputStream;3435enum class JVMFlagOrigin : int {36// This is the value returned by JVMFlag::get_origin(). It records who37// has most recently changed the value of a JVMFlag. DEFAULT means that the38// flag was never changed, or was most recently changed by FLAG_SET_DEFAULT.39DEFAULT = 0,40COMMAND_LINE = 1,41ENVIRON_VAR = 2,42CONFIG_FILE = 3,43MANAGEMENT = 4,44ERGONOMIC = 5,45ATTACH_ON_DEMAND = 6,46INTERNAL = 7,47JIMAGE_RESOURCE = 8,48};4950ENUMERATOR_RANGE(JVMFlagOrigin, JVMFlagOrigin::DEFAULT, JVMFlagOrigin::JIMAGE_RESOURCE)5152class JVMFlag {53friend class VMStructs;5455public:56enum Flags : int {57VALUE_ORIGIN_BITS = 4,58VALUE_ORIGIN_MASK = right_n_bits(VALUE_ORIGIN_BITS),5960// flag kind61KIND_PRODUCT = 1 << 4,62KIND_MANAGEABLE = 1 << 5,63KIND_DIAGNOSTIC = 1 << 6,64KIND_EXPERIMENTAL = 1 << 7,65KIND_NOT_PRODUCT = 1 << 8,66KIND_DEVELOP = 1 << 9,67KIND_PLATFORM_DEPENDENT = 1 << 10,68KIND_C1 = 1 << 11,69KIND_C2 = 1 << 12,70KIND_ARCH = 1 << 13,71KIND_LP64_PRODUCT = 1 << 14,72KIND_JVMCI = 1 << 15,7374// Note the difference:75// f->get_origin() == COMMAND_LINE76// f was mostly recently set by the command-line77// f->_flags & WAS_SET_ON_COMMAND_LINE78// f was specified on the command-line (but may have since been updated by79// someone else like FLAG_SET_ERGO)80WAS_SET_ON_COMMAND_LINE = 1 << 17,8182KIND_MASK = ~(VALUE_ORIGIN_MASK | WAS_SET_ON_COMMAND_LINE)83};8485enum Error {86// no error87SUCCESS = 0,88// flag name is missing89MISSING_NAME,90// flag value is missing91MISSING_VALUE,92// error parsing the textual form of the value93WRONG_FORMAT,94// flag is not writable95NON_WRITABLE,96// flag value is outside of its bounds97OUT_OF_BOUNDS,98// flag value violates its constraint99VIOLATES_CONSTRAINT,100// there is no flag with the given name101INVALID_FLAG,102// the flag can only be set only on command line during invocation of the VM103COMMAND_LINE_ONLY,104// the flag may only be set once105SET_ONLY_ONCE,106// the flag is not writable in this combination of product/debug build107CONSTANT,108// other, unspecified error related to setting the flag109ERR_OTHER110};111112enum MsgType {113NONE = 0,114DIAGNOSTIC_FLAG_BUT_LOCKED,115EXPERIMENTAL_FLAG_BUT_LOCKED,116DEVELOPER_FLAG_BUT_PRODUCT_BUILD,117NOTPRODUCT_FLAG_BUT_PRODUCT_BUILD118};119120#define JVM_FLAG_NON_STRING_TYPES_DO(f) \121f(bool) \122f(int) \123f(uint) \124f(intx) \125f(uintx) \126f(uint64_t) \127f(size_t) \128f(double)129130#define JVM_FLAG_TYPE_DECLARE(t) \131TYPE_ ## t,132133enum FlagType : int {134JVM_FLAG_NON_STRING_TYPES_DO(JVM_FLAG_TYPE_DECLARE)135// The two string types are a bit irregular: is_ccstr() returns true for both types.136TYPE_ccstr,137TYPE_ccstrlist,138NUM_FLAG_TYPES139};140141private:142void* _addr;143const char* _name;144Flags _flags;145int _type;146147NOT_PRODUCT(const char* _doc;)148149public:150// points to all Flags static array151static JVMFlag* flags;152153// number of flags154static size_t numFlags;155156private:157static JVMFlag* find_flag(const char* name, size_t length, bool allow_locked, bool return_flag);158159public:160constexpr JVMFlag() : _addr(), _name(), _flags(), _type() NOT_PRODUCT(COMMA _doc()) {}161162constexpr JVMFlag(int flag_enum, FlagType type, const char* name,163void* addr, int flags, int extra_flags, const char* doc);164165constexpr JVMFlag(int flag_enum, FlagType type, const char* name,166void* addr, int flags, const char* doc);167168static JVMFlag* find_flag(const char* name) {169return find_flag(name, strlen(name), false, false);170}171static JVMFlag* find_declared_flag(const char* name, size_t length) {172return find_flag(name, length, true, true);173}174static JVMFlag* find_declared_flag(const char* name) {175return find_declared_flag(name, strlen(name));176}177178static JVMFlag* fuzzy_match(const char* name, size_t length, bool allow_locked = false);179180static void assert_valid_flag_enum(JVMFlagsEnum i) NOT_DEBUG_RETURN;181static void check_all_flag_declarations() NOT_DEBUG_RETURN;182183inline JVMFlagsEnum flag_enum() const {184JVMFlagsEnum i = static_cast<JVMFlagsEnum>(this - JVMFlag::flags);185assert_valid_flag_enum(i);186return i;187}188189static JVMFlag* flag_from_enum(JVMFlagsEnum flag_enum) {190assert_valid_flag_enum(flag_enum);191return &JVMFlag::flags[flag_enum];192}193194#define JVM_FLAG_TYPE_ACCESSOR(t) \195bool is_##t() const { return _type == TYPE_##t;} \196t get_##t() const { assert(is_##t(), "sanity"); return *((t*) _addr); }197198JVM_FLAG_NON_STRING_TYPES_DO(JVM_FLAG_TYPE_ACCESSOR)199200bool is_ccstr() const { return _type == TYPE_ccstr || _type == TYPE_ccstrlist; }201bool ccstr_accumulates() const { return _type == TYPE_ccstrlist; }202ccstr get_ccstr() const { assert(is_ccstr(), "sanity"); return *((ccstr*) _addr); }203void set_ccstr(ccstr value) { assert(is_ccstr(), "sanity"); *((ccstr*) _addr) = value; }204205#define JVM_FLAG_AS_STRING(t) \206case TYPE_##t: return STR(t);207208const char* type_string() const {209return type_string_for((FlagType)_type);210}211212static const char* type_string_for(FlagType t) {213switch(t) {214JVM_FLAG_NON_STRING_TYPES_DO(JVM_FLAG_AS_STRING)215case TYPE_ccstr: return "ccstr";216case TYPE_ccstrlist: return "ccstrlist";217default:218ShouldNotReachHere();219return "unknown";220}221}222223int type() const { return _type; }224const char* name() const { return _name; }225226// Do not use JVMFlag::read() or JVMFlag::write() directly unless you know227// what you're doing. Use FLAG_SET_XXX macros or JVMFlagAccess instead.228template <typename T> T read() const {229assert_compatible_type<T>(_type);230return *static_cast<T*>(_addr);231}232233template <typename T> void write(T value) {234assert_compatible_type<T>(_type);235*static_cast<T*>(_addr) = value;236}237238JVMFlagOrigin get_origin() const { return JVMFlagOrigin(_flags & VALUE_ORIGIN_MASK); }239void set_origin(JVMFlagOrigin origin);240241bool is_default() const { return (get_origin() == JVMFlagOrigin::DEFAULT); }242bool is_ergonomic() const { return (get_origin() == JVMFlagOrigin::ERGONOMIC); }243bool is_command_line() const { return (_flags & WAS_SET_ON_COMMAND_LINE) != 0; }244void set_command_line() { _flags = Flags(_flags | WAS_SET_ON_COMMAND_LINE); }245bool is_jimage_resource() const { return (get_origin() == JVMFlagOrigin::JIMAGE_RESOURCE); }246bool is_product() const { return (_flags & KIND_PRODUCT) != 0; }247bool is_manageable() const { return (_flags & KIND_MANAGEABLE) != 0; }248bool is_diagnostic() const { return (_flags & KIND_DIAGNOSTIC) != 0; }249bool is_experimental() const { return (_flags & KIND_EXPERIMENTAL) != 0; }250bool is_notproduct() const { return (_flags & KIND_NOT_PRODUCT) != 0; }251bool is_develop() const { return (_flags & KIND_DEVELOP) != 0; }252253bool is_constant_in_binary() const;254255bool is_unlocker() const;256bool is_unlocked() const;257258// Only manageable flags can be accessed by writeableFlags.cpp259bool is_writeable() const { return is_manageable(); }260// All flags except "manageable" are assumed to be internal flags.261bool is_external() const { return is_manageable(); }262263void clear_diagnostic();264void clear_experimental();265void set_product();266267JVMFlag::MsgType get_locked_message(char*, int) const;268269static bool is_default(JVMFlagsEnum flag);270static bool is_ergo(JVMFlagsEnum flag);271static bool is_cmdline(JVMFlagsEnum flag);272static bool is_jimage_resource(JVMFlagsEnum flag);273static void setOnCmdLine(JVMFlagsEnum flag);274275276// printRanges will print out flags type, name and range values as expected by -XX:+PrintFlagsRanges277void print_on(outputStream* st, bool withComments = false, bool printRanges = false) const;278void print_kind(outputStream* st, unsigned int width) const;279void print_origin(outputStream* st, unsigned int width) const;280void print_as_flag(outputStream* st) const;281282static const char* flag_error_str(JVMFlag::Error error);283284private:285// type checking - the following functions make sure you access *_addr as286// the correct type <T>287288static void assert_valid_type_enum(int type_enum) {289assert(0 <= type_enum && type_enum < NUM_FLAG_TYPES, "sanity");290}291292// The following computation is not universal, but should be correct293// for the limited number of types that can be stored inside a JVMFlag.294template <typename T>295static constexpr int type_signature() {296return int(sizeof(T)) |297(((std::is_integral<T>::value) ? 1 : 0) << 8) |298(((std::is_signed<T>::value) ? 1 : 0) << 9) |299(((std::is_pointer<T>::value) ? 1 : 0) << 10);300}301302static const int type_signatures[];303304public:305template <typename T>306static void assert_compatible_type(int type_enum) {307assert(is_compatible_type<T>(type_enum), "must be");308}309310template <typename T>311static bool is_compatible_type(int type_enum) {312assert_valid_type_enum(type_enum);313return type_signatures[type_enum] == type_signature<T>();314}315316public:317static void printSetFlags(outputStream* out);318319// printRanges will print out flags type, name and range values as expected by -XX:+PrintFlagsRanges320static void printFlags(outputStream* out, bool withComments, bool printRanges = false, bool skipDefaults = false);321static void printError(bool verbose, const char* msg, ...) ATTRIBUTE_PRINTF(2, 3);322323static void verify() PRODUCT_RETURN;324};325326#define DECLARE_CONSTRAINT(type, func) JVMFlag::Error func(type value, bool verbose);327328#endif // SHARE_RUNTIME_FLAGS_JVMFLAG_HPP329330331