/* * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
// The JVM specification defines the allowed characters. // Tokens that are disallowed by the JVM specification can have // a meaning to the parser so we need to include them here. // The parser does not enforce all rules of the JVMS - a successful parse // does not mean that it is an allowed name. Illegal names will // be ignored since they never can match a class or method. // // '\0' and 0xf0-0xff are disallowed in constant string values // 0x20 ' ', 0x09 '\t' and, 0x2c ',' are used in the matching // 0x5b '[' and 0x5d ']' can not be used because of the matcher // 0x28 '(' and 0x29 ')' are used for the signature // 0x2e '.' is always replaced before the matching // 0x2f '/' is only used in the class name as package separator // // It seems hard to get Non-ASCII characters to work in all circumstances due // to limitations in Windows. So only ASCII characters are supported on Windows.
bool MethodMatcher::canonicalize(char * line, constchar *& error_msg) { char* colon = strstr(line, "::"); bool have_colon = (colon != NULL); if (have_colon) { // Don't allow multiple '::' if (colon[2] != '\0') { if (strstr(colon+2, "::")) {
error_msg = "Method pattern only allows one '::' allowed"; returnfalse;
}
}
char* pos = line; if (pos != NULL) { for (char* lp = pos + 1; *lp != '\0'; lp++) { if (*lp == '(') { break;
}
if (*lp == '/') {
error_msg = "Method pattern uses '/' together with '::' (tips: replace '/' with '+' for hidden classes)"; returnfalse;
}
}
}
} else { // Don't allow mixed package separators char* pos = strchr(line, '.'); bool in_signature = false; if (pos != NULL) { for (char* lp = pos + 1; *lp != '\0'; lp++) { if (*lp == '(') {
in_signature = true;
}
// After any comma the method pattern has ended if (*lp == ',') { break;
}
if (!in_signature && (*lp == '/')) {
error_msg = "Method pattern uses mixed '/' and '.' package separators"; returnfalse;
}
if (*lp == '.') {
error_msg = "Method pattern uses multiple '.' in pattern"; returnfalse;
}
}
}
}
for (char* lp = line; *lp != '\0'; lp++) { // Allow '.' to separate the class name from the method name. // This is the preferred spelling of methods: // exclude java/lang/String.indexOf(I)I // Allow ',' for spaces (eases command line quoting). // exclude,java/lang/String.indexOf // For backward compatibility, allow space as separator also. // exclude java/lang/String indexOf // exclude,java/lang/String,indexOf // For easy cut-and-paste of method names, allow VM output format // as produced by Method::print_short_name: // exclude java.lang.String::indexOf // For simple implementation convenience here, convert them all to space.
if (have_colon) { if (*lp == '.') *lp = '/'; // dots build the package prefix if (*lp == ':') *lp = ' ';
} if (*lp == ',' || *lp == '.') *lp = ' ';
#ifdef _WINDOWS // It seems hard to get Non-ASCII characters to work in all circumstances due // to limitations in Windows. So only ASCII characters are supported on Windows. if (!isascii(*lp)) {
error_msg = "Non-ASCII characters are not supported on Windows."; returnfalse;
} #endif
} returntrue;
}
// Over-consumption // method_name points to an option type or option name because the method name is not specified by users. // In very rare case, the method name happens to be same as option type/name, so look ahead to make sure // it doesn't show up again. if ((OptionType::Unknown != CompilerOracle::parse_option_type(method_name) ||
CompileCommand::Unknown != CompilerOracle::parse_option_name(method_name)) &&
*(line + bytes_read) != '\0' &&
strstr(line + bytes_read, method_name) == NULL) {
error_msg = "Did not specify any method name";
method_name[0] = '\0'; return;
}
if ((strchr(class_name, JVM_SIGNATURE_SPECIAL) != NULL) ||
(strchr(class_name, JVM_SIGNATURE_ENDSPECIAL) != NULL)) {
error_msg = "Chars '<' and '>' not allowed in class name"; return;
}
if ((strchr(method_name, JVM_SIGNATURE_SPECIAL) != NULL) ||
(strchr(method_name, JVM_SIGNATURE_ENDSPECIAL) != NULL)) { if (!vmSymbols::object_initializer_name()->equals(method_name) &&
!vmSymbols::class_initializer_name()->equals(method_name)) {
error_msg = "Chars '<' and '>' only allowed in and "; return;
}
}
if (c_match == MethodMatcher::Unknown || m_match == MethodMatcher::Unknown) {
assert(error_msg != NULL, "Must have been set by check_mode()"); return;
}
// there might be a signature following the method. // signatures always begin with ( so match that by hand if (line[0] == '(') {
line++;
sig[0] = '('; // scan the rest if (1 == sscanf(line, "%1022[[);/" RANGEBASE "]%n", sig+1, &bytes_read)) { if (strchr(sig, '*') != NULL) {
error_msg = " Wildcard * not allowed in signature"; return;
}
line += bytes_read;
}
signature = SymbolTable::new_symbol(sig);
}
Symbol* c_name = SymbolTable::new_symbol(class_name);
Symbol* m_name = SymbolTable::new_symbol(method_name);
BasicMatcher* BasicMatcher::parse_method_pattern(char* line, constchar*& error_msg, bool expect_trailing_chars) {
assert(error_msg == NULL, "Don't call here with error_msg already set");
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); if (line[bytes_read] != '\0') {
error_msg = "Unrecognized trailing text after method pattern"; delete bm; return NULL;
}
} return bm;
}
bool BasicMatcher::match(const methodHandle& method) { for (BasicMatcher* current = this; current != NULL; current = current->next()) { if (current->matches(method)) { returntrue;
}
} returnfalse;
}
InlineMatcher* InlineMatcher::parse_method_pattern(char* line, constchar*& error_msg) {
assert(error_msg == NULL, "Dont call here with error_msg already set");
InlineMatcher* im = new InlineMatcher();
MethodMatcher::parse_method_pattern(line, error_msg, im); if (error_msg != NULL) { delete im; return NULL;
} return im;
}
bool InlineMatcher::match(const methodHandle& method, int inline_action) { for (InlineMatcher* current = this; current != NULL; current = current->next()) { if (current->matches(method)) { return (current->_inline_action == inline_action);
}
} returnfalse;
}
InlineMatcher* InlineMatcher::parse_inline_pattern(char* str, constchar*& error_msg) { // check first token is +/-
InlineType _inline_action; switch (str[0]) { case'-':
_inline_action = InlineMatcher::dont_inline; break; case'+':
_inline_action = InlineMatcher::force_inline; break; default:
error_msg = "Missing leading inline type (+/-)"; return NULL;
}
str++;
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"); return NULL;
}
im->set_action(_inline_action); return im;
}
InlineMatcher* InlineMatcher::clone() {
InlineMatcher* m = new InlineMatcher();
m->_class_mode = _class_mode;
m->_method_mode = _method_mode;
m->_inline_action = _inline_action;
m->_class_name = _class_name; if(_class_name != NULL) {
_class_name->increment_refcount();
}
m->_method_name = _method_name; if (_method_name != NULL) {
_method_name->increment_refcount();
}
m->_signature = _signature; if (_signature != NULL) {
_signature->increment_refcount();
} return m;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.