# HG changeset patch # User iveresov # Date 1410286824 0 # Node ID 2d9cef76b5a619728e9158015f491127b0031e17 # Parent e09c0676c53fd92175baeba9214080112d23d6fd# Parent 2e6106d44079dd313a6c0e82df744f0b20bc618c Merge diff -r 2e6106d44079 -r 2d9cef76b5a6 src/share/vm/ci/ciMethod.cpp --- a/src/share/vm/ci/ciMethod.cpp Mon Sep 08 11:45:48 2014 -0700 +++ b/src/share/vm/ci/ciMethod.cpp Tue Sep 09 18:20:24 2014 +0000 @@ -1106,6 +1106,22 @@ } // ------------------------------------------------------------------ +// ciMethod::has_option_value +// +template +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(const char* option, intx& value); +template bool ciMethod::has_option_value(const char* option, uintx& value); +template bool ciMethod::has_option_value(const char* option, bool& value); +template bool ciMethod::has_option_value(const char* option, ccstr& value); + +// ------------------------------------------------------------------ // ciMethod::can_be_compiled // // Have previous compilations of this method succeeded? diff -r 2e6106d44079 -r 2d9cef76b5a6 src/share/vm/ci/ciMethod.hpp --- a/src/share/vm/ci/ciMethod.hpp Mon Sep 08 11:45:48 2014 -0700 +++ b/src/share/vm/ci/ciMethod.hpp Tue Sep 09 18:20:24 2014 +0000 @@ -264,6 +264,8 @@ bool should_print_assembly(); bool break_at_execute(); bool has_option(const char *option); + template + bool has_option_value(const char* option, T& value); bool can_be_compiled(); bool can_be_osr_compiled(int entry_bci); void set_not_compilable(const char* reason = NULL); diff -r 2e6106d44079 -r 2d9cef76b5a6 src/share/vm/compiler/compilerOracle.cpp --- a/src/share/vm/compiler/compilerOracle.cpp Mon Sep 08 11:45:48 2014 -0700 +++ b/src/share/vm/compiler/compilerOracle.cpp Tue Sep 09 18:20:24 2014 +0000 @@ -167,44 +167,134 @@ } } +enum OptionType { + IntxType, + UintxType, + BoolType, + CcstrType, + UnknownType +}; -class MethodOptionMatcher: public MethodMatcher { - const char * option; - public: - MethodOptionMatcher(Symbol* class_name, Mode class_mode, - Symbol* method_name, Mode method_mode, - Symbol* signature, const char * opt, MethodMatcher* next): - MethodMatcher(class_name, class_mode, method_name, method_mode, signature, next) { - option = opt; +/* Methods to map real type names to OptionType */ +template +static OptionType get_type_for() { + return UnknownType; +}; + +template<> OptionType get_type_for() { + return IntxType; +} + +template<> OptionType get_type_for() { + return UintxType; +} + +template<> OptionType get_type_for() { + return BoolType; +} + +template<> OptionType get_type_for() { + return CcstrType; +} + +template +static const T copy_value(const T value) { + return value; +} + +template<> const ccstr copy_value(const ccstr value) { + return (const ccstr)strdup(value); +} + +template +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* signature, const char* opt, + const T value, MethodMatcher* next) : + MethodMatcher(class_name, class_mode, method_name, method_mode, signature, next), + _type(get_type_for()), _value(copy_value(value)) { + _option = strdup(opt); } - bool match(methodHandle method, const char* opt) { - MethodOptionMatcher* current = this; + ~TypedMethodOptionMatcher() { + free((void*)_option); + } + + TypedMethodOptionMatcher* match(methodHandle method, const char* opt) { + TypedMethodOptionMatcher* current = this; while (current != NULL) { - current = (MethodOptionMatcher*)current->find(method); + current = (TypedMethodOptionMatcher*)current->find(method); if (current == NULL) { - return false; + return NULL; } - if (strcmp(current->option, opt) == 0) { - return true; + if (strcmp(current->_option, opt) == 0) { + return current; } current = current->next(); } - return false; + return NULL; + } + + TypedMethodOptionMatcher* next() { + return (TypedMethodOptionMatcher*)_next; } - MethodOptionMatcher* next() { - return (MethodOptionMatcher*)_next; - } + OptionType get_type(void) { + return _type; + }; + + T value() { return _value; } - virtual void print() { + void print() { + ttyLocker ttyl; print_base(); - tty->print(" %s", option); + tty->print(" %s", _option); + tty->print(" "); tty->cr(); } }; +template<> +void TypedMethodOptionMatcher::print() { + ttyLocker ttyl; + print_base(); + tty->print(" intx %s", _option); + tty->print(" = " INTX_FORMAT, _value); + tty->cr(); +}; +template<> +void TypedMethodOptionMatcher::print() { + ttyLocker ttyl; + print_base(); + tty->print(" uintx %s", _option); + tty->print(" = " UINTX_FORMAT, _value); + tty->cr(); +}; + +template<> +void TypedMethodOptionMatcher::print() { + ttyLocker ttyl; + print_base(); + tty->print(" bool %s", _option); + tty->print(" = %s", _value ? "true" : "false"); + tty->cr(); +}; + +template<> +void TypedMethodOptionMatcher::print() { + ttyLocker ttyl; + print_base(); + tty->print(" const char* %s", _option); + tty->print(" = '%s'", _value); + tty->cr(); +}; // this must parallel the command_names below enum OracleCommand { @@ -259,23 +349,46 @@ return lists[command]; } - - +template static MethodMatcher* add_option_string(Symbol* class_name, MethodMatcher::Mode c_mode, Symbol* method_name, MethodMatcher::Mode m_mode, Symbol* signature, - const char* option) { - lists[OptionCommand] = new MethodOptionMatcher(class_name, c_mode, method_name, m_mode, - signature, option, lists[OptionCommand]); + const char* option, + T value) { + lists[OptionCommand] = new TypedMethodOptionMatcher(class_name, c_mode, method_name, m_mode, + signature, option, value, lists[OptionCommand]); return lists[OptionCommand]; } +template +static bool get_option_value(methodHandle method, const char* option, T& value) { + TypedMethodOptionMatcher* m; + if (lists[OptionCommand] != NULL + && (m = ((TypedMethodOptionMatcher*)lists[OptionCommand])->match(method, option)) != NULL + && m->get_type() == get_type_for()) { + value = m->value(); + return true; + } else { + return false; + } +} bool CompilerOracle::has_option_string(methodHandle method, const char* option) { - return lists[OptionCommand] != NULL && - ((MethodOptionMatcher*)lists[OptionCommand])->match(method, option); + bool value = false; + get_option_value(method, option, value); + return value; } +template +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(methodHandle method, const char* option, intx& value); +template bool CompilerOracle::has_option_value(methodHandle method, const char* option, uintx& value); +template bool CompilerOracle::has_option_value(methodHandle method, const char* option, bool& value); +template bool CompilerOracle::has_option_value(methodHandle method, const char* option, ccstr& value); bool CompilerOracle::should_exclude(methodHandle method, bool& quietly) { quietly = true; @@ -433,6 +546,94 @@ +// 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) { if (line[0] == '\0') return; if (line[0] == '#') return; @@ -462,8 +663,10 @@ int bytes_read; OracleCommand command = parse_command_name(line, &bytes_read); line += bytes_read; + ResourceMark rm; if (command == UnknownCommand) { + ttyLocker ttyl; tty->print_cr("CompilerOracle: unrecognized line"); tty->print_cr(" \"%s\"", original_line); return; @@ -485,7 +688,7 @@ char method_name[256]; char sig[1024]; char errorbuf[1024]; - const char* error_msg = NULL; + const char* error_msg = NULL; // description of first error that appears MethodMatcher* match = NULL; if (scan_line(line, class_name, &c_match, method_name, &m_match, &bytes_read, error_msg)) { @@ -504,43 +707,77 @@ } if (command == OptionCommand) { - // Look for trailing options to support - // ciMethod::has_option("string") to control features in the - // compiler. Multiple options may follow the method name. - char option[256]; + // 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 + // + // 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) { if (match != NULL && !_quiet) { // Print out the last match added + ttyLocker ttyl; tty->print("CompilerOracle: %s ", command_names[command]); match->print(); } - match = add_option_string(c_name, c_match, m_name, m_match, signature, strdup(option)); 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 { + // Type (1) option + match = add_option_string(c_name, c_match, m_name, m_match, signature, option, true); + } + } // while( } else { - bytes_read = 0; - sscanf(line, "%*[ \t]%n", &bytes_read); - if (line[bytes_read] != '\0') { - jio_snprintf(errorbuf, sizeof(errorbuf), " Unrecognized text after command: %s", line); - error_msg = errorbuf; - } 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) { - if (!_quiet) { - ResourceMark rm; - tty->print("CompilerOracle: %s ", command_names[command]); - match->print(); - } - } else { + ttyLocker ttyl; + if (error_msg != NULL) { + // an error has happened tty->print_cr("CompilerOracle: unrecognized line"); tty->print_cr(" \"%s\"", original_line); if (error_msg != NULL) { 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(); + } } } diff -r 2e6106d44079 -r 2d9cef76b5a6 src/share/vm/compiler/compilerOracle.hpp --- a/src/share/vm/compiler/compilerOracle.hpp Mon Sep 08 11:45:48 2014 -0700 +++ b/src/share/vm/compiler/compilerOracle.hpp Tue Sep 09 18:20:24 2014 +0000 @@ -64,6 +64,11 @@ // Check to see if this method has option set for it 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 + static bool has_option_value(methodHandle method, const char* option, T& value); + // Reads from string instead of file static void parse_from_string(const char* command_string, void (*parser)(char*)); diff -r 2e6106d44079 -r 2d9cef76b5a6 src/share/vm/opto/compile.hpp --- a/src/share/vm/opto/compile.hpp Mon Sep 08 11:45:48 2014 -0700 +++ b/src/share/vm/opto/compile.hpp Tue Sep 09 18:20:24 2014 +0000 @@ -598,6 +598,10 @@ bool method_has_option(const char * option) { return method() != NULL && method()->has_option(option); } + template + bool method_has_option_value(const char * option, T& value) { + return method() != NULL && method()->has_option_value(option, value); + } #ifndef PRODUCT bool trace_opto_output() const { return _trace_opto_output; } bool parsed_irreducible_loop() const { return _parsed_irreducible_loop; }