8256508: Improve CompileCommand flag

Reviewed-by: redestad, kvn
This commit is contained in:
Nils Eliasson 2020-11-25 14:20:35 +00:00
parent 7aed9b65d0
commit cfb175dfdf
22 changed files with 796 additions and 482 deletions

View file

@ -3384,7 +3384,7 @@ void LIRGenerator::do_ProfileInvoke(ProfileInvoke* x) {
// Notify the runtime very infrequently only to take care of counter overflows
int freq_log = Tier23InlineeNotifyFreqLog;
double scale;
if (_method->has_option_value("CompileThresholdScaling", scale)) {
if (_method->has_option_value(CompileCommand::CompileThresholdScaling, scale)) {
freq_log = CompilerConfig::scaled_freq_log(freq_log, scale);
}
increment_event_counter_impl(info, x->inlinee(), LIR_OprFact::intConst(InvocationCounter::count_increment), right_n_bits(freq_log), InvocationEntryBci, false, true);
@ -3425,7 +3425,7 @@ void LIRGenerator::increment_event_counter(CodeEmitInfo* info, LIR_Opr step, int
}
// Increment the appropriate invocation/backedge counter and notify the runtime.
double scale;
if (_method->has_option_value("CompileThresholdScaling", scale)) {
if (_method->has_option_value(CompileCommand::CompileThresholdScaling, scale)) {
freq_log = CompilerConfig::scaled_freq_log(freq_log, scale);
}
increment_event_counter_impl(info, info->scope()->method(), step, right_n_bits(freq_log), bci, backedge, true);

View file

@ -1043,17 +1043,17 @@ MethodCounters* ciMethod::ensure_method_counters() {
// ------------------------------------------------------------------
// ciMethod::has_option
//
bool ciMethod::has_option(const char* option) {
bool ciMethod::has_option(enum CompileCommand option) {
check_is_loaded();
VM_ENTRY_MARK;
methodHandle mh(THREAD, get_Method());
return CompilerOracle::has_option_string(mh, option);
return CompilerOracle::has_option(mh, option);
}
// ------------------------------------------------------------------
// ciMethod::has_option_value
//
bool ciMethod::has_option_value(const char* option, double& value) {
bool ciMethod::has_option_value(enum CompileCommand option, double& value) {
check_is_loaded();
VM_ENTRY_MARK;
methodHandle mh(THREAD, get_Method());

View file

@ -293,8 +293,8 @@ class ciMethod : public ciMetadata {
// Find the proper vtable index to invoke this method.
int resolve_vtable_index(ciKlass* caller, ciKlass* receiver);
bool has_option(const char *option);
bool has_option_value(const char* option, double& value);
bool has_option(enum CompileCommand option);
bool has_option_value(enum CompileCommand option, double& value);
bool can_be_compiled();
bool can_be_parsed() const { return _can_be_parsed; }
bool has_compiled_code();

View file

@ -978,15 +978,15 @@ void nmethod::print_nmethod(bool printmethod) {
#if defined(SUPPORT_DATA_STRUCTS)
if (AbstractDisassembler::show_structs()) {
methodHandle mh(Thread::current(), _method);
if (printmethod || PrintDebugInfo || CompilerOracle::has_option_string(mh, "PrintDebugInfo")) {
if (printmethod || PrintDebugInfo || CompilerOracle::has_option(mh, CompileCommand::PrintDebugInfo)) {
print_scopes();
tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
}
if (printmethod || PrintRelocations || CompilerOracle::has_option_string(mh, "PrintRelocations")) {
if (printmethod || PrintRelocations || CompilerOracle::has_option(mh, CompileCommand::PrintRelocations)) {
print_relocations();
tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
}
if (printmethod || PrintDependencies || CompilerOracle::has_option_string(mh, "PrintDependencies")) {
if (printmethod || PrintDependencies || CompilerOracle::has_option(mh, CompileCommand::PrintDependencies)) {
print_dependencies();
tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
}

View file

@ -1585,8 +1585,8 @@ bool CompileBroker::compilation_is_prohibited(const methodHandle& method, int os
// The method may be explicitly excluded by the user.
double scale;
if (excluded || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) {
bool quietly = CompilerOracle::should_exclude_quietly();
if (excluded || (CompilerOracle::has_option_value(method, CompileCommand::CompileThresholdScaling, scale) && scale == 0)) {
bool quietly = CompilerOracle::be_quiet();
if (PrintCompilation && !quietly) {
// This does not happen quietly...
ResourceMark rm;

View file

@ -140,7 +140,7 @@ bool CompilerDirectives::match(const methodHandle& method) {
}
bool CompilerDirectives::add_match(char* str, const char*& error_msg) {
BasicMatcher* bm = BasicMatcher::parse_method_pattern(str, error_msg);
BasicMatcher* bm = BasicMatcher::parse_method_pattern(str, error_msg, false);
if (bm == NULL) {
assert(error_msg != NULL, "Must have error message");
return false;
@ -326,7 +326,7 @@ DirectiveSet* DirectiveSet::compilecommand_compatibility_init(const methodHandle
// Early bail out - checking all options is expensive - we rely on them not being used
// Only set a flag if it has not been modified and value changes.
// Only copy set if a flag needs to be set
if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::has_any_option()) {
if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::has_any_command_set()) {
DirectiveSetPtr set(this);
// All CompileCommands are not equal so this gets a bit verbose
@ -359,8 +359,7 @@ DirectiveSet* DirectiveSet::compilecommand_compatibility_init(const methodHandle
}
// inline and dontinline (including exclude) are implemented in the directiveset accessors
// ignore flags whose cc_flags are X
#define init_default_cc(name, type, dvalue, cc_flag) { type v; if (!_modified[name##Index] && CompilerOracle::has_option_value(method, #cc_flag, v) && v != this->name##Option) { set.cloned()->name##Option = v; } }
#define init_default_cc(name, type, dvalue, cc_flag) { type v; if (!_modified[name##Index] && CompilerOracle::has_option_value(method, CompileCommand::cc_flag, v) && v != this->name##Option) { set.cloned()->name##Option = v; } }
compilerdirectives_common_flags(init_default_cc)
compilerdirectives_c2_flags(init_default_cc)
compilerdirectives_c1_flags(init_default_cc)
@ -370,7 +369,7 @@ DirectiveSet* DirectiveSet::compilecommand_compatibility_init(const methodHandle
bool need_reset = true; // if Control/DisableIntrinsic redefined, only need to reset control_words once
if (!_modified[ControlIntrinsicIndex] &&
CompilerOracle::has_option_value(method, "ControlIntrinsic", option_value)) {
CompilerOracle::has_option_value(method, CompileCommand::ControlIntrinsic, option_value)) {
ControlIntrinsicIter iter(option_value);
if (need_reset) {
@ -390,7 +389,7 @@ DirectiveSet* DirectiveSet::compilecommand_compatibility_init(const methodHandle
if (!_modified[DisableIntrinsicIndex] &&
CompilerOracle::has_option_value(method, "DisableIntrinsic", option_value)) {
CompilerOracle::has_option_value(method, CompileCommand::DisableIntrinsic, option_value)) {
ControlIntrinsicIter iter(option_value, true/*disable_all*/);
if (need_reset) {

View file

@ -34,11 +34,11 @@
// Directives flag name, type, default value, compile command name
#define compilerdirectives_common_flags(cflags) \
cflags(Enable, bool, false, X) \
cflags(Exclude, bool, false, X) \
cflags(Enable, bool, false, Unknown) \
cflags(Exclude, bool, false, Unknown) \
cflags(BreakAtExecute, bool, false, BreakAtExecute) \
cflags(BreakAtCompile, bool, false, BreakAtCompile) \
cflags(Log, bool, LogCompilation, X) \
cflags(Log, bool, LogCompilation, Unknown) \
cflags(PrintAssembly, bool, PrintAssembly, PrintAssembly) \
cflags(PrintInlining, bool, PrintInlining, PrintInlining) \
cflags(PrintNMethods, bool, PrintNMethods, PrintNMethods) \
@ -46,7 +46,7 @@
cflags(ReplayInline, bool, false, ReplayInline) \
cflags(DumpReplay, bool, false, DumpReplay) \
cflags(DumpInline, bool, false, DumpInline) \
cflags(CompilerDirectivesIgnoreCompileCommands, bool, CompilerDirectivesIgnoreCompileCommands, X) \
cflags(CompilerDirectivesIgnoreCompileCommands, bool, CompilerDirectivesIgnoreCompileCommands, Unknown) \
cflags(DisableIntrinsic, ccstrlist, DisableIntrinsic, DisableIntrinsic) \
cflags(ControlIntrinsic, ccstrlist, ControlIntrinsic, ControlIntrinsic) \
cflags(RepeatCompilation, intx, RepeatCompilation, RepeatCompilation)

View file

@ -38,83 +38,72 @@
#include "runtime/jniHandles.hpp"
#include "runtime/os.hpp"
enum OptionType {
IntxType,
UintxType,
BoolType,
CcstrType,
DoubleType,
UnknownType
static const char* optiontype_names[] = {
#define enum_of_types(type, name) name,
OPTION_TYPES(enum_of_types)
#undef enum_of_types
};
const char* optiontype2name(enum OptionType type) {
return optiontype_names[static_cast<int>(type)];
}
static enum OptionType option_types[] = {
#define enum_of_options(option, name, ctype) OptionType::ctype,
COMPILECOMMAND_OPTIONS(enum_of_options)
#undef enum_of_options
};
enum OptionType option2type(enum CompileCommand option) {
return option_types[static_cast<int>(option)];
}
static const char* option_names[] = {
#define enum_of_options(option, name, ctype) name,
COMPILECOMMAND_OPTIONS(enum_of_options)
#undef enum_of_options
};
const char* option2name(enum CompileCommand option) {
return option_names[static_cast<int>(option)];
}
/* Methods to map real type names to OptionType */
template<typename T>
static OptionType get_type_for() {
return UnknownType;
return OptionType::Unknown;
};
template<> OptionType get_type_for<intx>() {
return IntxType;
return OptionType::Intx;
}
template<> OptionType get_type_for<uintx>() {
return UintxType;
return OptionType::Uintx;
}
template<> OptionType get_type_for<bool>() {
return BoolType;
return OptionType::Bool;
}
template<> OptionType get_type_for<ccstr>() {
return CcstrType;
return OptionType::Ccstr;
}
template<> OptionType get_type_for<double>() {
return DoubleType;
return OptionType::Double;
}
// this must parallel the command_names below
enum OracleCommand {
UnknownCommand = -1,
OracleFirstCommand = 0,
BreakCommand = OracleFirstCommand,
PrintCommand,
ExcludeCommand,
InlineCommand,
DontInlineCommand,
CompileOnlyCommand,
LogCommand,
OptionCommand,
QuietCommand,
HelpCommand,
OracleCommandCount
};
// this must parallel the enum OracleCommand
static const char * command_names[] = {
"break",
"print",
"exclude",
"inline",
"dontinline",
"compileonly",
"log",
"option",
"quiet",
"help"
};
class MethodMatcher;
class TypedMethodOptionMatcher;
static BasicMatcher* lists[OracleCommandCount] = { 0, };
static TypedMethodOptionMatcher* option_list = NULL;
static bool any_set = false;
class TypedMethodOptionMatcher : public MethodMatcher {
private:
TypedMethodOptionMatcher* _next;
const char* _option;
enum CompileCommand _option;
OptionType _type;
public:
@ -128,29 +117,36 @@ class TypedMethodOptionMatcher : public MethodMatcher {
TypedMethodOptionMatcher() : MethodMatcher(),
_next(NULL),
_type(UnknownType) {
_option = NULL;
_option(CompileCommand::Unknown),
_type(OptionType::Unknown) {
memset(&_u, 0, sizeof(_u));
}
static TypedMethodOptionMatcher* parse_method_pattern(char*& line, const char*& error_msg);
TypedMethodOptionMatcher* match(const methodHandle& method, const char* opt, OptionType type);
~TypedMethodOptionMatcher();
static TypedMethodOptionMatcher* parse_method_pattern(char*& line, char* errorbuf, const int buf_size);
TypedMethodOptionMatcher* match(const methodHandle &method, enum CompileCommand option, OptionType type);
void init(const char* opt, OptionType type, TypedMethodOptionMatcher* next) {
void init(enum CompileCommand option, OptionType type, TypedMethodOptionMatcher* next) {
_next = next;
_type = type;
_option = os::strdup_check_oom(opt);
_option = option;
}
void init_matcher(Symbol* class_name, Mode class_mode,
Symbol* method_name, Mode method_mode,
Symbol* signature) {
MethodMatcher::init(class_name, class_mode, method_name, method_mode, signature);
}
void set_next(TypedMethodOptionMatcher* next) {_next = next; }
TypedMethodOptionMatcher* next() { return _next; }
OptionType type() { return _type; }
enum CompileCommand option() { return _option; }
template<typename T> T value();
template<typename T> void set_value(T value);
void print();
void print_all();
TypedMethodOptionMatcher* clone();
~TypedMethodOptionMatcher();
};
// A few templated accessors instead of a full template class.
@ -197,21 +193,22 @@ template<> void TypedMethodOptionMatcher::set_value(ccstr value) {
void TypedMethodOptionMatcher::print() {
ttyLocker ttyl;
print_base(tty);
const char* name = option2name(_option);
switch (_type) {
case IntxType:
tty->print_cr(" intx %s = " INTX_FORMAT, _option, value<intx>());
case OptionType::Intx:
tty->print_cr(" intx %s = " INTX_FORMAT, name, value<intx>());
break;
case UintxType:
tty->print_cr(" uintx %s = " UINTX_FORMAT, _option, value<uintx>());
case OptionType::Uintx:
tty->print_cr(" uintx %s = " UINTX_FORMAT, name, value<uintx>());
break;
case BoolType:
tty->print_cr(" bool %s = %s", _option, value<bool>() ? "true" : "false");
case OptionType::Bool:
tty->print_cr(" bool %s = %s", name, value<bool>() ? "true" : "false");
break;
case DoubleType:
tty->print_cr(" double %s = %f", _option, value<double>());
case OptionType::Double:
tty->print_cr(" double %s = %f", name, value<double>());
break;
case CcstrType:
tty->print_cr(" const char* %s = '%s'", _option, value<ccstr>());
case OptionType::Ccstr:
tty->print_cr(" const char* %s = '%s'", name, value<ccstr>());
break;
default:
ShouldNotReachHere();
@ -247,78 +244,90 @@ TypedMethodOptionMatcher* TypedMethodOptionMatcher::clone() {
}
TypedMethodOptionMatcher::~TypedMethodOptionMatcher() {
if (type() == CcstrType) {
if (type() == OptionType::Ccstr) {
ccstr v = value<ccstr>();
os::free((void*)v);
}
if (_option != NULL) {
os::free((void*)_option);
}
}
TypedMethodOptionMatcher* TypedMethodOptionMatcher::parse_method_pattern(char*& line, const char*& error_msg) {
assert(error_msg == NULL, "Dont call here with error_msg already set");
TypedMethodOptionMatcher* TypedMethodOptionMatcher::parse_method_pattern(char*& line, char* errorbuf, const int buf_size) {
assert(*errorbuf == '\0', "Dont call here with error_msg already set");
const char* error_msg = NULL;
TypedMethodOptionMatcher* tom = new TypedMethodOptionMatcher();
MethodMatcher::parse_method_pattern(line, error_msg, tom);
if (error_msg != NULL) {
jio_snprintf(errorbuf, buf_size, error_msg);
delete tom;
return NULL;
}
return tom;
}
TypedMethodOptionMatcher* TypedMethodOptionMatcher::match(const methodHandle& method, const char* opt, OptionType type) {
TypedMethodOptionMatcher* TypedMethodOptionMatcher::match(const methodHandle& method, enum CompileCommand option, OptionType type) {
TypedMethodOptionMatcher* current = this;
while (current != NULL) {
// Fastest compare first.
if (current->type() == type) {
if (strcmp(current->_option, opt) == 0) {
if (current->_option == option) {
if (current->matches(method)) {
return current;
}
}
}
current = current->next();
}
return NULL;
}
template<typename T>
static void add_option_string(TypedMethodOptionMatcher* matcher,
const char* option,
static void register_command(TypedMethodOptionMatcher* matcher,
enum CompileCommand option,
T value) {
assert(matcher != option_list, "No circular lists please");
matcher->init(option, get_type_for<T>(), option_list);
if (option == CompileCommand::Log && !LogCompilation) {
tty->print_cr("Warning: +LogCompilation must be enabled in order for individual methods to be logged with ");
tty->print_cr(" CompileCommand=log,<method pattern>");
}
enum OptionType type = option2type(option);
if (type == OptionType::Ccstrlist) {
type = OptionType::Ccstr; // ccstrlists are stores as ccstr
}
assert(type == get_type_for<T>(), "sanity");
matcher->init(option, type, option_list);
matcher->set_value<T>(value);
option_list = matcher;
if ((option != CompileCommand::DontInline) &&
(option != CompileCommand::Inline) &&
(option != CompileCommand::Log)) {
any_set = true;
return;
}
static bool check_predicate(OracleCommand command, const methodHandle& method) {
return ((lists[command] != NULL) &&
!method.is_null() &&
lists[command]->match(method));
}
static void add_predicate(OracleCommand command, BasicMatcher* bm) {
assert(command != OptionCommand, "must use add_option_string");
if (command == LogCommand && !LogCompilation && lists[LogCommand] == NULL) {
tty->print_cr("Warning: +LogCompilation must be enabled in order for individual methods to be logged.");
}
bm->set_next(lists[command]);
lists[command] = bm;
if ((command != DontInlineCommand) && (command != InlineCommand)) {
any_set = true;
if (!CompilerOracle::be_quiet()) {
// Print out the succesful registration of a comile command
ttyLocker ttyl;
tty->print("CompileCommand: %s ", option2name(option));
matcher->print();
}
return;
}
template<typename T>
bool CompilerOracle::has_option_value(const methodHandle& method, const char* option, T& value) {
bool CompilerOracle::has_option_value(const methodHandle& method, enum CompileCommand option, T& value, bool verify_type) {
enum OptionType type = option2type(option);
if (type == OptionType::Unknown) {
return false; // Can't query options with type Unknown.
}
if (type == OptionType::Ccstrlist) {
type = OptionType::Ccstr; // CCstrList type options are stored as Ccstr
}
if (verify_type) {
if (type != get_type_for<T>()) {
// Whitebox API expects false if option and type doesn't match
return false;
}
} else {
assert(type == get_type_for<T>(), "Value type (%s) must match option %s (%s)",
optiontype2name(get_type_for<T>()),
option2name(option), optiontype2name(option2type(option)));
}
if (option_list != NULL) {
TypedMethodOptionMatcher* m = option_list->match(method, option, get_type_for<T>());
TypedMethodOptionMatcher* m = option_list->match(method, option, type);
if (m != NULL) {
value = m->value<T>();
return true;
@ -327,98 +336,144 @@ bool CompilerOracle::has_option_value(const methodHandle& method, const char* op
return false;
}
bool CompilerOracle::has_any_option() {
static bool check_predicate(enum CompileCommand option, const methodHandle& method) {
bool value = false;
if (CompilerOracle::has_option_value(method, option, value)) {
return value;
}
return false;
}
static bool has_command(enum CompileCommand option) {
TypedMethodOptionMatcher* m = option_list;
while (m != NULL) {
if (m->option() == option) {
return true;
} else {
m = m->next();
}
}
return false;
}
bool CompilerOracle::has_any_command_set() {
return any_set;
}
// Explicit instantiation for all OptionTypes supported.
template bool CompilerOracle::has_option_value<intx>(const methodHandle& method, const char* option, intx& value);
template bool CompilerOracle::has_option_value<uintx>(const methodHandle& method, const char* option, uintx& value);
template bool CompilerOracle::has_option_value<bool>(const methodHandle& method, const char* option, bool& value);
template bool CompilerOracle::has_option_value<ccstr>(const methodHandle& method, const char* option, ccstr& value);
template bool CompilerOracle::has_option_value<double>(const methodHandle& method, const char* option, double& value);
template bool CompilerOracle::has_option_value<intx>(const methodHandle& method, enum CompileCommand option, intx& value, bool verify_type);
template bool CompilerOracle::has_option_value<uintx>(const methodHandle& method, enum CompileCommand option, uintx& value, bool verify_type);
template bool CompilerOracle::has_option_value<bool>(const methodHandle& method, enum CompileCommand option, bool& value, bool verify_type);
template bool CompilerOracle::has_option_value<ccstr>(const methodHandle& method, enum CompileCommand option, ccstr& value, bool verify_type);
template bool CompilerOracle::has_option_value<double>(const methodHandle& method, enum CompileCommand option, double& value, bool verify_type);
bool CompilerOracle::has_option_string(const methodHandle& method, const char* option) {
bool CompilerOracle::has_option(const methodHandle& method, enum CompileCommand option) {
bool value = false;
has_option_value(method, option, value);
return value;
}
bool CompilerOracle::should_exclude(const methodHandle& method) {
if (check_predicate(ExcludeCommand, method)) {
if (check_predicate(CompileCommand::Exclude, method)) {
return true;
}
if (lists[CompileOnlyCommand] != NULL) {
return !lists[CompileOnlyCommand]->match(method);
if (has_command(CompileCommand::CompileOnly)) {
return !check_predicate(CompileCommand::CompileOnly, method);
}
return false;
}
bool CompilerOracle::should_inline(const methodHandle& method) {
return (check_predicate(InlineCommand, method));
return (check_predicate(CompileCommand::Inline, method));
}
bool CompilerOracle::should_not_inline(const methodHandle& method) {
return check_predicate(DontInlineCommand, method) || check_predicate(ExcludeCommand, method);
return check_predicate(CompileCommand::DontInline, method) || check_predicate(CompileCommand::Exclude, method);
}
bool CompilerOracle::should_print(const methodHandle& method) {
return check_predicate(PrintCommand, method);
return check_predicate(CompileCommand::Print, method);
}
bool CompilerOracle::should_print_methods() {
return lists[PrintCommand] != NULL;
return has_command(CompileCommand::Print);
}
bool CompilerOracle::should_log(const methodHandle& method) {
if (!LogCompilation) return false;
if (lists[LogCommand] == NULL) return true; // by default, log all
return (check_predicate(LogCommand, method));
if (!has_command(CompileCommand::Log)) {
return true; // by default, log all
}
return (check_predicate(CompileCommand::Log, method));
}
bool CompilerOracle::should_break_at(const methodHandle& method) {
return check_predicate(BreakCommand, method);
return check_predicate(CompileCommand::Break, method);
}
static OracleCommand parse_command_name(const char * line, int* bytes_read) {
assert(ARRAY_SIZE(command_names) == OracleCommandCount,
"command_names size mismatch");
static enum CompileCommand parse_option_name(const char* line, int* bytes_read, char* errorbuf, int bufsize) {
assert(ARRAY_SIZE(option_names) == static_cast<int>(CompileCommand::Count), "option_names size mismatch");
*bytes_read = 0;
char command[33];
int matches = sscanf(line, "%32[a-z]%n", command, bytes_read);
char option_buf[256];
int matches = sscanf(line, "%255[a-zA-Z0-9]%n", option_buf, bytes_read);
if (matches > 0) {
for (uint i = 0; i < ARRAY_SIZE(command_names); i++) {
if (strcmp(command, command_names[i]) == 0) {
return (OracleCommand)i;
for (uint i = 0; i < ARRAY_SIZE(option_names); i++) {
if (strcasecmp(option_buf, option_names[i]) == 0) {
return static_cast<enum CompileCommand>(i);
}
}
}
return UnknownCommand;
jio_snprintf(errorbuf, bufsize, "Unrecognized option '%s'", option_buf);
return CompileCommand::Unknown;
}
void print_tip() { // CMH Update info
tty->cr();
tty->print_cr("Usage: '-XX:CompileCommand=<option>,<method pattern>' - to set boolean option to true");
tty->print_cr("Usage: '-XX:CompileCommand=<option>,<method pattern>,<value>'");
tty->print_cr("Use: '-XX:CompileCommand=help' for more information and to list all option.");
tty->cr();
}
void print_option(enum CompileCommand option, const char* name, enum OptionType type) {
if (type != OptionType::Unknown) {
tty->print_cr(" %s (%s)", name, optiontype2name(type));
}
}
void print_commands() {
tty->cr();
tty->print_cr("All available options:");
#define enum_of_options(option, name, ctype) print_option(CompileCommand::option, name, OptionType::ctype);
COMPILECOMMAND_OPTIONS(enum_of_options)
#undef enum_of_options
tty->cr();
}
static void usage() {
tty->cr();
tty->print_cr("The CompileCommand option enables the user of the JVM to control specific");
tty->print_cr("behavior of the dynamic compilers. Many commands require a pattern that defines");
tty->print_cr("the set of methods the command shall be applied to. The CompileCommand");
tty->print_cr("option provides the following commands:");
tty->print_cr("behavior of the dynamic compilers.");
tty->cr();
tty->print_cr(" break,<pattern> - debug breakpoint in compiler and in generated code");
tty->print_cr(" print,<pattern> - print assembly");
tty->print_cr(" exclude,<pattern> - don't compile or inline");
tty->print_cr(" inline,<pattern> - always inline");
tty->print_cr(" dontinline,<pattern> - don't inline");
tty->print_cr(" compileonly,<pattern> - compile only");
tty->print_cr(" log,<pattern> - log compilation");
tty->print_cr(" option,<pattern>,<option type>,<option name>,<value>");
tty->print_cr(" - set value of custom option");
tty->print_cr(" option,<pattern>,<bool option name>");
tty->print_cr(" - shorthand for setting boolean flag");
tty->print_cr(" quiet - silence the compile command output");
tty->print_cr(" help - print this text");
tty->print_cr("Compile commands has this general form:");
tty->print_cr("-XX:CompileCommand=<option><method pattern><value>");
tty->print_cr(" Sets <option> to the specified value for methods matching <method pattern>");
tty->print_cr(" All options are typed");
tty->cr();
tty->print_cr("The preferred format for the method matching pattern is:");
tty->print_cr("-XX:CompileCommand=<option><method pattern>");
tty->print_cr(" Sets <option> to true for methods matching <method pattern>");
tty->print_cr(" Only applies to boolean options.");
tty->cr();
tty->print_cr("-XX:CompileCommand=quiet");
tty->print_cr(" Silence the compile command output");
tty->cr();
tty->print_cr("-XX:CompileCommand=help");
tty->print_cr(" Prints this help text");
tty->cr();
print_commands();
tty->cr();
tty->print_cr("Method patterns has the format:");
tty->print_cr(" package/Class.method()");
tty->cr();
tty->print_cr("For backward compatibility this form is also allowed:");
@ -428,7 +483,7 @@ static void usage() {
tty->print_cr(" package/Class.method ()");
tty->cr();
tty->print_cr("The class and method identifier can be used together with leading or");
tty->print_cr("trailing *'s for a small amount of wildcarding:");
tty->print_cr("trailing *'s for wildcard matching:");
tty->print_cr(" *ackage/Clas*.*etho*()");
tty->cr();
tty->print_cr("It is possible to use more than one CompileCommand on the command line:");
@ -447,60 +502,69 @@ static void usage() {
tty->cr();
};
// Scan next flag and value in line, return MethodMatcher object on success, NULL on failure.
// On failure, error_msg contains description for the first error.
// For future extensions: set error_msg on first error.
static void scan_flag_and_value(const char* type, const char* line, int& total_bytes_read,
TypedMethodOptionMatcher* matcher,
char* errorbuf, const int buf_size) {
total_bytes_read = 0;
int skip_whitespace(char* &line) {
// Skip any leading spaces
int whitespace_read = 0;
sscanf(line, "%*[ \t]%n", &whitespace_read);
line += whitespace_read;
return whitespace_read;
}
void skip_comma(char* &line) {
// Skip any leading spaces
if (*line == ',') {
line++;
}
}
static void scan_value(enum OptionType type, char* line, int& total_bytes_read,
TypedMethodOptionMatcher* matcher, enum CompileCommand option, char* errorbuf, const int buf_size) {
int bytes_read = 0;
char flag[256];
// Read flag name.
if (sscanf(line, "%*[ \t]%255[a-zA-Z0-9]%n", flag, &bytes_read) == 1) {
line += bytes_read;
total_bytes_read += bytes_read;
// Read value.
if (strcmp(type, "intx") == 0) {
const char* ccname = option2name(option);
const char* type_str = optiontype2name(type);
int skipped = skip_whitespace(line);
total_bytes_read += skipped;
if (type == OptionType::Intx) {
intx value;
if (sscanf(line, "%*[ \t]" INTX_FORMAT "%n", &value, &bytes_read) == 1) {
if (sscanf(line, "" INTX_FORMAT "%n", &value, &bytes_read) == 1) {
total_bytes_read += bytes_read;
add_option_string(matcher, flag, value);
line += bytes_read;
register_command(matcher, option, value);
return;
} else {
jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s ", flag, type);
jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
}
} else if (strcmp(type, "uintx") == 0) {
} else if (type == OptionType::Uintx) {
uintx value;
if (sscanf(line, "%*[ \t]" UINTX_FORMAT "%n", &value, &bytes_read) == 1) {
if (sscanf(line, "" UINTX_FORMAT "%n", &value, &bytes_read) == 1) {
total_bytes_read += bytes_read;
add_option_string(matcher, flag, value);
line += bytes_read;
register_command(matcher, option, value);
return;
} else {
jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type);
jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
}
} else if (strcmp(type, "ccstr") == 0) {
} else if (type == OptionType::Ccstr) {
ResourceMark rm;
char* value = NEW_RESOURCE_ARRAY(char, strlen(line) + 1);
if (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9]%n", value, &bytes_read) == 1) {
if (sscanf(line, "%255[_a-zA-Z0-9]%n", value, &bytes_read) == 1) {
total_bytes_read += bytes_read;
add_option_string(matcher, flag, (ccstr)value);
line += bytes_read;
register_command(matcher, option, (ccstr) value);
return;
} else {
jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type);
jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
}
} else if (strcmp(type, "ccstrlist") == 0) {
} else if (type == OptionType::Ccstrlist) {
// Accumulates several strings into one. The internal type is ccstr.
ResourceMark rm;
char* value = NEW_RESOURCE_ARRAY(char, strlen(line) + 1);
char* next_value = value;
if (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9+\\-]%n", next_value, &bytes_read) == 1) {
if (sscanf(line, "%255[_a-zA-Z0-9+\\-]%n", next_value, &bytes_read) == 1) {
total_bytes_read += bytes_read;
line += bytes_read;
next_value += bytes_read;
char* end_value = next_value-1;
next_value += bytes_read + 1;
char* end_value = next_value - 1;
while (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9+\\-]%n", next_value, &bytes_read) == 1) {
total_bytes_read += bytes_read;
line += bytes_read;
@ -508,184 +572,236 @@ static void scan_flag_and_value(const char* type, const char* line, int& total_b
next_value += bytes_read;
end_value = next_value-1;
}
add_option_string(matcher, flag, (ccstr)value);
register_command(matcher, option, (ccstr) value);
return;
} else {
jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type);
jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
}
} else if (strcmp(type, "bool") == 0) {
} else if (type == OptionType::Bool) {
char value[256];
if (sscanf(line, "%*[ \t]%255[a-zA-Z]%n", value, &bytes_read) == 1) {
if (strcmp(value, "true") == 0) {
total_bytes_read += bytes_read;
add_option_string(matcher, flag, true);
if (*line == '\0') {
// Short version of a CompileCommand sets a boolean Option to true
// -XXCompileCommand=<Option>,<method pattern>
register_command(matcher, option, true);
return;
} else if (strcmp(value, "false") == 0) {
}
if (sscanf(line, "%255[a-zA-Z]%n", value, &bytes_read) == 1) {
if (strcasecmp(value, "true") == 0) {
total_bytes_read += bytes_read;
add_option_string(matcher, flag, false);
line += bytes_read;
register_command(matcher, option, true);
return;
} else if (strcasecmp(value, "false") == 0) {
total_bytes_read += bytes_read;
line += bytes_read;
register_command(matcher, option, false);
return;
} else {
jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type);
jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
}
} else {
jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type);
jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
}
} else if (strcmp(type, "double") == 0) {
} else if (type == OptionType::Double) {
char buffer[2][256];
// Decimal separator '.' has been replaced with ' ' or '/' earlier,
// so read integer and fraction part of double value separately.
if (sscanf(line, "%*[ \t]%255[0-9]%*[ /\t]%255[0-9]%n", buffer[0], buffer[1], &bytes_read) == 2) {
if (sscanf(line, "%255[0-9]%*[ /\t]%255[0-9]%n", buffer[0], buffer[1], &bytes_read) == 2) {
char value[512] = "";
jio_snprintf(value, sizeof(value), "%s.%s", buffer[0], buffer[1]);
total_bytes_read += bytes_read;
add_option_string(matcher, flag, atof(value));
line += bytes_read;
register_command(matcher, option, atof(value));
return;
} else {
jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type);
jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
}
} else {
jio_snprintf(errorbuf, buf_size, " Type %s not supported ", type);
jio_snprintf(errorbuf, buf_size, "Type '%s' not supported ", type_str);
}
}
// Scan next option and value in line, return MethodMatcher object on success, NULL on failure.
// On failure, error_msg contains description for the first error.
// For future extensions: set error_msg on first error.
static void scan_option_and_value(enum OptionType type, char* line, int& total_bytes_read,
TypedMethodOptionMatcher* matcher,
char* errorbuf, const int buf_size) {
total_bytes_read = 0;
int bytes_read = 0;
char option_buf[256];
// Read option name.
if (sscanf(line, "%*[ \t]%255[a-zA-Z0-9]%n", option_buf, &bytes_read) == 1) {
line += bytes_read;
total_bytes_read += bytes_read;
int bytes_read2 = 0;
total_bytes_read += skip_whitespace(line);
enum CompileCommand option = parse_option_name(option_buf, &bytes_read2, errorbuf, buf_size);
if (option == CompileCommand::Unknown) {
assert(*errorbuf != '\0', "error must have been set");
return;
}
enum OptionType optiontype = option2type(option);
if (option2type(option) != type) {
const char* optiontype_name = optiontype2name(optiontype);
const char* type_name = optiontype2name(type);
jio_snprintf(errorbuf, buf_size, "Option '%s' with type '%s' doesn't match supplied type '%s'", option_buf, optiontype_name, type_name);
return;
}
scan_value(type, line, total_bytes_read, matcher, option, errorbuf, buf_size);
} else {
jio_snprintf(errorbuf, buf_size, " Flag name for type %s should be alphanumeric ", type);
const char* type_str = optiontype2name(type);
jio_snprintf(errorbuf, buf_size, "Option name for type '%s' should be alphanumeric ", type_str);
}
return;
}
int skip_whitespace(char* line) {
// Skip any leading spaces
int whitespace_read = 0;
sscanf(line, "%*[ \t]%n", &whitespace_read);
return whitespace_read;
}
void CompilerOracle::print_parse_error(const char*& error_msg, char* original_line) {
assert(error_msg != NULL, "Must have error_message");
void CompilerOracle::print_parse_error(char* error_msg, char* original_line) {
assert(*error_msg != '\0', "Must have error_message");
ttyLocker ttyl;
tty->print_cr("CompileCommand: An error occurred during parsing");
tty->print_cr("Line: %s", original_line);
tty->print_cr("Error: %s", error_msg);
CompilerOracle::print_tip();
tty->print_cr("Line: '%s'", original_line);
print_tip();
}
enum OptionType parse_option_type(const char* type_str) {
for (uint i = 0; i < ARRAY_SIZE(optiontype_names); i++) {
if (strcasecmp(type_str, optiontype_names[i]) == 0) {
return static_cast<enum OptionType>(i);
}
}
return OptionType::Unknown;
}
class LineCopy : StackObj {
const char* _copy;
public:
LineCopy(char* line) {
_copy = os::strdup(line, mtInternal);
}
~LineCopy() {
os::free((void*)_copy);
}
char* get() {
return (char*)_copy;
}
};
void CompilerOracle::parse_from_line(char* line) {
if (line[0] == '\0') return;
if (line[0] == '#') return;
char* original_line = line;
LineCopy original(line);
int bytes_read;
OracleCommand command = parse_command_name(line, &bytes_read);
char error_buf[1024] = {0};
enum CompileCommand option = parse_option_name(line, &bytes_read, error_buf, sizeof(error_buf));
line += bytes_read;
ResourceMark rm;
if (command == UnknownCommand) {
ttyLocker ttyl;
tty->print_cr("CompileCommand: unrecognized command");
tty->print_cr(" \"%s\"", original_line);
CompilerOracle::print_tip();
if (option == CompileCommand::Unknown) {
print_parse_error(error_buf, original.get());
return;
}
if (command == QuietCommand) {
if (option == CompileCommand::Quiet) {
_quiet = true;
return;
}
if (command == HelpCommand) {
if (option == CompileCommand::Help) {
usage();
return;
}
const char* error_msg = NULL;
if (command == OptionCommand) {
if (option == CompileCommand::Option) {
// Look for trailing options.
//
// Two types of trailing options are
// supported:
//
// (1) CompileCommand=option,Klass::method,flag
// (2) CompileCommand=option,Klass::method,type,flag,value
// (1) CompileCommand=option,Klass::method,option
// (2) CompileCommand=option,Klass::method,type,option,value
//
// Type (1) is used to enable a boolean flag for a method.
// Type (1) is used to enable a boolean option for a method.
//
// Type (2) is used to support options with a value. Values can have the
// the following types: intx, uintx, bool, ccstr, ccstrlist, and double.
//
// For future extensions: extend scan_flag_and_value()
char option[256]; // stores flag for Type (1) and type of Type (2)
line++; // skip the ','
TypedMethodOptionMatcher* archetype = TypedMethodOptionMatcher::parse_method_pattern(line, error_msg);
char option_type[256]; // stores option for Type (1) and type of Type (2)
skip_comma(line);
TypedMethodOptionMatcher* archetype = TypedMethodOptionMatcher::parse_method_pattern(line, error_buf, sizeof(error_buf));
if (archetype == NULL) {
assert(error_msg != NULL, "Must have error_message");
print_parse_error(error_msg, original_line);
print_parse_error(error_buf, original.get());
return;
}
line += skip_whitespace(line);
skip_whitespace(line);
// This is unnecessarily complex. Should retire multi-option lines and skip while loop
while (sscanf(line, "%255[a-zA-Z0-9]%n", option, &bytes_read) == 1) {
while (sscanf(line, "%255[a-zA-Z0-9]%n", option_type, &bytes_read) == 1) {
line += bytes_read;
// typed_matcher is used as a blueprint for each option, deleted at the end
TypedMethodOptionMatcher* typed_matcher = archetype->clone();
if (strcmp(option, "intx") == 0
|| strcmp(option, "uintx") == 0
|| strcmp(option, "bool") == 0
|| strcmp(option, "ccstr") == 0
|| strcmp(option, "ccstrlist") == 0
|| strcmp(option, "double") == 0
) {
char errorbuf[1024] = {0};
// Type (2) option: parse flag name and value.
scan_flag_and_value(option, line, bytes_read, typed_matcher, errorbuf, sizeof(errorbuf));
if (*errorbuf != '\0') {
error_msg = errorbuf;
print_parse_error(error_msg, original_line);
enum OptionType type = parse_option_type(option_type);
if (type != OptionType::Unknown) {
// Type (2) option: parse option name and value.
scan_option_and_value(type, line, bytes_read, typed_matcher, error_buf, sizeof(error_buf));
if (*error_buf != '\0') {
print_parse_error(error_buf, original.get());
return;
}
line += bytes_read;
} else {
// Type (1) option
add_option_string(typed_matcher, option, true);
}
if (typed_matcher != NULL && !_quiet) {
// Print out the last match added
assert(error_msg == NULL, "No error here");
ttyLocker ttyl;
tty->print("CompileCommand: %s ", command_names[command]);
typed_matcher->print();
}
line += skip_whitespace(line);
} // while(
delete archetype;
} else { // not an OptionCommand)
assert(error_msg == NULL, "Don't call here with error_msg already set");
BasicMatcher* matcher = BasicMatcher::parse_method_pattern(line, error_msg);
if (error_msg != NULL) {
assert(matcher == NULL, "consistency");
print_parse_error(error_msg, original_line);
// Type (1) option - option_type contains the option name -> bool value = true is implied
int bytes_read;
enum CompileCommand option = parse_option_name(option_type, &bytes_read, error_buf, sizeof(error_buf));
if (option == CompileCommand::Unknown) {
print_parse_error(error_buf, original.get());
return;
}
add_predicate(command, matcher);
if (!_quiet) {
ttyLocker ttyl;
tty->print("CompileCommand: %s ", command_names[command]);
matcher->print(tty);
tty->cr();
register_command(typed_matcher, option, true);
}
assert(typed_matcher != NULL, "sanity");
assert(*error_buf == '\0', "No error here");
skip_whitespace(line);
} // while(
delete archetype;
} else { // not an OptionCommand
// Command has the following form:
// CompileCommand=<option>,<method pattern><value>
// CompileCommand=<option>,<method pattern> (implies option is bool and value is true)
assert(*error_buf == '\0', "Don't call here with error_buf already set");
enum OptionType type = option2type(option);
int bytes_read = 0;
skip_comma(line);
TypedMethodOptionMatcher* matcher = TypedMethodOptionMatcher::parse_method_pattern(line, error_buf, sizeof(error_buf));
if (matcher == NULL) {
print_parse_error(error_buf, original.get());
return;
}
skip_whitespace(line);
if (*line == '\0') {
// if this is a bool option this implies true
if (option2type(option) == OptionType::Bool) {
register_command(matcher, option, true);
return;
} else {
jio_snprintf(error_buf, sizeof(error_buf), " Option '%s' is not followed by a value", option2name(option));
print_parse_error(error_buf, original.get());
return;
}
}
}
void CompilerOracle::print_tip() {
tty->cr();
tty->print_cr("Usage: '-XX:CompileCommand=command,\"package/Class.method()\"'");
tty->print_cr("Use: '-XX:CompileCommand=help' for more information.");
tty->cr();
scan_value(type, line, bytes_read, matcher, option, error_buf, sizeof(error_buf));
if (*error_buf != '\0') {
print_parse_error(error_buf, original.get());
return;
}
assert(matcher != NULL, "consistency");
}
}
static const char* default_cc_file = ".hotspot_compiler";
@ -760,7 +876,7 @@ void compilerOracle_init() {
default_cc_file, default_cc_file);
}
}
if (lists[PrintCommand] != NULL) {
if (has_command(CompileCommand::Print)) {
if (PrintAssembly) {
warning("CompileCommand and/or %s file contains 'print' commands, but PrintAssembly is also enabled", default_cc_file);
} else if (FLAG_IS_DEFAULT(DebugNonSafepoints)) {
@ -770,8 +886,7 @@ void compilerOracle_init() {
}
}
void CompilerOracle::parse_compile_only(char * line) {
void CompilerOracle::parse_compile_only(char* line) {
int i;
char name[1024];
const char* className = NULL;
@ -841,12 +956,12 @@ void CompilerOracle::parse_compile_only(char * line) {
Symbol* m_name = SymbolTable::new_symbol(methodName);
Symbol* signature = NULL;
BasicMatcher* bm = new BasicMatcher();
bm->init(c_name, c_match, m_name, m_match, signature);
add_predicate(CompileOnlyCommand, bm);
TypedMethodOptionMatcher* tom = new TypedMethodOptionMatcher();
tom->init_matcher(c_name, c_match, m_name, m_match, signature);
register_command(tom, CompileCommand::CompileOnly, true);
if (PrintVMOptions) {
tty->print("CompileOnly: compileonly ");
lists[CompileOnlyCommand]->print_all(tty);
tom->print();
}
className = NULL;
@ -856,3 +971,9 @@ void CompilerOracle::parse_compile_only(char * line) {
line = *line == '\0' ? line : line + 1;
}
}
enum CompileCommand CompilerOracle::string_to_option(const char* name) {
int bytes_read = 0;
char errorbuf[1024] = {0};
return parse_option_name(name, &bytes_read, errorbuf, sizeof(errorbuf));
}

View file

@ -30,17 +30,91 @@
class methodHandle;
// CompilerOracle is an interface for turning on and off compilation
// for some methods
// OPTION_TYPES: type, name
#define OPTION_TYPES(type) \
type(Intx, "intx") \
type(Uintx, "uintx") \
type(Bool, "bool") \
type(Ccstr, "ccstr") \
type(Ccstrlist, "ccstrlist") \
type(Double, "double")
// COMPILECOMMAND_OPTIONS: option, name, variant, type
#define COMPILECOMMAND_OPTIONS(option) \
option(Help, "help", Unknown) \
option(Quiet, "quiet", Unknown) \
option(Log, "log", Bool) \
option(Print, "print", Bool) \
option(Inline, "inline", Bool) \
option(DontInline, "dontinline", Bool) \
option(CompileOnly, "compileonly", Bool)\
option(Exclude, "exclude", Bool) \
option(Break, "break", Bool) \
option(BreakAtExecute, "BreakAtExecute", Bool) \
option(BreakAtCompile, "BreakAtCompile", Bool) \
option(PrintAssembly, "PrintAssembly", Bool) \
option(PrintInlining, "PrintInlining", Bool) \
option(PrintIntrinsics, "PrintIntrinsics", Bool) \
option(PrintNMethods, "PrintNMethods", Bool) \
option(PrintOptoAssembly, "PrintOptoAssembly", Bool) \
option(PrintDebugInfo, "PrintDebugInfo", Bool) \
option(PrintRelocations, "PrintRelocations", Bool) \
option(PrintDependencies, "PrintDependencies", Bool) \
option(BackgroundCompilation, "BackgroundCompilation", Bool) \
option(RepeatCompilation, "RepeatCompilation", Intx) \
option(ReplayInline, "ReplayInline", Bool) \
option(DumpReplay, "DumpReplay", Bool) \
option(DumpInline, "DumpInline", Bool) \
option(CompileThresholdScaling, "CompileThresholdScaling", Double) \
option(ControlIntrinsic, "ControlIntrinsic", Ccstrlist) \
option(DisableIntrinsic, "DisableIntrinsic", Ccstrlist) \
option(NoRTMLockEliding, "NoRTMLockEliding", Bool) \
option(UseRTMLockEliding, "UseRTMLockEliding", Bool) \
option(BlockLayoutByFrequency, "BlockLayoutByFrequency", Bool) \
option(TraceOptoPipelining, "TraceOptoPipelining", Bool) \
option(TraceOptoOutput, "TraceOptoOutput", Bool) \
option(TraceSpilling, "TraceSpilling", Bool) \
option(PrintIdeal, "PrintIdeal", Bool) \
option(IGVPrintLevel, "IGVPrintLevel", Intx) \
option(Vectorize, "Vectorize", Bool) \
option(VectorizeDebug, "VectorizeDebug", Uintx) \
option(CloneMapDebug, "CloneMapDebug", Bool) \
option(MaxNodeLimit, "MaxNodeLimit", Intx) \
NOT_PRODUCT(option(TestOptionInt, "TestOptionInt", Intx)) \
NOT_PRODUCT(option(TestOptionUint, "TestOptionUint", Uintx)) \
NOT_PRODUCT(option(TestOptionBool, "TestOptionBool", Bool)) \
NOT_PRODUCT(option(TestOptionBool2, "TestOptionBool2", Bool)) \
NOT_PRODUCT(option(TestOptionStr, "TestOptionStr", Ccstr)) \
NOT_PRODUCT(option(TestOptionList, "TestOptionList", Ccstrlist)) \
NOT_PRODUCT(option(TestOptionDouble, "TestOptionDouble", Double)) \
option(Option, "option", Unknown) \
option(Unknown, "unknown", Unknown)
enum class CompileCommand {
#define enum_of_options(option, name, ctype) option,
COMPILECOMMAND_OPTIONS(enum_of_options)
#undef enum_of_options
Count
};
enum class OptionType {
#define enum_of_types(type, name) type,
OPTION_TYPES(enum_of_types)
#undef enum_of_types
Unknown
};
class CompilerOracle : AllStatic {
private:
static bool _quiet;
static void print_tip();
static void print_parse_error(const char*& error_msg, char* original_line);
static void print_parse_error(char* error_msg, char* original_line);
static void print_command(enum CompileCommand option, const char* name, enum OptionType type);
public:
// True if the command file has been specified or is implicit
static bool has_command_file();
@ -49,7 +123,7 @@ class CompilerOracle : AllStatic {
// Tells whether we to exclude compilation of method
static bool should_exclude(const methodHandle& method);
static bool should_exclude_quietly() { return _quiet; }
static bool be_quiet() { return _quiet; }
// Tells whether we want to inline this method
static bool should_inline(const methodHandle& method);
@ -66,25 +140,28 @@ class CompilerOracle : AllStatic {
// Tells whether to break when compiling method
static bool should_break_at(const methodHandle& method);
// Check to see if this method has option set for it
static bool has_option_string(const methodHandle& method, const char * option);
// Tells whether there are any methods to print for print_method_statistics()
static bool should_print_methods();
// A wrapper for checking bool options
static bool has_option(const methodHandle& method, enum CompileCommand option);
// Check if method has option and value set. If yes, overwrite value and return true,
// otherwise leave value unchanged and return false.
template<typename T>
static bool has_option_value(const methodHandle& method, const char* option, T& value);
// Fast check if there is any option available that compile control needs to know about
static bool has_any_option();
static bool has_option_value(const methodHandle& method, enum CompileCommand option, T& value, bool verfiy_type = false);
// Reads from string instead of file
static void parse_from_string(const char* command_string, void (*parser)(char*));
static void parse_from_string(const char* option_string, void (*parser)(char*));
static void parse_from_line(char* line);
static void parse_compile_only(char * line);
static void parse_compile_only(char* line);
// Tells whether there are any methods to print for print_method_statistics()
static bool should_print_methods();
// Fast check if there is any option set that compile control needs to know about
static bool has_any_command_set();
// convert a string to a proper compilecommand option - used from whitebox.
// returns CompileCommand::Unknown on names not matching an option.
static enum CompileCommand string_to_option(const char* name);
};
#endif // SHARE_COMPILER_COMPILERORACLE_HPP

View file

@ -259,6 +259,10 @@ void MethodMatcher::parse_method_pattern(char*& line, const char*& error_msg, Me
}
skip_leading_spaces(line, &total_bytes_read);
if (*line == '\0') {
error_msg = "Method pattern missing from command";
return;
}
if (2 == sscanf(line, "%255" RANGESLASH "%*[ ]" "%255" RANGE0 "%n", class_name, method_name, &bytes_read)) {
c_match = check_mode(class_name, error_msg);
@ -352,15 +356,15 @@ void MethodMatcher::print_base(outputStream* st) {
}
}
BasicMatcher* BasicMatcher::parse_method_pattern(char* line, const char*& error_msg) {
BasicMatcher* BasicMatcher::parse_method_pattern(char* line, const char*& error_msg, bool expect_trailing_chars) {
assert(error_msg == NULL, "Don't call here with error_msg already set");
BasicMatcher* bm = new BasicMatcher();
BasicMatcher *bm = new BasicMatcher();
MethodMatcher::parse_method_pattern(line, error_msg, bm);
if (error_msg != NULL) {
delete bm;
return NULL;
}
if (!expect_trailing_chars) {
// check for bad trailing characters
int bytes_read = 0;
sscanf(line, "%*[ \t]%n", &bytes_read);
@ -369,6 +373,7 @@ BasicMatcher* BasicMatcher::parse_method_pattern(char* line, const char*& error_
delete bm;
return NULL;
}
}
return bm;
}
@ -426,8 +431,7 @@ InlineMatcher* InlineMatcher::parse_inline_pattern(char* str, const char*& error
}
str++;
int bytes_read = 0;
assert(error_msg== NULL, "error_msg must not be set yet");
assert(error_msg == NULL, "error_msg must not be set yet");
InlineMatcher* im = InlineMatcher::parse_method_pattern(str, error_msg);
if (im == NULL) {
assert(error_msg != NULL, "Must have error message");

View file

@ -81,7 +81,7 @@ public:
_next(next) {
}
static BasicMatcher* parse_method_pattern(char* line, const char*& error_msg);
static BasicMatcher* parse_method_pattern(char* line, const char*& error_msg, bool expect_trailing_chars);
bool match(const methodHandle& method);
void set_next(BasicMatcher* next) { _next = next; }
BasicMatcher* next() { return _next; }

View file

@ -47,7 +47,7 @@
bool TieredThresholdPolicy::call_predicate_helper(const methodHandle& method, CompLevel cur_level, int i, int b, double scale) {
double threshold_scaling;
if (CompilerOracle::has_option_value(method, "CompileThresholdScaling", threshold_scaling)) {
if (CompilerOracle::has_option_value(method, CompileCommand::CompileThresholdScaling, threshold_scaling)) {
scale *= threshold_scaling;
}
switch(cur_level) {
@ -78,7 +78,7 @@ bool TieredThresholdPolicy::call_predicate_helper(const methodHandle& method, Co
bool TieredThresholdPolicy::loop_predicate_helper(const methodHandle& method, CompLevel cur_level, int i, int b, double scale) {
double threshold_scaling;
if (CompilerOracle::has_option_value(method, "CompileThresholdScaling", threshold_scaling)) {
if (CompilerOracle::has_option_value(method, CompileCommand::CompileThresholdScaling, threshold_scaling)) {
scale *= threshold_scaling;
}
switch(cur_level) {

View file

@ -94,7 +94,7 @@ class MethodCounters : public Metadata {
// Set per-method thresholds.
double scale = 1.0;
CompilerOracle::has_option_value(mh, "CompileThresholdScaling", scale);
CompilerOracle::has_option_value(mh, CompileCommand::CompileThresholdScaling, scale);
int compile_threshold = CompilerConfig::scaled_compile_threshold(CompileThreshold, scale);
_interpreter_invocation_limit = compile_threshold << InvocationCounter::count_shift;

View file

@ -1289,7 +1289,7 @@ void MethodData::init() {
// Set per-method invoke- and backedge mask.
double scale = 1.0;
methodHandle mh(Thread::current(), _method);
CompilerOracle::has_option_value(mh, "CompileThresholdScaling", scale);
CompilerOracle::has_option_value(mh, CompileCommand::CompileThresholdScaling, scale);
_invoke_mask = right_n_bits(CompilerConfig::scaled_freq_log(Tier0InvokeNotifyFreqLog, scale)) << InvocationCounter::count_shift;
_backedge_mask = right_n_bits(CompilerConfig::scaled_freq_log(Tier0BackedgeNotifyFreqLog, scale)) << InvocationCounter::count_shift;
@ -1306,8 +1306,8 @@ void MethodData::init() {
#if INCLUDE_RTM_OPT
_rtm_state = NoRTM; // No RTM lock eliding by default
if (UseRTMLocking &&
!CompilerOracle::has_option_string(mh, "NoRTMLockEliding")) {
if (CompilerOracle::has_option_string(mh, "UseRTMLockEliding") || !UseRTMDeopt) {
!CompilerOracle::has_option(mh, CompileCommand::NoRTMLockEliding)) {
if (CompilerOracle::has_option(mh, CompileCommand::UseRTMLockEliding) || !UseRTMDeopt) {
// Generate RTM lock eliding code without abort ratio calculation code.
_rtm_state = UseRTM;
} else if (UseRTMDeopt) {

View file

@ -953,10 +953,10 @@ void Compile::Init(int aliaslevel) {
#if INCLUDE_RTM_OPT
if (UseRTMLocking && has_method() && (method()->method_data_or_null() != NULL)) {
int rtm_state = method()->method_data()->rtm_state();
if (method_has_option("NoRTMLockEliding") || ((rtm_state & NoRTM) != 0)) {
if (method_has_option(CompileCommand::NoRTMLockEliding) || ((rtm_state & NoRTM) != 0)) {
// Don't generate RTM lock eliding code.
set_rtm_state(NoRTM);
} else if (method_has_option("UseRTMLockEliding") || ((rtm_state & UseRTM) != 0) || !UseRTMDeopt) {
} else if (method_has_option(CompileCommand::UseRTMLockEliding) || ((rtm_state & UseRTM) != 0) || !UseRTMDeopt) {
// Generate RTM lock eliding code without abort ratio calculation code.
set_rtm_state(UseRTM);
} else if (UseRTMDeopt) {

View file

@ -594,7 +594,7 @@ class Compile : public Phase {
void set_clinit_barrier_on_entry(bool z) { _clinit_barrier_on_entry = z; }
// check the CompilerOracle for special behaviours for this compile
bool method_has_option(const char * option) {
bool method_has_option(enum CompileCommand option) {
return method() != NULL && method()->has_option(option);
}

View file

@ -1056,7 +1056,7 @@ WB_ENTRY(jint, WB_MatchesMethod(JNIEnv* env, jobject o, jobject method, jstring
const char* error_msg = NULL;
BasicMatcher* m = BasicMatcher::parse_method_pattern(method_str, error_msg);
BasicMatcher* m = BasicMatcher::parse_method_pattern(method_str, error_msg, false);
if (m == NULL) {
assert(error_msg != NULL, "Must have error_msg");
tty->print_cr("Got error: %s", error_msg);
@ -1810,9 +1810,12 @@ static bool GetMethodOption(JavaThread* thread, JNIEnv* env, jobject method, jst
ThreadToNativeFromVM ttnfv(thread);
const char* flag_name = env->GetStringUTFChars(name, NULL);
CHECK_JNI_EXCEPTION_(env, false);
bool result = CompilerOracle::has_option_value(mh, flag_name, *value);
enum CompileCommand option = CompilerOracle::string_to_option(flag_name);
env->ReleaseStringUTFChars(name, flag_name);
return result;
if (option == CompileCommand::Unknown) {
return false;
}
return CompilerOracle::has_option_value(mh, option, *value, true /* verify type*/);
}
WB_ENTRY(jobject, WB_GetMethodBooleaneOption(JNIEnv* env, jobject wb, jobject method, jstring name))

View file

@ -28,6 +28,7 @@
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* @requires vm.debug == true
* @run driver compiler.oracle.CheckCompileCommandOption
*/
@ -43,12 +44,12 @@ public class CheckCompileCommandOption {
// Currently, two types of trailing options can be used with
// -XX:CompileCommand=option
//
// (1) CompileCommand=option,Klass::method,flag
// (2) CompileCommand=option,Klass::method,type,flag,value
// (1) CompileCommand=option,Klass::method,option
// (2) CompileCommand=option,Klass::method,type,option,value
//
// Type (1) is used to enable a boolean flag for a method.
// Type (1) is used to enable a boolean option for a method.
//
// Type (2) is used to support flags with a value. Values can
// Type (2) is used to support options with a value. Values can
// have the the following types: intx, uintx, bool, ccstr,
// ccstrlist, and double.
@ -65,85 +66,145 @@ public class CheckCompileCommandOption {
private static final String[][] FILE_EXPECTED_OUTPUT = {
{
"CompileCommand: option com/oracle/Test.test bool MyBoolOption1 = true",
"CompileCommand: option com/oracle/Test.test bool MyBoolOption2 = true",
"CompileCommand: option com/oracle/Test.test bool MyBoolOption3 = true",
"CompileCommand: option com/oracle/Test.test bool MyBoolOption5 = true",
"CompileCommand: option com/oracle/Test.test bool MyBoolOption6 = true",
"CompileCommand: option com/oracle/Test.test bool MyBoolOption7 = true",
"CompileCommand: option com/oracle/Test.test bool MyBoolOption8 = true",
"CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption9 = true",
"CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption10 = true",
"CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption11 = true",
"CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption13 = true",
"CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption14 = true",
"CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption15 = true",
"CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption16 = true"
"com/oracle/Test.test1 bool TestOptionBool = true",
"com/oracle/Test.test2 bool TestOptionBool = true",
"com/oracle/Test.test3 bool TestOptionBool = true",
"com/oracle/Test.test4 bool TestOptionBool = true",
"com/oracle/Test.test4 bool TestOptionBool2 = true",
"com/oracle/Test.test5 bool TestOptionBool = true",
"com/oracle/Test.test5 bool TestOptionBool2 = true",
"com/oracle/Test.test6(I) bool TestOptionBool = true",
"com/oracle/Test.test7(I) bool TestOptionBool = true",
"com/oracle/Test.test8(I) bool TestOptionBool = true",
"com/oracle/Test.test9(I) bool TestOptionBool = true",
"com/oracle/Test.test9(I) bool TestOptionBool2 = true",
"com/oracle/Test.test10(I) bool TestOptionBool = true",
"com/oracle/Test.test10(I) bool TestOptionBool2 = true"
},
{
"CompileCommand: option Test.test const char* MyListOption = '_foo _bar'",
"CompileCommand: option Test.test const char* MyStrOption = '_foo'",
"CompileCommand: option Test.test bool MyBoolOption = false",
"CompileCommand: option Test.test intx MyIntxOption = -1",
"CompileCommand: option Test.test uintx MyUintxOption = 1",
"CompileCommand: option Test.test bool MyFlag = true",
"CompileCommand: option Test.test double MyDoubleOption = 1.123000"
"Test.test const char* TestOptionList = '_foo _bar'",
"Test.test const char* TestOptionStr = '_foo'",
"Test.test bool TestOptionBool = false",
"Test.test intx TestOptionInt = -1",
"Test.test uintx TestOptionUint = 1",
"Test.test bool TestOptionBool2 = true",
"Test.test double TestOptionDouble = 1.123000"
}
};
private static final String[][] TYPE_1_ARGUMENTS = {
{
"-XX:CompileCommand=option,com/oracle/Test.test,MyBoolOption1",
"-XX:CompileCommand=option,com/oracle/Test,test,MyBoolOption2",
"-XX:CompileCommand=option,com.oracle.Test::test,MyBoolOption3",
"-XX:CompileCommand=option,com/oracle/Test.test,MyBoolOption5,MyBoolOption6",
"-XX:CompileCommand=option,com/oracle/Test,test,MyBoolOption7,MyBoolOption8",
"-XX:CompileCommand=option,com/oracle/Test.test,TestOptionBool",
"-XX:CompileCommand=option,com/oracle/Test,test,TestOptionBool2",
"-XX:CompileCommand=option,com/oracle/Test.test2,TestOptionBool2,TestOptionBool",
"-version"
}
};
private static final String[][] TYPE_1_EXPECTED_OUTPUTS = {
{
"CompileCommand: option com/oracle/Test.test bool MyBoolOption1 = true",
"CompileCommand: option com/oracle/Test.test bool MyBoolOption2 = true",
"CompileCommand: option com/oracle/Test.test bool MyBoolOption3 = true",
"CompileCommand: option com/oracle/Test.test bool MyBoolOption5 = true",
"CompileCommand: option com/oracle/Test.test bool MyBoolOption6 = true",
"CompileCommand: option com/oracle/Test.test bool MyBoolOption7 = true",
"CompileCommand: option com/oracle/Test.test bool MyBoolOption8 = true"
"com/oracle/Test.test bool TestOptionBool = true",
"com/oracle/Test.test bool TestOptionBool2 = true",
"com/oracle/Test.test2 bool TestOptionBool = true",
"com/oracle/Test.test2 bool TestOptionBool2 = true",
}
};
private static final String[][] TYPE_2_ARGUMENTS = {
{
"-XX:CompileCommand=option,Test::test,ccstrlist,MyListOption,_foo,_bar",
"-XX:CompileCommand=option,Test::test,ccstr,MyStrOption,_foo",
"-XX:CompileCommand=option,Test::test,bool,MyBoolOption,false",
"-XX:CompileCommand=option,Test::test,intx,MyIntxOption,-1",
"-XX:CompileCommand=option,Test::test,uintx,MyUintxOption,1",
"-XX:CompileCommand=option,Test::test,MyFlag",
"-XX:CompileCommand=option,Test::test,double,MyDoubleOption1,1.123",
"-XX:CompileCommand=option,Test.test,double,MyDoubleOption2,1.123",
"-XX:CompileCommand=option,Test::test,bool,MyBoolOptionX,false,intx,MyIntxOptionX,-1,uintx,MyUintxOptionX,1,MyFlagX,double,MyDoubleOptionX,1.123",
"-XX:CompileCommand=option,Test::test,ccstrlist,TestOptionList,_foo,_bar",
"-XX:CompileCommand=option,Test::test,ccstr,TestOptionStr,_foo",
"-XX:CompileCommand=option,Test::test,bool,TestOptionBool,false",
"-XX:CompileCommand=option,Test::test,intx,TestOptionInt,-1",
"-XX:CompileCommand=option,Test::test,uintx,TestOptionUint,1",
"-XX:CompileCommand=option,Test::test,TestOptionBool2",
"-XX:CompileCommand=option,Test::test,double,TestOptionDouble,1.123",
"-XX:CompileCommand=option,Test.test2,double,TestOptionDouble,1.123",
"-version"
}
};
private static final String[][] TYPE_2_EXPECTED_OUTPUTS = {
{
"CompileCommand: option Test.test const char* MyListOption = '_foo _bar'",
"CompileCommand: option Test.test const char* MyStrOption = '_foo'",
"CompileCommand: option Test.test bool MyBoolOption = false",
"CompileCommand: option Test.test intx MyIntxOption = -1",
"CompileCommand: option Test.test uintx MyUintxOption = 1",
"CompileCommand: option Test.test bool MyFlag = true",
"CompileCommand: option Test.test double MyDoubleOption1 = 1.123000",
"CompileCommand: option Test.test double MyDoubleOption2 = 1.123000",
"CompileCommand: option Test.test bool MyBoolOptionX = false",
"CompileCommand: option Test.test intx MyIntxOptionX = -1",
"CompileCommand: option Test.test uintx MyUintxOptionX = 1",
"CompileCommand: option Test.test bool MyFlagX = true",
"CompileCommand: option Test.test double MyDoubleOptionX = 1.123000",
"Test.test const char* TestOptionList = '_foo _bar'",
"Test.test const char* TestOptionStr = '_foo'",
"Test.test bool TestOptionBool = false",
"Test.test intx TestOptionInt = -1",
"Test.test uintx TestOptionUint = 1",
"Test.test bool TestOptionBool2 = true",
"Test.test double TestOptionDouble = 1.123000",
"Test.test2 double TestOptionDouble = 1.123000"
}
};
private static final String[][] TYPE_3_ARGUMENTS = {
{
"-XX:CompileCommand=option,Test::test,bool,TestOptionBool,false,intx,TestOptionInt,-1,uintx,TestOptionUint,1,TestOptionBool2,double,TestOptionDouble,1.123",
"-version"
}
};
private static final String[][] TYPE_3_EXPECTED_OUTPUTS = {
{
"Test.test bool TestOptionBool = false",
"Test.test intx TestOptionInt = -1",
"Test.test uintx TestOptionUint = 1",
"Test.test bool TestOptionBool2 = true",
"Test.test double TestOptionDouble = 1.123000"
}
};
private static final String[][] TYPE_4_ARGUMENTS = {
{
"-XX:CompileCommand=TestOptionList,Test::test,_foo,_bar",
"-XX:CompileCommand=TestOptionStr,Test::test,_foo",
"-XX:CompileCommand=TestOptionBool,Test::test,false",
"-XX:CompileCommand=TestOptionInt,Test::test,-1",
"-XX:CompileCommand=TestOptionUint,Test::test,1",
"-XX:CompileCommand=TestOptionBool2,Test::test",
"-XX:CompileCommand=TestOptionDouble,Test::test,1.123",
"-XX:CompileCommand=TestOptionDouble,Test.test2,1.123",
"-version"
}
};
private static final String[][] TYPE_4_EXPECTED_OUTPUTS = {
{
"CompileCommand: TestOptionList Test.test const char* TestOptionList = '_foo _bar'",
"CompileCommand: TestOptionStr Test.test const char* TestOptionStr = '_foo'",
"CompileCommand: TestOptionBool Test.test bool TestOptionBool = false",
"CompileCommand: TestOptionInt Test.test intx TestOptionInt = -1",
"CompileCommand: TestOptionUint Test.test uintx TestOptionUint = 1",
"CompileCommand: TestOptionBool2 Test.test bool TestOptionBool2 = true",
"CompileCommand: TestOptionDouble Test.test double TestOptionDouble = 1.123000",
"CompileCommand: TestOptionDouble Test.test2 double TestOptionDouble = 1.123000"
}
};
private static final String[][] TYPE_4_INVALID_ARGUMENTS = {
{
"-XX:CompileCommand=InvalidOption,Test::test,_foo,_bar",
"-XX:CompileCommand=TestOptionInt,Test::test,_foo",
"-XX:CompileCommand=TestOptionBool,Test::test,1",
"-XX:CompileCommand=TestOptionDouble,Test::test,-1",
"-XX:CompileCommand=TestOptionUint,Test::test",
"-XX:CompileCommand=TestOptionBool2,Test::test,falsee",
"-XX:CompileCommand=TestOptionDouble,Test::test,true",
"-XX:CompileCommand=TestOptionDouble,Test.test2,1.f",
"-version"
}
};
private static final String[][] TYPE_4_INVALID_OUTPUTS = {
{
"Unrecognized option 'InvalidOption'",
"Value cannot be read for option 'TestOptionInt' of type 'intx'",
"Value cannot be read for option 'TestOptionBool' of type 'bool'",
"Value cannot be read for option 'TestOptionDouble' of type 'double'",
"Option 'TestOptionUint' is not followed by a value",
"Value cannot be read for option 'TestOptionBool2' of type 'bool'",
"Value cannot be read for option 'TestOptionDouble' of type 'double'",
"Value cannot be read for option 'TestOptionDouble' of type 'double'"
}
};
@ -211,6 +272,23 @@ public class CheckCompileCommandOption {
out.shouldHaveExitValue(0);
}
private static void verifyInvalidOption(String[] arguments, String[] expected_outputs) throws Exception {
ProcessBuilder pb;
OutputAnalyzer out;
pb = ProcessTools.createJavaProcessBuilder(arguments);
out = new OutputAnalyzer(pb.start());
for (String expected_output : expected_outputs) {
out.shouldContain(expected_output);
}
out.shouldContain("CompileCommand: An error occurred during parsing");
out.shouldHaveExitValue(0);
}
public static void main(String[] args) throws Exception {
if (TYPE_1_ARGUMENTS.length != TYPE_1_EXPECTED_OUTPUTS.length) {
@ -221,6 +299,14 @@ public class CheckCompileCommandOption {
throw new RuntimeException("Test is set up incorrectly: length of arguments and expected outputs for type (2) options does not match.");
}
if (TYPE_3_ARGUMENTS.length != TYPE_3_EXPECTED_OUTPUTS.length) {
throw new RuntimeException("Test is set up incorrectly: length of arguments and expected outputs for type (3) options does not match.");
}
if (TYPE_4_ARGUMENTS.length != TYPE_4_EXPECTED_OUTPUTS.length) {
throw new RuntimeException("Test is set up incorrectly: length of arguments and expected outputs for type (4) options does not match.");
}
// Check if type (1) options are parsed correctly
for (int i = 0; i < TYPE_1_ARGUMENTS.length; i++) {
verifyValidOption(TYPE_1_ARGUMENTS[i], TYPE_1_EXPECTED_OUTPUTS[i]);
@ -231,12 +317,28 @@ public class CheckCompileCommandOption {
verifyValidOption(TYPE_2_ARGUMENTS[i], TYPE_2_EXPECTED_OUTPUTS[i]);
}
// Check if type (3) options are parsed correctly
for (int i = 0; i < TYPE_3_ARGUMENTS.length; i++) {
verifyValidOption(TYPE_3_ARGUMENTS[i], TYPE_3_EXPECTED_OUTPUTS[i]);
}
// Check if type (4) options are parsed correctly
for (int i = 0; i < TYPE_4_ARGUMENTS.length; i++) {
verifyValidOption(TYPE_4_ARGUMENTS[i], TYPE_4_EXPECTED_OUTPUTS[i]);
}
// Check if error is reported for invalid type (2) options
// (flags with type information specified)
for (String[] arguments: TYPE_2_INVALID_ARGUMENTS) {
verifyInvalidOption(arguments);
}
// Check if error is reported for invalid type (2) options
// (flags with type information specified)
for (int i = 0; i < TYPE_4_INVALID_ARGUMENTS.length; i++) {
verifyInvalidOption(TYPE_4_INVALID_ARGUMENTS[i], TYPE_4_INVALID_OUTPUTS[i]);
}
// Check if commands in command file are parsed correctly
for (int i = 0; i < FILE_ARGUMENTS.length; i++) {
verifyValidOption(FILE_ARGUMENTS[i], FILE_EXPECTED_OUTPUT[i]);

View file

@ -27,17 +27,30 @@
* @library /test/lib
* @modules java.base/jdk.internal.misc
* @build sun.hotspot.WhiteBox
* @requires vm.debug == true
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
* -XX:CompileCommand=option,compiler.oracle.GetMethodOptionTest::test,ccstrlist,MyListOption,_foo,_bar
* -XX:CompileCommand=option,compiler.oracle.GetMethodOptionTest::test,ccstr,MyStrOption,_foo
* -XX:CompileCommand=option,compiler.oracle.GetMethodOptionTest::test,bool,MyBoolOption,false
* -XX:CompileCommand=option,compiler.oracle.GetMethodOptionTest::test,intx,MyIntxOption,-1
* -XX:CompileCommand=option,compiler.oracle.GetMethodOptionTest::test,uintx,MyUintxOption,1
* -XX:CompileCommand=option,compiler.oracle.GetMethodOptionTest::test,MyFlag
* -XX:CompileCommand=option,compiler.oracle.GetMethodOptionTest::test,double,MyDoubleOption1,1.123
* -XX:CompileCommand=option,compiler.oracle.GetMethodOptionTest::test,double,MyDoubleOption2,1.123
* -XX:CompileCommand=option,compiler.oracle.GetMethodOptionTest::test,bool,MyBoolOptionX,false,intx,MyIntxOptionX,-1,uintx,MyUintxOptionX,1,MyFlagX,double,MyDoubleOptionX,1.123
* -XX:CompileCommand=option,compiler.oracle.GetMethodOptionTest::test,ccstrlist,TestOptionList,_foo,_bar
* -XX:CompileCommand=option,compiler.oracle.GetMethodOptionTest::test,ccstr,TestOptionStr,_foo
* -XX:CompileCommand=option,compiler.oracle.GetMethodOptionTest::test,bool,TestOptionBool,false
* -XX:CompileCommand=option,compiler.oracle.GetMethodOptionTest::test,intx,TestOptionInt,-1
* -XX:CompileCommand=option,compiler.oracle.GetMethodOptionTest::test,uintx,TestOptionUint,1
* -XX:CompileCommand=option,compiler.oracle.GetMethodOptionTest::test,TestOptionBool2
* -XX:CompileCommand=option,compiler.oracle.GetMethodOptionTest::test,double,TestOptionDouble,1.123
* compiler.oracle.GetMethodOptionTest
*
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
* -XX:CompileCommand=option,compiler.oracle.GetMethodOptionTest::test,bool,TestOptionBool,false,intx,TestOptionInt,-1,uintx,TestOptionUint,1,bool,TestOptionBool2,true,ccstr,TestOptionStr,_foo,double,TestOptionDouble,1.123,ccstrlist,TestOptionList,_foo,_bar
* compiler.oracle.GetMethodOptionTest
*
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
* -XX:CompileCommand=TestOptionList,compiler.oracle.GetMethodOptionTest::test,_foo,_bar
* -XX:CompileCommand=TestOptionStr,compiler.oracle.GetMethodOptionTest::test,_foo
* -XX:CompileCommand=TestOptionBool,compiler.oracle.GetMethodOptionTest::test,false
-XX:CompileCommand=TestOptionBool2,compiler.oracle.GetMethodOptionTest::test
* -XX:CompileCommand=TestOptionInt,compiler.oracle.GetMethodOptionTest::test,-1
* -XX:CompileCommand=TestOptionUint,compiler.oracle.GetMethodOptionTest::test,1
* -XX:CompileCommand=TestOptionDouble,compiler.oracle.GetMethodOptionTest::test,1.123
* compiler.oracle.GetMethodOptionTest
*/
@ -72,19 +85,13 @@ public class GetMethodOptionTest {
private static void test2() { }
private static enum TestCase {
MyListOption("_foo _bar", WB::getMethodStringOption),
MyStrOption("_foo", WB::getMethodStringOption),
MyBoolOption(false, WB::getMethodBooleanOption),
MyIntxOption(-1L, WB::getMethodIntxOption),
MyUintxOption(1L, WB::getMethodUintxOption),
MyFlag(true, WB::getMethodBooleanOption),
MyDoubleOption1(1.123d, WB::getMethodDoubleOption),
MyDoubleOption2(1.123d, WB::getMethodDoubleOption),
MyBoolOptionX(false, WB::getMethodBooleanOption),
MyIntxOptionX(-1L, WB::getMethodIntxOption),
MyUintxOptionX(1L, WB::getMethodUintxOption),
MyFlagX(true, WB::getMethodBooleanOption),
MyDoubleOptionX(1.123d, WB::getMethodDoubleOption);
TestOptionBool(false, WB::getMethodBooleanOption),
TestOptionStr("_foo", WB::getMethodStringOption),
TestOptionInt(-1L, WB::getMethodIntxOption),
TestOptionUint(1L, WB::getMethodUintxOption),
TestOptionBool2(true, WB::getMethodBooleanOption),
TestOptionDouble(1.123d, WB::getMethodDoubleOption),
TestOptionList("_foo _bar", WB::getMethodStringOption);
public final Object value;
public final BiFunction<Executable, String, Object> getter;

View file

@ -1,10 +1,10 @@
option,com/oracle/Test.test,MyBoolOption1
option,com/oracle/Test,test,MyBoolOption2
option,com.oracle.Test::test,MyBoolOption3
option,com/oracle/Test.test,MyBoolOption5,MyBoolOption6
option,com/oracle/Test,test,MyBoolOption7,MyBoolOption8
option,com/oracle/Test.test(I),MyBoolOption9
option,com/oracle/Test,test,(I),MyBoolOption10
option,com.oracle.Test::test(I),MyBoolOption11
option,com/oracle/Test.test(I),MyBoolOption13,MyBoolOption14
option,com/oracle/Test,test(I),MyBoolOption15,MyBoolOption16
option,com/oracle/Test.test1,TestOptionBool
option,com/oracle/Test,test2,TestOptionBool
option,com.oracle.Test::test3,TestOptionBool
option,com/oracle/Test.test4,TestOptionBool,TestOptionBool2
option,com/oracle/Test,test5,TestOptionBool,TestOptionBool2
option,com/oracle/Test.test6(I),TestOptionBool
option,com/oracle/Test,test7,(I),TestOptionBool
option,com.oracle.Test::test8(I),TestOptionBool
option,com/oracle/Test.test9(I),TestOptionBool,TestOptionBool2
option,com/oracle/Test,test10(I),TestOptionBool,TestOptionBool2

View file

@ -1,7 +1,7 @@
option,Test::test,ccstrlist,MyListOption,_foo,_bar
option,Test::test,ccstr,MyStrOption,_foo
option,Test::test,bool,MyBoolOption,false
option,Test::test,intx,MyIntxOption,-1
option,Test::test,uintx,MyUintxOption,1
option,Test::test,MyFlag
option,Test::test,double,MyDoubleOption,1.123
option,Test::test,ccstrlist,TestOptionList,_foo,_bar
option,Test::test,ccstr,TestOptionStr,_foo
option,Test::test,bool,TestOptionBool,false
option,Test::test,intx,TestOptionInt,-1
option,Test::test,uintx,TestOptionUint,1
option,Test::test,TestOptionBool2
option,Test::test,double,TestOptionDouble,1.123

View file

@ -48,7 +48,8 @@ public class CompilerConfigFileWarning {
pb = ProcessTools.createJavaProcessBuilder("-XX:CompileCommandFile=hs_comp.txt", "-version");
output = new OutputAnalyzer(pb.start());
output.shouldContain("CompileCommand: unrecognized command");
output.shouldContain("An error occurred during parsing");
output.shouldContain("Unrecognized option 'aaa'");
output.shouldContain("aaa, aaa");
// Skip on debug builds since we'll always read the file there