1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/compiler/compilerOracle.cpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,710 @@ 1.4 +/* 1.5 + * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "incls/_precompiled.incl" 1.29 +#include "incls/_compilerOracle.cpp.incl" 1.30 + 1.31 +class MethodMatcher : public CHeapObj { 1.32 + public: 1.33 + enum Mode { 1.34 + Exact, 1.35 + Prefix = 1, 1.36 + Suffix = 2, 1.37 + Substring = Prefix | Suffix, 1.38 + Any, 1.39 + Unknown = -1 1.40 + }; 1.41 + 1.42 + protected: 1.43 + jobject _class_name; 1.44 + Mode _class_mode; 1.45 + jobject _method_name; 1.46 + Mode _method_mode; 1.47 + jobject _signature; 1.48 + MethodMatcher* _next; 1.49 + 1.50 + static bool match(symbolHandle candidate, symbolHandle match, Mode match_mode); 1.51 + 1.52 + symbolHandle class_name() const { return (symbolOop)JNIHandles::resolve_non_null(_class_name); } 1.53 + symbolHandle method_name() const { return (symbolOop)JNIHandles::resolve_non_null(_method_name); } 1.54 + symbolHandle signature() const { return (symbolOop)JNIHandles::resolve(_signature); } 1.55 + 1.56 + public: 1.57 + MethodMatcher(symbolHandle class_name, Mode class_mode, 1.58 + symbolHandle method_name, Mode method_mode, 1.59 + symbolHandle signature, MethodMatcher* next); 1.60 + MethodMatcher(symbolHandle class_name, symbolHandle method_name, MethodMatcher* next); 1.61 + 1.62 + // utility method 1.63 + MethodMatcher* find(methodHandle method) { 1.64 + symbolHandle class_name = Klass::cast(method->method_holder())->name(); 1.65 + symbolHandle method_name = method->name(); 1.66 + for (MethodMatcher* current = this; current != NULL; current = current->_next) { 1.67 + if (match(class_name, current->class_name(), current->_class_mode) && 1.68 + match(method_name, current->method_name(), current->_method_mode) && 1.69 + (current->signature().is_null() || current->signature()() == method->signature())) { 1.70 + return current; 1.71 + } 1.72 + } 1.73 + return NULL; 1.74 + } 1.75 + 1.76 + bool match(methodHandle method) { 1.77 + return find(method) != NULL; 1.78 + } 1.79 + 1.80 + MethodMatcher* next() const { return _next; } 1.81 + 1.82 + static void print_symbol(symbolHandle h, Mode mode) { 1.83 + ResourceMark rm; 1.84 + 1.85 + if (mode == Suffix || mode == Substring || mode == Any) { 1.86 + tty->print("*"); 1.87 + } 1.88 + if (mode != Any) { 1.89 + h()->print_symbol_on(tty); 1.90 + } 1.91 + if (mode == Prefix || mode == Substring) { 1.92 + tty->print("*"); 1.93 + } 1.94 + } 1.95 + 1.96 + void print_base() { 1.97 + print_symbol(class_name(), _class_mode); 1.98 + tty->print("."); 1.99 + print_symbol(method_name(), _method_mode); 1.100 + if (!signature().is_null()) { 1.101 + tty->print(" "); 1.102 + signature()->print_symbol_on(tty); 1.103 + } 1.104 + } 1.105 + 1.106 + virtual void print() { 1.107 + print_base(); 1.108 + tty->cr(); 1.109 + } 1.110 +}; 1.111 + 1.112 +MethodMatcher::MethodMatcher(symbolHandle class_name, symbolHandle method_name, MethodMatcher* next) { 1.113 + _class_name = JNIHandles::make_global(class_name); 1.114 + _method_name = JNIHandles::make_global(method_name); 1.115 + _next = next; 1.116 + _class_mode = MethodMatcher::Exact; 1.117 + _method_mode = MethodMatcher::Exact; 1.118 + _signature = NULL; 1.119 +} 1.120 + 1.121 + 1.122 +MethodMatcher::MethodMatcher(symbolHandle class_name, Mode class_mode, 1.123 + symbolHandle method_name, Mode method_mode, 1.124 + symbolHandle signature, MethodMatcher* next): 1.125 + _class_mode(class_mode) 1.126 + , _method_mode(method_mode) 1.127 + , _next(next) 1.128 + , _class_name(JNIHandles::make_global(class_name())) 1.129 + , _method_name(JNIHandles::make_global(method_name())) 1.130 + , _signature(JNIHandles::make_global(signature())) { 1.131 +} 1.132 + 1.133 +bool MethodMatcher::match(symbolHandle candidate, symbolHandle match, Mode match_mode) { 1.134 + if (match_mode == Any) { 1.135 + return true; 1.136 + } 1.137 + 1.138 + if (match_mode == Exact) { 1.139 + return candidate() == match(); 1.140 + } 1.141 + 1.142 + ResourceMark rm; 1.143 + const char * candidate_string = candidate->as_C_string(); 1.144 + const char * match_string = match->as_C_string(); 1.145 + 1.146 + switch (match_mode) { 1.147 + case Prefix: 1.148 + return strstr(candidate_string, match_string) == candidate_string; 1.149 + 1.150 + case Suffix: { 1.151 + size_t clen = strlen(candidate_string); 1.152 + size_t mlen = strlen(match_string); 1.153 + return clen >= mlen && strcmp(candidate_string + clen - mlen, match_string) == 0; 1.154 + } 1.155 + 1.156 + case Substring: 1.157 + return strstr(candidate_string, match_string) != NULL; 1.158 + 1.159 + default: 1.160 + return false; 1.161 + } 1.162 +} 1.163 + 1.164 + 1.165 +class MethodOptionMatcher: public MethodMatcher { 1.166 + const char * option; 1.167 + public: 1.168 + MethodOptionMatcher(symbolHandle class_name, Mode class_mode, 1.169 + symbolHandle method_name, Mode method_mode, 1.170 + symbolHandle signature, const char * opt, MethodMatcher* next): 1.171 + MethodMatcher(class_name, class_mode, method_name, method_mode, signature, next) { 1.172 + option = opt; 1.173 + } 1.174 + 1.175 + bool match(methodHandle method, const char* opt) { 1.176 + MethodOptionMatcher* current = this; 1.177 + while (current != NULL) { 1.178 + current = (MethodOptionMatcher*)current->find(method); 1.179 + if (current == NULL) { 1.180 + return false; 1.181 + } 1.182 + if (strcmp(current->option, opt) == 0) { 1.183 + return true; 1.184 + } 1.185 + current = current->next(); 1.186 + } 1.187 + return false; 1.188 + } 1.189 + 1.190 + MethodOptionMatcher* next() { 1.191 + return (MethodOptionMatcher*)_next; 1.192 + } 1.193 + 1.194 + virtual void print() { 1.195 + print_base(); 1.196 + tty->print(" %s", option); 1.197 + tty->cr(); 1.198 + } 1.199 +}; 1.200 + 1.201 + 1.202 + 1.203 +// this must parallel the command_names below 1.204 +enum OracleCommand { 1.205 + UnknownCommand = -1, 1.206 + OracleFirstCommand = 0, 1.207 + BreakCommand = OracleFirstCommand, 1.208 + PrintCommand, 1.209 + ExcludeCommand, 1.210 + InlineCommand, 1.211 + DontInlineCommand, 1.212 + CompileOnlyCommand, 1.213 + LogCommand, 1.214 + OptionCommand, 1.215 + QuietCommand, 1.216 + HelpCommand, 1.217 + OracleCommandCount 1.218 +}; 1.219 + 1.220 +// this must parallel the enum OracleCommand 1.221 +static const char * command_names[] = { 1.222 + "break", 1.223 + "print", 1.224 + "exclude", 1.225 + "inline", 1.226 + "dontinline", 1.227 + "compileonly", 1.228 + "log", 1.229 + "option", 1.230 + "quiet", 1.231 + "help" 1.232 +}; 1.233 + 1.234 +static const char * command_name(OracleCommand command) { 1.235 + if (command < OracleFirstCommand || command >= OracleCommandCount) { 1.236 + return "unknown command"; 1.237 + } 1.238 + return command_names[command]; 1.239 +} 1.240 + 1.241 +class MethodMatcher; 1.242 +static MethodMatcher* lists[OracleCommandCount] = { 0, }; 1.243 + 1.244 + 1.245 +static bool check_predicate(OracleCommand command, methodHandle method) { 1.246 + return ((lists[command] != NULL) && 1.247 + !method.is_null() && 1.248 + lists[command]->match(method)); 1.249 +} 1.250 + 1.251 + 1.252 +static MethodMatcher* add_predicate(OracleCommand command, 1.253 + symbolHandle class_name, MethodMatcher::Mode c_mode, 1.254 + symbolHandle method_name, MethodMatcher::Mode m_mode, 1.255 + symbolHandle signature) { 1.256 + assert(command != OptionCommand, "must use add_option_string"); 1.257 + if (command == LogCommand && !LogCompilation && lists[LogCommand] == NULL) 1.258 + tty->print_cr("Warning: +LogCompilation must be enabled in order for individual methods to be logged."); 1.259 + lists[command] = new MethodMatcher(class_name, c_mode, method_name, m_mode, signature, lists[command]); 1.260 + return lists[command]; 1.261 +} 1.262 + 1.263 + 1.264 + 1.265 +static MethodMatcher* add_option_string(symbolHandle class_name, MethodMatcher::Mode c_mode, 1.266 + symbolHandle method_name, MethodMatcher::Mode m_mode, 1.267 + symbolHandle signature, 1.268 + const char* option) { 1.269 + lists[OptionCommand] = new MethodOptionMatcher(class_name, c_mode, method_name, m_mode, 1.270 + signature, option, lists[OptionCommand]); 1.271 + return lists[OptionCommand]; 1.272 +} 1.273 + 1.274 + 1.275 +bool CompilerOracle::has_option_string(methodHandle method, const char* option) { 1.276 + return lists[OptionCommand] != NULL && 1.277 + ((MethodOptionMatcher*)lists[OptionCommand])->match(method, option); 1.278 +} 1.279 + 1.280 + 1.281 +bool CompilerOracle::should_exclude(methodHandle method, bool& quietly) { 1.282 + quietly = true; 1.283 + if (lists[ExcludeCommand] != NULL) { 1.284 + if (lists[ExcludeCommand]->match(method)) { 1.285 + quietly = _quiet; 1.286 + return true; 1.287 + } 1.288 + } 1.289 + 1.290 + if (lists[CompileOnlyCommand] != NULL) { 1.291 + return !lists[CompileOnlyCommand]->match(method); 1.292 + } 1.293 + return false; 1.294 +} 1.295 + 1.296 + 1.297 +bool CompilerOracle::should_inline(methodHandle method) { 1.298 + return (check_predicate(InlineCommand, method)); 1.299 +} 1.300 + 1.301 + 1.302 +bool CompilerOracle::should_not_inline(methodHandle method) { 1.303 + return (check_predicate(DontInlineCommand, method)); 1.304 +} 1.305 + 1.306 + 1.307 +bool CompilerOracle::should_print(methodHandle method) { 1.308 + return (check_predicate(PrintCommand, method)); 1.309 +} 1.310 + 1.311 + 1.312 +bool CompilerOracle::should_log(methodHandle method) { 1.313 + if (!LogCompilation) return false; 1.314 + if (lists[LogCommand] == NULL) return true; // by default, log all 1.315 + return (check_predicate(LogCommand, method)); 1.316 +} 1.317 + 1.318 + 1.319 +bool CompilerOracle::should_break_at(methodHandle method) { 1.320 + return check_predicate(BreakCommand, method); 1.321 +} 1.322 + 1.323 + 1.324 +static OracleCommand parse_command_name(const char * line, int* bytes_read) { 1.325 + assert(ARRAY_SIZE(command_names) == OracleCommandCount, 1.326 + "command_names size mismatch"); 1.327 + 1.328 + *bytes_read = 0; 1.329 + char command[32]; 1.330 + int result = sscanf(line, "%32[a-z]%n", command, bytes_read); 1.331 + for (uint i = 0; i < ARRAY_SIZE(command_names); i++) { 1.332 + if (strcmp(command, command_names[i]) == 0) { 1.333 + return (OracleCommand)i; 1.334 + } 1.335 + } 1.336 + return UnknownCommand; 1.337 +} 1.338 + 1.339 + 1.340 +static void usage() { 1.341 + tty->print_cr(" CompileCommand and the CompilerOracle allows simple control over"); 1.342 + tty->print_cr(" what's allowed to be compiled. The standard supported directives"); 1.343 + tty->print_cr(" are exclude and compileonly. The exclude directive stops a method"); 1.344 + tty->print_cr(" from being compiled and compileonly excludes all methods except for"); 1.345 + tty->print_cr(" the ones mentioned by compileonly directives. The basic form of"); 1.346 + tty->print_cr(" all commands is a command name followed by the name of the method"); 1.347 + tty->print_cr(" in one of two forms: the standard class file format as in"); 1.348 + tty->print_cr(" class/name.methodName or the PrintCompilation format"); 1.349 + tty->print_cr(" class.name::methodName. The method name can optionally be followed"); 1.350 + tty->print_cr(" by a space then the signature of the method in the class file"); 1.351 + tty->print_cr(" format. Otherwise the directive applies to all methods with the"); 1.352 + tty->print_cr(" same name and class regardless of signature. Leading and trailing"); 1.353 + tty->print_cr(" *'s in the class and/or method name allows a small amount of"); 1.354 + tty->print_cr(" wildcarding. "); 1.355 + tty->cr(); 1.356 + tty->print_cr(" Examples:"); 1.357 + tty->cr(); 1.358 + tty->print_cr(" exclude java/lang/StringBuffer.append"); 1.359 + tty->print_cr(" compileonly java/lang/StringBuffer.toString ()Ljava/lang/String;"); 1.360 + tty->print_cr(" exclude java/lang/String*.*"); 1.361 + tty->print_cr(" exclude *.toString"); 1.362 +} 1.363 + 1.364 + 1.365 +// The characters allowed in a class or method name. All characters > 0x7f 1.366 +// are allowed in order to handle obfuscated class files (e.g. Volano) 1.367 +#define RANGEBASE "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789$_<>" \ 1.368 + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" \ 1.369 + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" \ 1.370 + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf" \ 1.371 + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" \ 1.372 + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" \ 1.373 + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" \ 1.374 + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" \ 1.375 + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" 1.376 + 1.377 +#define RANGE0 "[*" RANGEBASE "]" 1.378 +#define RANGEDOT "[*" RANGEBASE ".]" 1.379 +#define RANGESLASH "[*" RANGEBASE "/]" 1.380 + 1.381 + 1.382 +// Accept several syntaxes for these patterns 1.383 +// original syntax 1.384 +// cmd java.lang.String foo 1.385 +// PrintCompilation syntax 1.386 +// cmd java.lang.String::foo 1.387 +// VM syntax 1.388 +// cmd java/lang/String[. ]foo 1.389 +// 1.390 + 1.391 +static const char* patterns[] = { 1.392 + "%*[ \t]%255" RANGEDOT " " "%255" RANGE0 "%n", 1.393 + "%*[ \t]%255" RANGEDOT "::" "%255" RANGE0 "%n", 1.394 + "%*[ \t]%255" RANGESLASH "%*[ .]" "%255" RANGE0 "%n", 1.395 +}; 1.396 + 1.397 +static MethodMatcher::Mode check_mode(char name[], const char*& error_msg) { 1.398 + if (strcmp(name, "*") == 0) return MethodMatcher::Any; 1.399 + 1.400 + int match = MethodMatcher::Exact; 1.401 + if (name[0] == '*') { 1.402 + match |= MethodMatcher::Suffix; 1.403 + strcpy(name, name + 1); 1.404 + } 1.405 + 1.406 + size_t len = strlen(name); 1.407 + if (len > 0 && name[len - 1] == '*') { 1.408 + match |= MethodMatcher::Prefix; 1.409 + name[len - 1] = '\0'; 1.410 + } 1.411 + 1.412 + if (strstr(name, "*") != NULL) { 1.413 + error_msg = " Embedded * not allowed"; 1.414 + return MethodMatcher::Unknown; 1.415 + } 1.416 + return (MethodMatcher::Mode)match; 1.417 +} 1.418 + 1.419 +static bool scan_line(const char * line, 1.420 + char class_name[], MethodMatcher::Mode* c_mode, 1.421 + char method_name[], MethodMatcher::Mode* m_mode, 1.422 + int* bytes_read, const char*& error_msg) { 1.423 + *bytes_read = 0; 1.424 + error_msg = NULL; 1.425 + for (uint i = 0; i < ARRAY_SIZE(patterns); i++) { 1.426 + if (2 == sscanf(line, patterns[i], class_name, method_name, bytes_read)) { 1.427 + *c_mode = check_mode(class_name, error_msg); 1.428 + *m_mode = check_mode(method_name, error_msg); 1.429 + return *c_mode != MethodMatcher::Unknown && *m_mode != MethodMatcher::Unknown; 1.430 + } 1.431 + } 1.432 + return false; 1.433 +} 1.434 + 1.435 + 1.436 + 1.437 +void CompilerOracle::parse_from_line(char* line) { 1.438 + if (line[0] == '\0') return; 1.439 + if (line[0] == '#') return; 1.440 + 1.441 + bool have_colon = (strstr(line, "::") != NULL); 1.442 + for (char* lp = line; *lp != '\0'; lp++) { 1.443 + // Allow '.' to separate the class name from the method name. 1.444 + // This is the preferred spelling of methods: 1.445 + // exclude java/lang/String.indexOf(I)I 1.446 + // Allow ',' for spaces (eases command line quoting). 1.447 + // exclude,java/lang/String.indexOf 1.448 + // For backward compatibility, allow space as separator also. 1.449 + // exclude java/lang/String indexOf 1.450 + // exclude,java/lang/String,indexOf 1.451 + // For easy cut-and-paste of method names, allow VM output format 1.452 + // as produced by methodOopDesc::print_short_name: 1.453 + // exclude java.lang.String::indexOf 1.454 + // For simple implementation convenience here, convert them all to space. 1.455 + if (have_colon) { 1.456 + if (*lp == '.') *lp = '/'; // dots build the package prefix 1.457 + if (*lp == ':') *lp = ' '; 1.458 + } 1.459 + if (*lp == ',' || *lp == '.') *lp = ' '; 1.460 + } 1.461 + 1.462 + char* original_line = line; 1.463 + int bytes_read; 1.464 + OracleCommand command = parse_command_name(line, &bytes_read); 1.465 + line += bytes_read; 1.466 + 1.467 + if (command == QuietCommand) { 1.468 + _quiet = true; 1.469 + return; 1.470 + } 1.471 + 1.472 + if (command == HelpCommand) { 1.473 + usage(); 1.474 + return; 1.475 + } 1.476 + 1.477 + MethodMatcher::Mode c_match = MethodMatcher::Exact; 1.478 + MethodMatcher::Mode m_match = MethodMatcher::Exact; 1.479 + char class_name[256]; 1.480 + char method_name[256]; 1.481 + char sig[1024]; 1.482 + char errorbuf[1024]; 1.483 + const char* error_msg = NULL; 1.484 + MethodMatcher* match = NULL; 1.485 + 1.486 + if (scan_line(line, class_name, &c_match, method_name, &m_match, &bytes_read, error_msg)) { 1.487 + EXCEPTION_MARK; 1.488 + symbolHandle c_name = oopFactory::new_symbol_handle(class_name, CHECK); 1.489 + symbolHandle m_name = oopFactory::new_symbol_handle(method_name, CHECK); 1.490 + symbolHandle signature; 1.491 + 1.492 + line += bytes_read; 1.493 + // there might be a signature following the method. 1.494 + // signatures always begin with ( so match that by hand 1.495 + if (1 == sscanf(line, "%*[ \t](%254[);/" RANGEBASE "]%n", sig + 1, &bytes_read)) { 1.496 + sig[0] = '('; 1.497 + line += bytes_read; 1.498 + signature = oopFactory::new_symbol_handle(sig, CHECK); 1.499 + } 1.500 + 1.501 + if (command == OptionCommand) { 1.502 + // Look for trailing options to support 1.503 + // ciMethod::has_option("string") to control features in the 1.504 + // compiler. Multiple options may follow the method name. 1.505 + char option[256]; 1.506 + while (sscanf(line, "%*[ \t]%255[a-zA-Z0-9]%n", option, &bytes_read) == 1) { 1.507 + if (match != NULL && !_quiet) { 1.508 + // Print out the last match added 1.509 + tty->print("CompilerOracle: %s ", command_names[command]); 1.510 + match->print(); 1.511 + } 1.512 + match = add_option_string(c_name, c_match, m_name, m_match, signature, strdup(option)); 1.513 + line += bytes_read; 1.514 + } 1.515 + } else { 1.516 + bytes_read = 0; 1.517 + sscanf(line, "%*[ \t]%n", &bytes_read); 1.518 + if (line[bytes_read] != '\0') { 1.519 + jio_snprintf(errorbuf, sizeof(errorbuf), " Unrecognized text after command: %s", line); 1.520 + error_msg = errorbuf; 1.521 + } else { 1.522 + match = add_predicate(command, c_name, c_match, m_name, m_match, signature); 1.523 + } 1.524 + } 1.525 + } 1.526 + 1.527 + if (match != NULL) { 1.528 + if (!_quiet) { 1.529 + tty->print("CompilerOracle: %s ", command_names[command]); 1.530 + match->print(); 1.531 + } 1.532 + } else { 1.533 + tty->print_cr("CompilerOracle: unrecognized line"); 1.534 + tty->print_cr(" \"%s\"", original_line); 1.535 + if (error_msg != NULL) { 1.536 + tty->print_cr(error_msg); 1.537 + } 1.538 + } 1.539 +} 1.540 + 1.541 +static const char* cc_file() { 1.542 + if (CompileCommandFile == NULL) 1.543 + return ".hotspot_compiler"; 1.544 + return CompileCommandFile; 1.545 +} 1.546 +bool CompilerOracle::_quiet = false; 1.547 + 1.548 +void CompilerOracle::parse_from_file() { 1.549 + FILE* stream = fopen(cc_file(), "rt"); 1.550 + if (stream == NULL) return; 1.551 + 1.552 + char token[1024]; 1.553 + int pos = 0; 1.554 + int c = getc(stream); 1.555 + while(c != EOF) { 1.556 + if (c == '\n') { 1.557 + token[pos++] = '\0'; 1.558 + parse_from_line(token); 1.559 + pos = 0; 1.560 + } else { 1.561 + token[pos++] = c; 1.562 + } 1.563 + c = getc(stream); 1.564 + } 1.565 + token[pos++] = '\0'; 1.566 + parse_from_line(token); 1.567 + 1.568 + fclose(stream); 1.569 +} 1.570 + 1.571 +void CompilerOracle::parse_from_string(const char* str, void (*parse_line)(char*)) { 1.572 + char token[1024]; 1.573 + int pos = 0; 1.574 + const char* sp = str; 1.575 + int c = *sp++; 1.576 + while (c != '\0') { 1.577 + if (c == '\n') { 1.578 + token[pos++] = '\0'; 1.579 + parse_line(token); 1.580 + pos = 0; 1.581 + } else { 1.582 + token[pos++] = c; 1.583 + } 1.584 + c = *sp++; 1.585 + } 1.586 + token[pos++] = '\0'; 1.587 + parse_line(token); 1.588 +} 1.589 + 1.590 +void CompilerOracle::append_comment_to_file(const char* message) { 1.591 + fileStream stream(fopen(cc_file(), "at")); 1.592 + stream.print("# "); 1.593 + for (int index = 0; message[index] != '\0'; index++) { 1.594 + stream.put(message[index]); 1.595 + if (message[index] == '\n') stream.print("# "); 1.596 + } 1.597 + stream.cr(); 1.598 +} 1.599 + 1.600 +void CompilerOracle::append_exclude_to_file(methodHandle method) { 1.601 + fileStream stream(fopen(cc_file(), "at")); 1.602 + stream.print("exclude "); 1.603 + Klass::cast(method->method_holder())->name()->print_symbol_on(&stream); 1.604 + stream.print("."); 1.605 + method->name()->print_symbol_on(&stream); 1.606 + method->signature()->print_symbol_on(&stream); 1.607 + stream.cr(); 1.608 + stream.cr(); 1.609 +} 1.610 + 1.611 + 1.612 +void compilerOracle_init() { 1.613 + CompilerOracle::parse_from_string(CompileCommand, CompilerOracle::parse_from_line); 1.614 + CompilerOracle::parse_from_string(CompileOnly, CompilerOracle::parse_compile_only); 1.615 + CompilerOracle::parse_from_file(); 1.616 +} 1.617 + 1.618 + 1.619 +void CompilerOracle::parse_compile_only(char * line) { 1.620 + int i; 1.621 + char name[1024]; 1.622 + const char* className = NULL; 1.623 + const char* methodName = NULL; 1.624 + 1.625 + bool have_colon = (strstr(line, "::") != NULL); 1.626 + char method_sep = have_colon ? ':' : '.'; 1.627 + 1.628 + if (Verbose) { 1.629 + tty->print_cr(line); 1.630 + } 1.631 + 1.632 + ResourceMark rm; 1.633 + while (*line != '\0') { 1.634 + MethodMatcher::Mode c_match = MethodMatcher::Exact; 1.635 + MethodMatcher::Mode m_match = MethodMatcher::Exact; 1.636 + 1.637 + for (i = 0; 1.638 + i < 1024 && *line != '\0' && *line != method_sep && *line != ',' && !isspace(*line); 1.639 + line++, i++) { 1.640 + name[i] = *line; 1.641 + if (name[i] == '.') name[i] = '/'; // package prefix uses '/' 1.642 + } 1.643 + 1.644 + if (i > 0) { 1.645 + char* newName = NEW_RESOURCE_ARRAY( char, i + 1); 1.646 + if (newName == NULL) 1.647 + return; 1.648 + strncpy(newName, name, i); 1.649 + newName[i] = '\0'; 1.650 + 1.651 + if (className == NULL) { 1.652 + className = newName; 1.653 + c_match = MethodMatcher::Prefix; 1.654 + } else { 1.655 + methodName = newName; 1.656 + } 1.657 + } 1.658 + 1.659 + if (*line == method_sep) { 1.660 + if (className == NULL) { 1.661 + className = ""; 1.662 + c_match = MethodMatcher::Any; 1.663 + } else { 1.664 + // foo/bar.blah is an exact match on foo/bar, bar.blah is a suffix match on bar 1.665 + if (strchr(className, '/') != NULL) { 1.666 + c_match = MethodMatcher::Exact; 1.667 + } else { 1.668 + c_match = MethodMatcher::Suffix; 1.669 + } 1.670 + } 1.671 + } else { 1.672 + // got foo or foo/bar 1.673 + if (className == NULL) { 1.674 + ShouldNotReachHere(); 1.675 + } else { 1.676 + // got foo or foo/bar 1.677 + if (strchr(className, '/') != NULL) { 1.678 + c_match = MethodMatcher::Prefix; 1.679 + } else if (className[0] == '\0') { 1.680 + c_match = MethodMatcher::Any; 1.681 + } else { 1.682 + c_match = MethodMatcher::Substring; 1.683 + } 1.684 + } 1.685 + } 1.686 + 1.687 + // each directive is terminated by , or NUL or . followed by NUL 1.688 + if (*line == ',' || *line == '\0' || (line[0] == '.' && line[1] == '\0')) { 1.689 + if (methodName == NULL) { 1.690 + methodName = ""; 1.691 + if (*line != method_sep) { 1.692 + m_match = MethodMatcher::Any; 1.693 + } 1.694 + } 1.695 + 1.696 + EXCEPTION_MARK; 1.697 + symbolHandle c_name = oopFactory::new_symbol_handle(className, CHECK); 1.698 + symbolHandle m_name = oopFactory::new_symbol_handle(methodName, CHECK); 1.699 + symbolHandle signature; 1.700 + 1.701 + add_predicate(CompileOnlyCommand, c_name, c_match, m_name, m_match, signature); 1.702 + if (PrintVMOptions) { 1.703 + tty->print("CompileOnly: compileonly "); 1.704 + lists[CompileOnlyCommand]->print(); 1.705 + } 1.706 + 1.707 + className = NULL; 1.708 + methodName = NULL; 1.709 + } 1.710 + 1.711 + line = *line == '\0' ? line : line + 1; 1.712 + } 1.713 +}