提交 986d79a1 编写于 作者: D drchase

Merge

...@@ -1105,6 +1105,22 @@ bool ciMethod::has_option(const char* option) { ...@@ -1105,6 +1105,22 @@ bool ciMethod::has_option(const char* option) {
return CompilerOracle::has_option_string(mh, option); return CompilerOracle::has_option_string(mh, option);
} }
// ------------------------------------------------------------------
// ciMethod::has_option_value
//
template<typename T>
bool ciMethod::has_option_value(const char* option, T& value) {
check_is_loaded();
VM_ENTRY_MARK;
methodHandle mh(THREAD, get_Method());
return CompilerOracle::has_option_value(mh, option, value);
}
// Explicit instantiation for all OptionTypes supported.
template bool ciMethod::has_option_value<intx>(const char* option, intx& value);
template bool ciMethod::has_option_value<uintx>(const char* option, uintx& value);
template bool ciMethod::has_option_value<bool>(const char* option, bool& value);
template bool ciMethod::has_option_value<ccstr>(const char* option, ccstr& value);
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// ciMethod::can_be_compiled // ciMethod::can_be_compiled
// //
......
...@@ -264,6 +264,8 @@ class ciMethod : public ciMetadata { ...@@ -264,6 +264,8 @@ class ciMethod : public ciMetadata {
bool should_print_assembly(); bool should_print_assembly();
bool break_at_execute(); bool break_at_execute();
bool has_option(const char *option); bool has_option(const char *option);
template<typename T>
bool has_option_value(const char* option, T& value);
bool can_be_compiled(); bool can_be_compiled();
bool can_be_osr_compiled(int entry_bci); bool can_be_osr_compiled(int entry_bci);
void set_not_compilable(const char* reason = NULL); void set_not_compilable(const char* reason = NULL);
......
...@@ -167,44 +167,134 @@ bool MethodMatcher::match(Symbol* candidate, Symbol* match, Mode match_mode) { ...@@ -167,44 +167,134 @@ bool MethodMatcher::match(Symbol* candidate, Symbol* match, Mode match_mode) {
} }
} }
enum OptionType {
IntxType,
UintxType,
BoolType,
CcstrType,
UnknownType
};
class MethodOptionMatcher: public MethodMatcher { /* Methods to map real type names to OptionType */
const char * option; template<typename T>
public: static OptionType get_type_for() {
MethodOptionMatcher(Symbol* class_name, Mode class_mode, return UnknownType;
};
template<> OptionType get_type_for<intx>() {
return IntxType;
}
template<> OptionType get_type_for<uintx>() {
return UintxType;
}
template<> OptionType get_type_for<bool>() {
return BoolType;
}
template<> OptionType get_type_for<ccstr>() {
return CcstrType;
}
template<typename T>
static const T copy_value(const T value) {
return value;
}
template<> const ccstr copy_value<ccstr>(const ccstr value) {
return (const ccstr)strdup(value);
}
template <typename T>
class TypedMethodOptionMatcher : public MethodMatcher {
const char* _option;
OptionType _type;
const T _value;
public:
TypedMethodOptionMatcher(Symbol* class_name, Mode class_mode,
Symbol* method_name, Mode method_mode, Symbol* method_name, Mode method_mode,
Symbol* signature, const char * opt, MethodMatcher* next): Symbol* signature, const char* opt,
MethodMatcher(class_name, class_mode, method_name, method_mode, signature, next) { const T value, MethodMatcher* next) :
option = opt; MethodMatcher(class_name, class_mode, method_name, method_mode, signature, next),
_type(get_type_for<T>()), _value(copy_value<T>(value)) {
_option = strdup(opt);
} }
bool match(methodHandle method, const char* opt) { ~TypedMethodOptionMatcher() {
MethodOptionMatcher* current = this; free((void*)_option);
}
TypedMethodOptionMatcher* match(methodHandle method, const char* opt) {
TypedMethodOptionMatcher* current = this;
while (current != NULL) { while (current != NULL) {
current = (MethodOptionMatcher*)current->find(method); current = (TypedMethodOptionMatcher*)current->find(method);
if (current == NULL) { if (current == NULL) {
return false; return NULL;
} }
if (strcmp(current->option, opt) == 0) { if (strcmp(current->_option, opt) == 0) {
return true; return current;
} }
current = current->next(); current = current->next();
} }
return false; return NULL;
} }
MethodOptionMatcher* next() { TypedMethodOptionMatcher* next() {
return (MethodOptionMatcher*)_next; return (TypedMethodOptionMatcher*)_next;
} }
virtual void print() { OptionType get_type(void) {
return _type;
};
T value() { return _value; }
void print() {
ttyLocker ttyl;
print_base(); print_base();
tty->print(" %s", option); tty->print(" %s", _option);
tty->print(" <unknown option type>");
tty->cr(); tty->cr();
} }
}; };
template<>
void TypedMethodOptionMatcher<intx>::print() {
ttyLocker ttyl;
print_base();
tty->print(" intx %s", _option);
tty->print(" = " INTX_FORMAT, _value);
tty->cr();
};
template<>
void TypedMethodOptionMatcher<uintx>::print() {
ttyLocker ttyl;
print_base();
tty->print(" uintx %s", _option);
tty->print(" = " UINTX_FORMAT, _value);
tty->cr();
};
template<>
void TypedMethodOptionMatcher<bool>::print() {
ttyLocker ttyl;
print_base();
tty->print(" bool %s", _option);
tty->print(" = %s", _value ? "true" : "false");
tty->cr();
};
template<>
void TypedMethodOptionMatcher<ccstr>::print() {
ttyLocker ttyl;
print_base();
tty->print(" const char* %s", _option);
tty->print(" = '%s'", _value);
tty->cr();
};
// this must parallel the command_names below // this must parallel the command_names below
enum OracleCommand { enum OracleCommand {
...@@ -259,23 +349,46 @@ static MethodMatcher* add_predicate(OracleCommand command, ...@@ -259,23 +349,46 @@ static MethodMatcher* add_predicate(OracleCommand command,
return lists[command]; return lists[command];
} }
template<typename T>
static MethodMatcher* add_option_string(Symbol* class_name, MethodMatcher::Mode c_mode, static MethodMatcher* add_option_string(Symbol* class_name, MethodMatcher::Mode c_mode,
Symbol* method_name, MethodMatcher::Mode m_mode, Symbol* method_name, MethodMatcher::Mode m_mode,
Symbol* signature, Symbol* signature,
const char* option) { const char* option,
lists[OptionCommand] = new MethodOptionMatcher(class_name, c_mode, method_name, m_mode, T value) {
signature, option, lists[OptionCommand]); lists[OptionCommand] = new TypedMethodOptionMatcher<T>(class_name, c_mode, method_name, m_mode,
signature, option, value, lists[OptionCommand]);
return lists[OptionCommand]; return lists[OptionCommand];
} }
template<typename T>
static bool get_option_value(methodHandle method, const char* option, T& value) {
TypedMethodOptionMatcher<T>* m;
if (lists[OptionCommand] != NULL
&& (m = ((TypedMethodOptionMatcher<T>*)lists[OptionCommand])->match(method, option)) != NULL
&& m->get_type() == get_type_for<T>()) {
value = m->value();
return true;
} else {
return false;
}
}
bool CompilerOracle::has_option_string(methodHandle method, const char* option) { bool CompilerOracle::has_option_string(methodHandle method, const char* option) {
return lists[OptionCommand] != NULL && bool value = false;
((MethodOptionMatcher*)lists[OptionCommand])->match(method, option); get_option_value(method, option, value);
return value;
}
template<typename T>
bool CompilerOracle::has_option_value(methodHandle method, const char* option, T& value) {
return ::get_option_value(method, option, value);
} }
// Explicit instantiation for all OptionTypes supported.
template bool CompilerOracle::has_option_value<intx>(methodHandle method, const char* option, intx& value);
template bool CompilerOracle::has_option_value<uintx>(methodHandle method, const char* option, uintx& value);
template bool CompilerOracle::has_option_value<bool>(methodHandle method, const char* option, bool& value);
template bool CompilerOracle::has_option_value<ccstr>(methodHandle method, const char* option, ccstr& value);
bool CompilerOracle::should_exclude(methodHandle method, bool& quietly) { bool CompilerOracle::should_exclude(methodHandle method, bool& quietly) {
quietly = true; quietly = true;
...@@ -433,6 +546,94 @@ static bool scan_line(const char * line, ...@@ -433,6 +546,94 @@ static bool scan_line(const char * line,
// 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 MethodMatcher* scan_flag_and_value(const char* type, const char* line, int& total_bytes_read,
Symbol* c_name, MethodMatcher::Mode c_match,
Symbol* m_name, MethodMatcher::Mode m_match,
Symbol* signature,
char* errorbuf, const int buf_size) {
total_bytes_read = 0;
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) {
intx value;
if (sscanf(line, "%*[ \t]" INTX_FORMAT "%n", &value, &bytes_read) == 1) {
total_bytes_read += bytes_read;
return add_option_string(c_name, c_match, m_name, m_match, signature, flag, value);
} else {
jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s ", flag, type);
}
} else if (strcmp(type, "uintx") == 0) {
uintx value;
if (sscanf(line, "%*[ \t]" UINTX_FORMAT "%n", &value, &bytes_read) == 1) {
total_bytes_read += bytes_read;
return add_option_string(c_name, c_match, m_name, m_match, signature, flag, value);
} else {
jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type);
}
} else if (strcmp(type, "ccstr") == 0) {
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) {
total_bytes_read += bytes_read;
return add_option_string(c_name, c_match, m_name, m_match, signature, flag, (ccstr)value);
} else {
jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type);
}
} else if (strcmp(type, "ccstrlist") == 0) {
// 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) {
total_bytes_read += bytes_read;
line += bytes_read;
next_value += bytes_read;
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;
*end_value = ' '; // override '\0'
next_value += bytes_read;
end_value = next_value-1;
}
return add_option_string(c_name, c_match, m_name, m_match, signature, flag, (ccstr)value);
} else {
jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type);
}
} else if (strcmp(type, "bool") == 0) {
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;
return add_option_string(c_name, c_match, m_name, m_match, signature, flag, true);
} else if (strcmp(value, "false") == 0) {
total_bytes_read += bytes_read;
return add_option_string(c_name, c_match, m_name, m_match, signature, flag, false);
} else {
jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type);
}
} else {
jio_snprintf(errorbuf, sizeof(errorbuf), " Value cannot be read for flag %s of type %s", flag, type);
}
} else {
jio_snprintf(errorbuf, sizeof(errorbuf), " Type %s not supported ", type);
}
} else {
jio_snprintf(errorbuf, sizeof(errorbuf), " Flag name for type %s should be alphanumeric ", type);
}
return NULL;
}
void CompilerOracle::parse_from_line(char* line) { void CompilerOracle::parse_from_line(char* line) {
if (line[0] == '\0') return; if (line[0] == '\0') return;
if (line[0] == '#') return; if (line[0] == '#') return;
...@@ -462,8 +663,10 @@ void CompilerOracle::parse_from_line(char* line) { ...@@ -462,8 +663,10 @@ void CompilerOracle::parse_from_line(char* line) {
int bytes_read; int bytes_read;
OracleCommand command = parse_command_name(line, &bytes_read); OracleCommand command = parse_command_name(line, &bytes_read);
line += bytes_read; line += bytes_read;
ResourceMark rm;
if (command == UnknownCommand) { if (command == UnknownCommand) {
ttyLocker ttyl;
tty->print_cr("CompilerOracle: unrecognized line"); tty->print_cr("CompilerOracle: unrecognized line");
tty->print_cr(" \"%s\"", original_line); tty->print_cr(" \"%s\"", original_line);
return; return;
...@@ -485,7 +688,7 @@ void CompilerOracle::parse_from_line(char* line) { ...@@ -485,7 +688,7 @@ void CompilerOracle::parse_from_line(char* line) {
char method_name[256]; char method_name[256];
char sig[1024]; char sig[1024];
char errorbuf[1024]; char errorbuf[1024];
const char* error_msg = NULL; const char* error_msg = NULL; // description of first error that appears
MethodMatcher* match = NULL; MethodMatcher* match = NULL;
if (scan_line(line, class_name, &c_match, method_name, &m_match, &bytes_read, error_msg)) { if (scan_line(line, class_name, &c_match, method_name, &m_match, &bytes_read, error_msg)) {
...@@ -504,43 +707,77 @@ void CompilerOracle::parse_from_line(char* line) { ...@@ -504,43 +707,77 @@ void CompilerOracle::parse_from_line(char* line) {
} }
if (command == OptionCommand) { if (command == OptionCommand) {
// Look for trailing options to support // Look for trailing options.
// ciMethod::has_option("string") to control features in the //
// compiler. Multiple options may follow the method name. // Two types of trailing options are
char option[256]; // supported:
//
// (1) CompileCommand=option,Klass::method,flag
// (2) CompileCommand=option,Klass::method,type,flag,value
//
// Type (1) is used to support ciMethod::has_option("someflag")
// (i.e., to check if a flag "someflag" is enabled for a method).
//
// Type (2) is used to support options with a value. Values can have the
// the following types: intx, uintx, bool, ccstr, and ccstrlist.
//
// For future extensions: extend scan_flag_and_value()
char option[256]; // stores flag for Type (1) and type of Type (2)
while (sscanf(line, "%*[ \t]%255[a-zA-Z0-9]%n", option, &bytes_read) == 1) { while (sscanf(line, "%*[ \t]%255[a-zA-Z0-9]%n", option, &bytes_read) == 1) {
if (match != NULL && !_quiet) { if (match != NULL && !_quiet) {
// Print out the last match added // Print out the last match added
ttyLocker ttyl;
tty->print("CompilerOracle: %s ", command_names[command]); tty->print("CompilerOracle: %s ", command_names[command]);
match->print(); match->print();
} }
match = add_option_string(c_name, c_match, m_name, m_match, signature, strdup(option));
line += bytes_read; line += bytes_read;
if (strcmp(option, "intx") == 0
|| strcmp(option, "uintx") == 0
|| strcmp(option, "bool") == 0
|| strcmp(option, "ccstr") == 0
|| strcmp(option, "ccstrlist") == 0
) {
// Type (2) option: parse flag name and value.
match = scan_flag_and_value(option, line, bytes_read,
c_name, c_match, m_name, m_match, signature,
errorbuf, sizeof(errorbuf));
if (match == NULL) {
error_msg = errorbuf;
break;
} }
line += bytes_read;
} else { } else {
bytes_read = 0; // Type (1) option
sscanf(line, "%*[ \t]%n", &bytes_read); match = add_option_string(c_name, c_match, m_name, m_match, signature, option, true);
if (line[bytes_read] != '\0') { }
jio_snprintf(errorbuf, sizeof(errorbuf), " Unrecognized text after command: %s", line); } // while(
error_msg = errorbuf;
} else { } else {
match = add_predicate(command, c_name, c_match, m_name, m_match, signature); match = add_predicate(command, c_name, c_match, m_name, m_match, signature);
} }
} }
}
if (match != NULL) { ttyLocker ttyl;
if (!_quiet) { if (error_msg != NULL) {
ResourceMark rm; // an error has happened
tty->print("CompilerOracle: %s ", command_names[command]);
match->print();
}
} else {
tty->print_cr("CompilerOracle: unrecognized line"); tty->print_cr("CompilerOracle: unrecognized line");
tty->print_cr(" \"%s\"", original_line); tty->print_cr(" \"%s\"", original_line);
if (error_msg != NULL) { if (error_msg != NULL) {
tty->print_cr("%s", error_msg); tty->print_cr("%s", error_msg);
} }
} else {
// check for remaining characters
bytes_read = 0;
sscanf(line, "%*[ \t]%n", &bytes_read);
if (line[bytes_read] != '\0') {
tty->print_cr("CompilerOracle: unrecognized line");
tty->print_cr(" \"%s\"", original_line);
tty->print_cr(" Unrecognized text %s after command ", line);
} else if (match != NULL && !_quiet) {
tty->print("CompilerOracle: %s ", command_names[command]);
match->print();
}
} }
} }
......
...@@ -64,6 +64,11 @@ class CompilerOracle : AllStatic { ...@@ -64,6 +64,11 @@ class CompilerOracle : AllStatic {
// Check to see if this method has option set for it // Check to see if this method has option set for it
static bool has_option_string(methodHandle method, const char * option); static bool has_option_string(methodHandle method, const char * 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(methodHandle method, const char* option, T& value);
// Reads from string instead of file // 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* command_string, void (*parser)(char*));
......
...@@ -598,6 +598,10 @@ class Compile : public Phase { ...@@ -598,6 +598,10 @@ class Compile : public Phase {
bool method_has_option(const char * option) { bool method_has_option(const char * option) {
return method() != NULL && method()->has_option(option); return method() != NULL && method()->has_option(option);
} }
template<typename T>
bool method_has_option_value(const char * option, T& value) {
return method() != NULL && method()->has_option_value(option, value);
}
#ifndef PRODUCT #ifndef PRODUCT
bool trace_opto_output() const { return _trace_opto_output; } bool trace_opto_output() const { return _trace_opto_output; }
bool parsed_irreducible_loop() const { return _parsed_irreducible_loop; } bool parsed_irreducible_loop() const { return _parsed_irreducible_loop; }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册