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