Path: blob/master/src/hotspot/share/runtime/flags/jvmFlag.cpp
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#include "precompiled.hpp"25#include "jvm_io.h"26#include "jfr/jfrEvents.hpp"27#include "memory/allocation.inline.hpp"28#include "runtime/arguments.hpp"29#include "runtime/flags/jvmFlag.hpp"30#include "runtime/flags/jvmFlagAccess.hpp"31#include "runtime/flags/jvmFlagLookup.hpp"32#include "runtime/globals_extension.hpp"33#include "utilities/defaultStream.hpp"34#include "utilities/stringUtils.hpp"3536static bool is_product_build() {37#ifdef PRODUCT38return true;39#else40return false;41#endif42}4344void JVMFlag::set_origin(JVMFlagOrigin new_origin) {45int old_flags = _flags;46int origin = static_cast<int>(new_origin);47assert((origin & VALUE_ORIGIN_MASK) == origin, "sanity");48int was_in_cmdline = (new_origin == JVMFlagOrigin::COMMAND_LINE) ? WAS_SET_ON_COMMAND_LINE : 0;49_flags = Flags((_flags & ~VALUE_ORIGIN_MASK) | origin | was_in_cmdline);50if ((old_flags & WAS_SET_ON_COMMAND_LINE) != 0) {51assert((_flags & WAS_SET_ON_COMMAND_LINE) != 0, "once initialized, should never change");52}53}5455/**56* Returns if this flag is a constant in the binary. Right now this is57* true for notproduct and develop flags in product builds.58*/59bool JVMFlag::is_constant_in_binary() const {60#ifdef PRODUCT61return is_notproduct() || is_develop();62#else63return false;64#endif65}6667bool JVMFlag::is_unlocker() const {68return strcmp(_name, "UnlockDiagnosticVMOptions") == 0 ||69strcmp(_name, "UnlockExperimentalVMOptions") == 0;70}7172bool JVMFlag::is_unlocked() const {73if (is_diagnostic()) {74return UnlockDiagnosticVMOptions;75}76if (is_experimental()) {77return UnlockExperimentalVMOptions;78}79return true;80}8182void JVMFlag::clear_diagnostic() {83assert(is_diagnostic(), "sanity");84_flags = Flags(_flags & ~KIND_DIAGNOSTIC);85assert(!is_diagnostic(), "sanity");86}8788void JVMFlag::clear_experimental() {89assert(is_experimental(), "sanity");90_flags = Flags(_flags & ~KIND_EXPERIMENTAL);91assert(!is_experimental(), "sanity");92}9394void JVMFlag::set_product() {95assert(!is_product(), "sanity");96_flags = Flags(_flags | KIND_PRODUCT);97assert(is_product(), "sanity");98}99100// Get custom message for this locked flag, or NULL if101// none is available. Returns message type produced.102JVMFlag::MsgType JVMFlag::get_locked_message(char* buf, int buflen) const {103buf[0] = '\0';104if (is_diagnostic() && !is_unlocked()) {105jio_snprintf(buf, buflen,106"Error: VM option '%s' is diagnostic and must be enabled via -XX:+UnlockDiagnosticVMOptions.\n"107"Error: The unlock option must precede '%s'.\n",108_name, _name);109return JVMFlag::DIAGNOSTIC_FLAG_BUT_LOCKED;110}111if (is_experimental() && !is_unlocked()) {112jio_snprintf(buf, buflen,113"Error: VM option '%s' is experimental and must be enabled via -XX:+UnlockExperimentalVMOptions.\n"114"Error: The unlock option must precede '%s'.\n",115_name, _name);116return JVMFlag::EXPERIMENTAL_FLAG_BUT_LOCKED;117}118if (is_develop() && is_product_build()) {119jio_snprintf(buf, buflen, "Error: VM option '%s' is develop and is available only in debug version of VM.\n",120_name);121return JVMFlag::DEVELOPER_FLAG_BUT_PRODUCT_BUILD;122}123if (is_notproduct() && is_product_build()) {124jio_snprintf(buf, buflen, "Error: VM option '%s' is notproduct and is available only in debug version of VM.\n",125_name);126return JVMFlag::NOTPRODUCT_FLAG_BUT_PRODUCT_BUILD;127}128return JVMFlag::NONE;129}130131// Helper function for JVMFlag::print_on().132// Fills current line up to requested position.133// Should the current position already be past the requested position,134// one separator blank is enforced.135void fill_to_pos(outputStream* st, unsigned int req_pos) {136if ((unsigned int)st->position() < req_pos) {137st->fill_to(req_pos); // need to fill with blanks to reach req_pos138} else {139st->print(" "); // enforce blank separation. Previous field too long.140}141}142143void JVMFlag::print_on(outputStream* st, bool withComments, bool printRanges) const {144// Don't print notproduct and develop flags in a product build.145if (is_constant_in_binary()) {146return;147}148149if (!printRanges) {150// The command line options -XX:+PrintFlags* cause this function to be called151// for each existing flag to print information pertinent to this flag. The data152// is displayed in columnar form, with the following layout:153// col1 - data type, right-justified154// col2 - name, left-justified155// col3 - ' =' double-char, leading space to align with possible '+='156// col4 - value left-justified157// col5 - kind right-justified158// col6 - origin left-justified159// col7 - comments left-justified160//161// The column widths are fixed. They are defined such that, for most cases,162// an eye-pleasing tabular output is created.163//164// Sample output:165// bool ThreadPriorityVerbose = false {product} {default}166// uintx ThresholdTolerance = 10 {product} {default}167// size_t TLABSize = 0 {product} {default}168// uintx SurvivorRatio = 8 {product} {default}169// double InitialRAMPercentage = 1.562500 {product} {default}170// ccstr CompileCommandFile = MyFile.cmd {product} {command line}171// ccstrlist CompileOnly = Method1172// CompileOnly += Method2 {product} {command line}173// | | | | | | |174// | | | | | | +-- col7175// | | | | | +-- col6176// | | | | +-- col5177// | | | +-- col4178// | | +-- col3179// | +-- col2180// +-- col1181182const unsigned int col_spacing = 1;183const unsigned int col1_pos = 0;184const unsigned int col1_width = 9;185const unsigned int col2_pos = col1_pos + col1_width + col_spacing;186const unsigned int col2_width = 39;187const unsigned int col3_pos = col2_pos + col2_width + col_spacing;188const unsigned int col3_width = 2;189const unsigned int col4_pos = col3_pos + col3_width + col_spacing;190const unsigned int col4_width = 30;191const unsigned int col5_pos = col4_pos + col4_width + col_spacing;192const unsigned int col5_width = 20;193const unsigned int col6_pos = col5_pos + col5_width + col_spacing;194const unsigned int col6_width = 15;195const unsigned int col7_pos = col6_pos + col6_width + col_spacing;196const unsigned int col7_width = 1;197198st->fill_to(col1_pos);199st->print("%*s", col1_width, type_string()); // right-justified, therefore width is required.200201fill_to_pos(st, col2_pos);202st->print("%s", _name);203204fill_to_pos(st, col3_pos);205st->print(" ="); // use " =" for proper alignment with multiline ccstr output.206207fill_to_pos(st, col4_pos);208if (is_bool()) {209st->print("%s", get_bool() ? "true" : "false");210} else if (is_int()) {211st->print("%d", get_int());212} else if (is_uint()) {213st->print("%u", get_uint());214} else if (is_intx()) {215st->print(INTX_FORMAT, get_intx());216} else if (is_uintx()) {217st->print(UINTX_FORMAT, get_uintx());218} else if (is_uint64_t()) {219st->print(UINT64_FORMAT, get_uint64_t());220} else if (is_size_t()) {221st->print(SIZE_FORMAT, get_size_t());222} else if (is_double()) {223st->print("%f", get_double());224} else if (is_ccstr()) {225// Honor <newline> characters in ccstr: print multiple lines.226const char* cp = get_ccstr();227if (cp != NULL) {228const char* eol;229while ((eol = strchr(cp, '\n')) != NULL) {230size_t llen = pointer_delta(eol, cp, sizeof(char));231st->print("%.*s", (int)llen, cp);232st->cr();233cp = eol+1;234fill_to_pos(st, col2_pos);235st->print("%s", _name);236fill_to_pos(st, col3_pos);237st->print("+=");238fill_to_pos(st, col4_pos);239}240st->print("%s", cp);241}242} else {243st->print("unhandled type %s", type_string());244st->cr();245return;246}247248fill_to_pos(st, col5_pos);249print_kind(st, col5_width);250251fill_to_pos(st, col6_pos);252print_origin(st, col6_width);253254#ifndef PRODUCT255if (withComments) {256fill_to_pos(st, col7_pos);257st->print("%s", _doc);258}259#endif260st->cr();261} else if (!is_bool() && !is_ccstr()) {262// The command line options -XX:+PrintFlags* cause this function to be called263// for each existing flag to print information pertinent to this flag. The data264// is displayed in columnar form, with the following layout:265// col1 - data type, right-justified266// col2 - name, left-justified267// col4 - range [ min ... max]268// col5 - kind right-justified269// col6 - origin left-justified270// col7 - comments left-justified271//272// The column widths are fixed. They are defined such that, for most cases,273// an eye-pleasing tabular output is created.274//275// Sample output:276// intx MinPassesBeforeFlush [ 0 ... 9223372036854775807 ] {diagnostic} {default}277// uintx MinRAMFraction [ 1 ... 18446744073709551615 ] {product} {default}278// double MinRAMPercentage [ 0.000 ... 100.000 ] {product} {default}279// uintx MinSurvivorRatio [ 3 ... 18446744073709551615 ] {product} {default}280// size_t MinTLABSize [ 1 ... 9223372036854775807 ] {product} {default}281// intx MaxInlineSize [ 0 ... 2147483647 ] {product} {default}282// | | | | | |283// | | | | | +-- col7284// | | | | +-- col6285// | | | +-- col5286// | | +-- col4287// | +-- col2288// +-- col1289290const unsigned int col_spacing = 1;291const unsigned int col1_pos = 0;292const unsigned int col1_width = 9;293const unsigned int col2_pos = col1_pos + col1_width + col_spacing;294const unsigned int col2_width = 49;295const unsigned int col3_pos = col2_pos + col2_width + col_spacing;296const unsigned int col3_width = 0;297const unsigned int col4_pos = col3_pos + col3_width + col_spacing;298const unsigned int col4_width = 60;299const unsigned int col5_pos = col4_pos + col4_width + col_spacing;300const unsigned int col5_width = 35;301const unsigned int col6_pos = col5_pos + col5_width + col_spacing;302const unsigned int col6_width = 15;303const unsigned int col7_pos = col6_pos + col6_width + col_spacing;304const unsigned int col7_width = 1;305306st->fill_to(col1_pos);307st->print("%*s", col1_width, type_string()); // right-justified, therefore width is required.308309fill_to_pos(st, col2_pos);310st->print("%s", _name);311312fill_to_pos(st, col4_pos);313JVMFlagAccess::print_range(st, this);314315fill_to_pos(st, col5_pos);316print_kind(st, col5_width);317318fill_to_pos(st, col6_pos);319print_origin(st, col6_width);320321#ifndef PRODUCT322if (withComments) {323fill_to_pos(st, col7_pos);324st->print("%s", _doc);325}326#endif327st->cr();328}329}330331void JVMFlag::print_kind(outputStream* st, unsigned int width) const {332struct Data {333int flag;334const char* name;335};336337Data data[] = {338{ KIND_JVMCI, "JVMCI" },339{ KIND_C1, "C1" },340{ KIND_C2, "C2" },341{ KIND_ARCH, "ARCH" },342{ KIND_PLATFORM_DEPENDENT, "pd" },343{ KIND_PRODUCT, "product" },344{ KIND_MANAGEABLE, "manageable" },345{ KIND_DIAGNOSTIC, "diagnostic" },346{ KIND_EXPERIMENTAL, "experimental" },347{ KIND_NOT_PRODUCT, "notproduct" },348{ KIND_DEVELOP, "develop" },349{ KIND_LP64_PRODUCT, "lp64_product" },350{ -1, "" }351};352353if ((_flags & KIND_MASK) != 0) {354bool is_first = true;355const size_t buffer_size = 64;356size_t buffer_used = 0;357char kind[buffer_size];358359jio_snprintf(kind, buffer_size, "{");360buffer_used++;361for (int i = 0; data[i].flag != -1; i++) {362Data d = data[i];363if ((_flags & d.flag) != 0) {364if (is_first) {365is_first = false;366} else {367assert(buffer_used + 1 < buffer_size, "Too small buffer");368jio_snprintf(kind + buffer_used, buffer_size - buffer_used, " ");369buffer_used++;370}371size_t length = strlen(d.name);372assert(buffer_used + length < buffer_size, "Too small buffer");373jio_snprintf(kind + buffer_used, buffer_size - buffer_used, "%s", d.name);374buffer_used += length;375}376}377assert(buffer_used + 2 <= buffer_size, "Too small buffer");378jio_snprintf(kind + buffer_used, buffer_size - buffer_used, "}");379st->print("%*s", width, kind);380}381}382383void JVMFlag::print_origin(outputStream* st, unsigned int width) const {384st->print("{");385switch(get_origin()) {386case JVMFlagOrigin::DEFAULT:387st->print("default"); break;388case JVMFlagOrigin::COMMAND_LINE:389st->print("command line"); break;390case JVMFlagOrigin::ENVIRON_VAR:391st->print("environment"); break;392case JVMFlagOrigin::CONFIG_FILE:393st->print("config file"); break;394case JVMFlagOrigin::MANAGEMENT:395st->print("management"); break;396case JVMFlagOrigin::ERGONOMIC:397if (_flags & WAS_SET_ON_COMMAND_LINE) {398st->print("command line, ");399}400st->print("ergonomic"); break;401case JVMFlagOrigin::ATTACH_ON_DEMAND:402st->print("attach"); break;403case JVMFlagOrigin::INTERNAL:404st->print("internal"); break;405case JVMFlagOrigin::JIMAGE_RESOURCE:406st->print("jimage"); break;407}408st->print("}");409}410411void JVMFlag::print_as_flag(outputStream* st) const {412if (is_bool()) {413st->print("-XX:%s%s", get_bool() ? "+" : "-", _name);414} else if (is_int()) {415st->print("-XX:%s=%d", _name, get_int());416} else if (is_uint()) {417st->print("-XX:%s=%u", _name, get_uint());418} else if (is_intx()) {419st->print("-XX:%s=" INTX_FORMAT, _name, get_intx());420} else if (is_uintx()) {421st->print("-XX:%s=" UINTX_FORMAT, _name, get_uintx());422} else if (is_uint64_t()) {423st->print("-XX:%s=" UINT64_FORMAT, _name, get_uint64_t());424} else if (is_size_t()) {425st->print("-XX:%s=" SIZE_FORMAT, _name, get_size_t());426} else if (is_double()) {427st->print("-XX:%s=%f", _name, get_double());428} else if (is_ccstr()) {429st->print("-XX:%s=", _name);430const char* cp = get_ccstr();431if (cp != NULL) {432// Need to turn embedded '\n's back into separate arguments433// Not so efficient to print one character at a time,434// but the choice is to do the transformation to a buffer435// and print that. And this need not be efficient.436for (; *cp != '\0'; cp += 1) {437switch (*cp) {438default:439st->print("%c", *cp);440break;441case '\n':442st->print(" -XX:%s=", _name);443break;444}445}446}447} else {448ShouldNotReachHere();449}450}451452const char* JVMFlag::flag_error_str(JVMFlag::Error error) {453switch (error) {454case JVMFlag::MISSING_NAME: return "MISSING_NAME";455case JVMFlag::MISSING_VALUE: return "MISSING_VALUE";456case JVMFlag::NON_WRITABLE: return "NON_WRITABLE";457case JVMFlag::OUT_OF_BOUNDS: return "OUT_OF_BOUNDS";458case JVMFlag::VIOLATES_CONSTRAINT: return "VIOLATES_CONSTRAINT";459case JVMFlag::INVALID_FLAG: return "INVALID_FLAG";460case JVMFlag::ERR_OTHER: return "ERR_OTHER";461case JVMFlag::SUCCESS: return "SUCCESS";462default: ShouldNotReachHere(); return "NULL";463}464}465466//----------------------------------------------------------------------467// Build flagTable[]468469// Find out the number of LP64/ARCH/JVMCI/COMPILER1/COMPILER2 flags,470// for JVMFlag::flag_group()471472#define ENUM_F(type, name, ...) enum_##name,473#define IGNORE_F(...)474475// dev dev-pd pro pro-pd notpro range constraint476enum FlagCounter_LP64 { LP64_RUNTIME_FLAGS( ENUM_F, ENUM_F, ENUM_F, ENUM_F, ENUM_F, IGNORE_F, IGNORE_F) num_flags_LP64 };477enum FlagCounter_ARCH { ARCH_FLAGS( ENUM_F, ENUM_F, ENUM_F, IGNORE_F, IGNORE_F) num_flags_ARCH };478enum FlagCounter_JVMCI { JVMCI_ONLY(JVMCI_FLAGS( ENUM_F, ENUM_F, ENUM_F, ENUM_F, ENUM_F, IGNORE_F, IGNORE_F)) num_flags_JVMCI };479enum FlagCounter_C1 { COMPILER1_PRESENT(C1_FLAGS(ENUM_F, ENUM_F, ENUM_F, ENUM_F, ENUM_F, IGNORE_F, IGNORE_F)) num_flags_C1 };480enum FlagCounter_C2 { COMPILER2_PRESENT(C2_FLAGS(ENUM_F, ENUM_F, ENUM_F, ENUM_F, ENUM_F, IGNORE_F, IGNORE_F)) num_flags_C2 };481482const int first_flag_enum_LP64 = 0;483const int first_flag_enum_ARCH = first_flag_enum_LP64 + num_flags_LP64;484const int first_flag_enum_JVMCI = first_flag_enum_ARCH + num_flags_ARCH;485const int first_flag_enum_C1 = first_flag_enum_JVMCI + num_flags_JVMCI;486const int first_flag_enum_C2 = first_flag_enum_C1 + num_flags_C1;487const int first_flag_enum_other = first_flag_enum_C2 + num_flags_C2;488489static constexpr int flag_group(int flag_enum) {490if (flag_enum < first_flag_enum_ARCH) return JVMFlag::KIND_LP64_PRODUCT;491if (flag_enum < first_flag_enum_JVMCI) return JVMFlag::KIND_ARCH;492if (flag_enum < first_flag_enum_C1) return JVMFlag::KIND_JVMCI;493if (flag_enum < first_flag_enum_C2) return JVMFlag::KIND_C1;494if (flag_enum < first_flag_enum_other) return JVMFlag::KIND_C2;495496return 0;497}498499constexpr JVMFlag::JVMFlag(int flag_enum, FlagType type, const char* name,500void* addr, int flags, int extra_flags, const char* doc) :501_addr(addr), _name(name), _flags(), _type(type) NOT_PRODUCT(COMMA _doc(doc)) {502flags = flags | extra_flags | static_cast<int>(JVMFlagOrigin::DEFAULT) | flag_group(flag_enum);503if ((flags & JVMFlag::KIND_PRODUCT) != 0) {504if (flags & (JVMFlag::KIND_DIAGNOSTIC | JVMFlag::KIND_MANAGEABLE | JVMFlag::KIND_EXPERIMENTAL)) {505// Backwards compatibility. This will be relaxed in JDK-7123237.506flags &= ~(JVMFlag::KIND_PRODUCT);507}508}509_flags = static_cast<Flags>(flags);510}511512constexpr JVMFlag::JVMFlag(int flag_enum, FlagType type, const char* name,513void* addr, int flags, const char* doc) :514JVMFlag(flag_enum, type, name, addr, flags, /*extra_flags*/0, doc) {}515516const int PRODUCT_KIND = JVMFlag::KIND_PRODUCT;517const int PRODUCT_KIND_PD = JVMFlag::KIND_PRODUCT | JVMFlag::KIND_PLATFORM_DEPENDENT;518const int DEVELOP_KIND = JVMFlag::KIND_DEVELOP;519const int DEVELOP_KIND_PD = JVMFlag::KIND_DEVELOP | JVMFlag::KIND_PLATFORM_DEPENDENT;520const int NOTPROD_KIND = JVMFlag::KIND_NOT_PRODUCT;521522#define FLAG_TYPE(type) (JVMFlag::TYPE_ ## type)523#define INITIALIZE_DEVELOP_FLAG( type, name, value, ...) JVMFlag(FLAG_MEMBER_ENUM(name), FLAG_TYPE(type), XSTR(name), (void*)&name, DEVELOP_KIND, __VA_ARGS__),524#define INITIALIZE_DEVELOP_FLAG_PD(type, name, ...) JVMFlag(FLAG_MEMBER_ENUM(name), FLAG_TYPE(type), XSTR(name), (void*)&name, DEVELOP_KIND_PD, __VA_ARGS__),525#define INITIALIZE_PRODUCT_FLAG( type, name, value, ...) JVMFlag(FLAG_MEMBER_ENUM(name), FLAG_TYPE(type), XSTR(name), (void*)&name, PRODUCT_KIND, __VA_ARGS__),526#define INITIALIZE_PRODUCT_FLAG_PD(type, name, ...) JVMFlag(FLAG_MEMBER_ENUM(name), FLAG_TYPE(type), XSTR(name), (void*)&name, PRODUCT_KIND_PD, __VA_ARGS__),527#define INITIALIZE_NOTPROD_FLAG( type, name, value, ...) JVMFlag(FLAG_MEMBER_ENUM(name), FLAG_TYPE(type), XSTR(name), (void*)&name, NOTPROD_KIND, __VA_ARGS__),528529// Handy aliases to match the symbols used in the flag specification macros.530const int DIAGNOSTIC = JVMFlag::KIND_DIAGNOSTIC;531const int MANAGEABLE = JVMFlag::KIND_MANAGEABLE;532const int EXPERIMENTAL = JVMFlag::KIND_EXPERIMENTAL;533534#define MATERIALIZE_ALL_FLAGS \535ALL_FLAGS(INITIALIZE_DEVELOP_FLAG, \536INITIALIZE_DEVELOP_FLAG_PD, \537INITIALIZE_PRODUCT_FLAG, \538INITIALIZE_PRODUCT_FLAG_PD, \539INITIALIZE_NOTPROD_FLAG, \540IGNORE_RANGE, \541IGNORE_CONSTRAINT)542543static JVMFlag flagTable[NUM_JVMFlagsEnum + 1] = {544MATERIALIZE_ALL_FLAGS545JVMFlag() // The iteration code wants a flag with a NULL name at the end of the table.546};547548// We want flagTable[] to be completely initialized at C++ compilation time, which requires549// that all arguments passed to JVMFlag() constructors be constexpr. The following line550// checks for this -- if any non-constexpr arguments are passed, the C++ compiler will551// generate an error.552//553// constexpr implies internal linkage. This means the flagTable_verify_constexpr[] variable554// will not be included in jvmFlag.o, so there's no footprint cost for having this variable.555//556// Note that we cannot declare flagTable[] as constexpr because JVMFlag::_flags is modified557// at runtime.558constexpr JVMFlag flagTable_verify_constexpr[] = { MATERIALIZE_ALL_FLAGS };559560JVMFlag* JVMFlag::flags = flagTable;561size_t JVMFlag::numFlags = (sizeof(flagTable) / sizeof(JVMFlag));562563#define JVM_FLAG_TYPE_SIGNATURE(t) JVMFlag::type_signature<t>(),564565const int JVMFlag::type_signatures[] = {566JVM_FLAG_NON_STRING_TYPES_DO(JVM_FLAG_TYPE_SIGNATURE)567JVMFlag::type_signature<ccstr>(),568JVMFlag::type_signature<ccstr>()569};570571// Search the flag table for a named flag572JVMFlag* JVMFlag::find_flag(const char* name, size_t length, bool allow_locked, bool return_flag) {573JVMFlag* flag = JVMFlagLookup::find(name, length);574if (flag != NULL) {575// Found a matching entry.576// Don't report notproduct and develop flags in product builds.577if (flag->is_constant_in_binary()) {578return (return_flag ? flag : NULL);579}580// Report locked flags only if allowed.581if (!(flag->is_unlocked() || flag->is_unlocker())) {582if (!allow_locked) {583// disable use of locked flags, e.g. diagnostic, experimental,584// etc. until they are explicitly unlocked585return NULL;586}587}588return flag;589}590// JVMFlag name is not in the flag table591return NULL;592}593594JVMFlag* JVMFlag::fuzzy_match(const char* name, size_t length, bool allow_locked) {595float VMOptionsFuzzyMatchSimilarity = 0.7f;596JVMFlag* match = NULL;597float score;598float max_score = -1;599600for (JVMFlag* current = &flagTable[0]; current->_name != NULL; current++) {601score = StringUtils::similarity(current->_name, strlen(current->_name), name, length);602if (score > max_score) {603max_score = score;604match = current;605}606}607608if (match == NULL) {609return NULL;610}611612if (!(match->is_unlocked() || match->is_unlocker())) {613if (!allow_locked) {614return NULL;615}616}617618if (max_score < VMOptionsFuzzyMatchSimilarity) {619return NULL;620}621622return match;623}624625bool JVMFlag::is_default(JVMFlagsEnum flag) {626return flag_from_enum(flag)->is_default();627}628629bool JVMFlag::is_ergo(JVMFlagsEnum flag) {630return flag_from_enum(flag)->is_ergonomic();631}632633bool JVMFlag::is_cmdline(JVMFlagsEnum flag) {634return flag_from_enum(flag)->is_command_line();635}636637bool JVMFlag::is_jimage_resource(JVMFlagsEnum flag) {638return flag_from_enum(flag)->is_jimage_resource();639}640641void JVMFlag::setOnCmdLine(JVMFlagsEnum flag) {642flag_from_enum(flag)->set_command_line();643}644645extern "C" {646static int compare_flags(const void* void_a, const void* void_b) {647return strcmp((*((JVMFlag**) void_a))->name(), (*((JVMFlag**) void_b))->name());648}649}650651void JVMFlag::printSetFlags(outputStream* out) {652// Print which flags were set on the command line653// note: this method is called before the thread structure is in place654// which means resource allocation cannot be used.655656// The last entry is the null entry.657const size_t length = JVMFlag::numFlags - 1;658659// Sort660JVMFlag** array = NEW_C_HEAP_ARRAY(JVMFlag*, length, mtArguments);661for (size_t i = 0; i < length; i++) {662array[i] = &flagTable[i];663}664qsort(array, length, sizeof(JVMFlag*), compare_flags);665666667for (size_t i = 0; i < length; i++) {668if (array[i]->get_origin() != JVMFlagOrigin::DEFAULT) {669array[i]->print_as_flag(out);670out->print(" ");671}672}673out->cr();674FREE_C_HEAP_ARRAY(JVMFlag*, array);675}676677#ifndef PRODUCT678679void JVMFlag::verify() {680assert(Arguments::check_vm_args_consistency(), "Some flag settings conflict");681}682683#endif // PRODUCT684685#ifdef ASSERT686687void JVMFlag::assert_valid_flag_enum(JVMFlagsEnum i) {688assert(0 <= int(i) && int(i) < NUM_JVMFlagsEnum, "must be");689}690691void JVMFlag::check_all_flag_declarations() {692for (JVMFlag* current = &flagTable[0]; current->_name != NULL; current++) {693int flags = static_cast<int>(current->_flags);694// Backwards compatibility. This will be relaxed/removed in JDK-7123237.695int mask = JVMFlag::KIND_DIAGNOSTIC | JVMFlag::KIND_MANAGEABLE | JVMFlag::KIND_EXPERIMENTAL;696if ((flags & mask) != 0) {697assert((flags & mask) == JVMFlag::KIND_DIAGNOSTIC ||698(flags & mask) == JVMFlag::KIND_MANAGEABLE ||699(flags & mask) == JVMFlag::KIND_EXPERIMENTAL,700"%s can be declared with at most one of "701"DIAGNOSTIC, MANAGEABLE or EXPERIMENTAL", current->_name);702assert((flags & KIND_NOT_PRODUCT) == 0 &&703(flags & KIND_DEVELOP) == 0,704"%s has an optional DIAGNOSTIC, MANAGEABLE or EXPERIMENTAL "705"attribute; it must be declared as a product flag", current->_name);706}707}708}709710#endif // ASSERT711712void JVMFlag::printFlags(outputStream* out, bool withComments, bool printRanges, bool skipDefaults) {713// Print the flags sorted by name714// Note: This method may be called before the thread structure is in place715// which means resource allocation cannot be used. Also, it may be716// called as part of error reporting, so handle native OOMs gracefully.717718// The last entry is the null entry.719const size_t length = JVMFlag::numFlags - 1;720721722if (!printRanges) {723out->print_cr("[Global flags]");724} else {725out->print_cr("[Global flags ranges]");726}727728// Sort729JVMFlag** array = NEW_C_HEAP_ARRAY_RETURN_NULL(JVMFlag*, length, mtArguments);730if (array != NULL) {731for (size_t i = 0; i < length; i++) {732array[i] = &flagTable[i];733}734qsort(array, length, sizeof(JVMFlag*), compare_flags);735736for (size_t i = 0; i < length; i++) {737if (array[i]->is_unlocked() && !(skipDefaults && array[i]->is_default())) {738array[i]->print_on(out, withComments, printRanges);739}740}741FREE_C_HEAP_ARRAY(JVMFlag*, array);742} else {743// OOM? Print unsorted.744for (size_t i = 0; i < length; i++) {745if (flagTable[i].is_unlocked() && !(skipDefaults && flagTable[i].is_default())) {746flagTable[i].print_on(out, withComments, printRanges);747}748}749}750}751752void JVMFlag::printError(bool verbose, const char* msg, ...) {753if (verbose) {754va_list listPointer;755va_start(listPointer, msg);756jio_vfprintf(defaultStream::error_stream(), msg, listPointer);757va_end(listPointer);758}759}760761762