src/share/vm/compiler/compilerOracle.cpp

changeset 0
f90c822e73f8
child 6876
710a3c8b516e
     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 +}

mercurial