1 /* 2 * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "compiler/compilerOracle.hpp" 27 #include "compiler/methodMatcher.hpp" 28 #include "memory/allocation.inline.hpp" 29 #include "memory/oopFactory.hpp" 30 #include "memory/resourceArea.hpp" 31 #include "oops/klass.hpp" 32 #include "oops/method.hpp" 33 #include "oops/symbol.hpp" 34 #include "runtime/handles.inline.hpp" 35 #include "runtime/jniHandles.hpp" 36 #include "runtime/os.hpp" 37 38 enum OptionType { 39 IntxType, 40 UintxType, 41 BoolType, 42 CcstrType, 43 DoubleType, 44 UnknownType 45 }; 46 47 /* Methods to map real type names to OptionType */ 48 template<typename T> 49 static OptionType get_type_for() { 50 return UnknownType; 51 }; 52 53 template<> OptionType get_type_for<intx>() { 54 return IntxType; 55 } 56 57 template<> OptionType get_type_for<uintx>() { 58 return UintxType; 59 } 60 61 template<> OptionType get_type_for<bool>() { 62 return BoolType; 63 } 64 65 template<> OptionType get_type_for<ccstr>() { 66 return CcstrType; 67 } 68 69 template<> OptionType get_type_for<double>() { 70 return DoubleType; 71 } 72 73 // this must parallel the command_names below 74 enum OracleCommand { 75 UnknownCommand = -1, 76 OracleFirstCommand = 0, 77 BreakCommand = OracleFirstCommand, 78 PrintCommand, 79 ExcludeCommand, 80 InlineCommand, 81 DontInlineCommand, 82 CompileOnlyCommand, 83 LogCommand, 84 OptionCommand, 85 QuietCommand, 86 HelpCommand, 87 OracleCommandCount 88 }; 89 90 // this must parallel the enum OracleCommand 91 static const char * command_names[] = { 92 "break", 93 "print", 94 "exclude", 95 "inline", 96 "dontinline", 97 "compileonly", 98 "log", 99 "option", 100 "quiet", 101 "help" 102 }; 103 104 class MethodMatcher; 105 class TypedMethodOptionMatcher; 106 107 static BasicMatcher* lists[OracleCommandCount] = { 0, }; 108 static TypedMethodOptionMatcher* option_list = NULL; 109 static bool any_set = false; 110 111 class TypedMethodOptionMatcher : public MethodMatcher { 112 private: 113 TypedMethodOptionMatcher* _next; 114 const char* _option; 115 OptionType _type; 116 public: 117 118 union { 119 bool bool_value; 120 intx intx_value; 121 uintx uintx_value; 122 double double_value; 123 ccstr ccstr_value; 124 } _u; 125 126 TypedMethodOptionMatcher() : MethodMatcher(), 127 _next(NULL), 128 _type(UnknownType) { 129 _option = NULL; 130 memset(&_u, 0, sizeof(_u)); 131 } 132 133 static TypedMethodOptionMatcher* parse_method_pattern(char*& line, const char*& error_msg); 134 TypedMethodOptionMatcher* match(methodHandle method, const char* opt, OptionType type); 135 136 void init(const char* opt, OptionType type, TypedMethodOptionMatcher* next) { 137 _next = next; 138 _type = type; 139 _option = os::strdup_check_oom(opt); 140 } 141 142 void set_next(TypedMethodOptionMatcher* next) {_next = next; } 143 TypedMethodOptionMatcher* next() { return _next; } 144 OptionType type() { return _type; } 145 template<typename T> T value(); 146 template<typename T> void set_value(T value); 147 void print(); 148 void print_all(); 149 TypedMethodOptionMatcher* clone(); 150 ~TypedMethodOptionMatcher(); 151 }; 152 153 // A few templated accessors instead of a full template class. 154 template<> intx TypedMethodOptionMatcher::value<intx>() { 155 return _u.intx_value; 156 } 157 158 template<> uintx TypedMethodOptionMatcher::value<uintx>() { 159 return _u.uintx_value; 160 } 161 162 template<> bool TypedMethodOptionMatcher::value<bool>() { 163 return _u.bool_value; 164 } 165 166 template<> double TypedMethodOptionMatcher::value<double>() { 167 return _u.double_value; 168 } 169 170 template<> ccstr TypedMethodOptionMatcher::value<ccstr>() { 171 return _u.ccstr_value; 172 } 173 174 template<> void TypedMethodOptionMatcher::set_value(intx value) { 175 _u.intx_value = value; 176 } 177 178 template<> void TypedMethodOptionMatcher::set_value(uintx value) { 179 _u.uintx_value = value; 180 } 181 182 template<> void TypedMethodOptionMatcher::set_value(double value) { 183 _u.double_value = value; 184 } 185 186 template<> void TypedMethodOptionMatcher::set_value(bool value) { 187 _u.bool_value = value; 188 } 189 190 template<> void TypedMethodOptionMatcher::set_value(ccstr value) { 191 _u.ccstr_value = (const ccstr)os::strdup_check_oom(value); 192 } 193 194 void TypedMethodOptionMatcher::print() { 195 ttyLocker ttyl; 196 print_base(tty); 197 switch (_type) { 198 case IntxType: 199 tty->print_cr(" intx %s = " INTX_FORMAT, _option, value<intx>()); 200 break; 201 case UintxType: 202 tty->print_cr(" uintx %s = " UINTX_FORMAT, _option, value<uintx>()); 203 break; 204 case BoolType: 205 tty->print_cr(" bool %s = %s", _option, value<bool>() ? "true" : "false"); 206 break; 207 case DoubleType: 208 tty->print_cr(" double %s = %f", _option, value<double>()); 209 break; 210 case CcstrType: 211 tty->print_cr(" const char* %s = '%s'", _option, value<ccstr>()); 212 break; 213 default: 214 ShouldNotReachHere(); 215 } 216 } 217 218 void TypedMethodOptionMatcher::print_all() { 219 print(); 220 if (_next != NULL) { 221 tty->print(" "); 222 _next->print_all(); 223 } 224 } 225 226 TypedMethodOptionMatcher* TypedMethodOptionMatcher::clone() { 227 TypedMethodOptionMatcher* m = new TypedMethodOptionMatcher(); 228 m->_class_mode = _class_mode; 229 m->_class_name = _class_name; 230 m->_method_mode = _method_mode; 231 m->_method_name = _method_name; 232 m->_signature = _signature; 233 // Need to ref count the symbols 234 if (_class_name != NULL) { 235 _class_name->increment_refcount(); 236 } 237 if (_method_name != NULL) { 238 _method_name->increment_refcount(); 239 } 240 if (_signature != NULL) { 241 _signature->increment_refcount(); 242 } 243 return m; 244 } 245 246 TypedMethodOptionMatcher::~TypedMethodOptionMatcher() { 247 if (_option != NULL) { 248 os::free((void*)_option); 249 } 250 } 251 252 TypedMethodOptionMatcher* TypedMethodOptionMatcher::parse_method_pattern(char*& line, const char*& error_msg) { 253 assert(error_msg == NULL, "Dont call here with error_msg already set"); 254 TypedMethodOptionMatcher* tom = new TypedMethodOptionMatcher(); 255 MethodMatcher::parse_method_pattern(line, error_msg, tom); 256 if (error_msg != NULL) { 257 delete tom; 258 return NULL; 259 } 260 return tom; 261 } 262 263 TypedMethodOptionMatcher* TypedMethodOptionMatcher::match(methodHandle method, const char* opt, OptionType type) { 264 TypedMethodOptionMatcher* current = this; 265 while (current != NULL) { 266 // Fastest compare first. 267 if (current->type() == type) { 268 if (strcmp(current->_option, opt) == 0) { 269 if (current->matches(method)) { 270 return current; 271 } 272 } 273 } 274 current = current->next(); 275 } 276 return NULL; 277 } 278 279 template<typename T> 280 static void add_option_string(TypedMethodOptionMatcher* matcher, 281 const char* option, 282 T value) { 283 assert(matcher != option_list, "No circular lists please"); 284 matcher->init(option, get_type_for<T>(), option_list); 285 matcher->set_value<T>(value); 286 option_list = matcher; 287 any_set = true; 288 return; 289 } 290 291 static bool check_predicate(OracleCommand command, methodHandle method) { 292 return ((lists[command] != NULL) && 293 !method.is_null() && 294 lists[command]->match(method)); 295 } 296 297 static void add_predicate(OracleCommand command, BasicMatcher* bm) { 298 assert(command != OptionCommand, "must use add_option_string"); 299 if (command == LogCommand && !LogCompilation && lists[LogCommand] == NULL) { 300 tty->print_cr("Warning: +LogCompilation must be enabled in order for individual methods to be logged."); 301 } 302 bm->set_next(lists[command]); 303 lists[command] = bm; 304 if ((command != DontInlineCommand) && (command != InlineCommand)) { 305 any_set = true; 306 } 307 return; 308 } 309 310 template<typename T> 311 bool CompilerOracle::has_option_value(const methodHandle& method, const char* option, T& value) { 312 if (option_list != NULL) { 313 TypedMethodOptionMatcher* m = option_list->match(method, option, get_type_for<T>()); 314 if (m != NULL) { 315 value = m->value<T>(); 316 return true; 317 } 318 } 319 return false; 320 } 321 322 bool CompilerOracle::has_any_option() { 323 return any_set; 324 } 325 326 // Explicit instantiation for all OptionTypes supported. 327 template bool CompilerOracle::has_option_value<intx>(const methodHandle& method, const char* option, intx& value); 328 template bool CompilerOracle::has_option_value<uintx>(const methodHandle& method, const char* option, uintx& value); 329 template bool CompilerOracle::has_option_value<bool>(const methodHandle& method, const char* option, bool& value); 330 template bool CompilerOracle::has_option_value<ccstr>(const methodHandle& method, const char* option, ccstr& value); 331 template bool CompilerOracle::has_option_value<double>(const methodHandle& method, const char* option, double& value); 332 333 bool CompilerOracle::has_option_string(const methodHandle& method, const char* option) { 334 bool value = false; 335 has_option_value(method, option, value); 336 return value; 337 } 338 339 bool CompilerOracle::should_exclude(const methodHandle& method) { 340 if (check_predicate(ExcludeCommand, method)) { 341 return true; 342 } 343 if (lists[CompileOnlyCommand] != NULL) { 344 return !lists[CompileOnlyCommand]->match(method); 345 } 346 return false; 347 } 348 349 bool CompilerOracle::should_inline(const methodHandle& method) { 350 return (check_predicate(InlineCommand, method)); 351 } 352 353 bool CompilerOracle::should_not_inline(const methodHandle& method) { 354 return check_predicate(DontInlineCommand, method) || check_predicate(ExcludeCommand, method); 355 } 356 357 bool CompilerOracle::should_print(const methodHandle& method) { 358 return check_predicate(PrintCommand, method); 359 } 360 361 bool CompilerOracle::should_print_methods() { 362 return lists[PrintCommand] != NULL; 363 } 364 365 bool CompilerOracle::should_log(const methodHandle& method) { 366 if (!LogCompilation) return false; 367 if (lists[LogCommand] == NULL) return true; // by default, log all 368 return (check_predicate(LogCommand, method)); 369 } 370 371 bool CompilerOracle::should_break_at(const methodHandle& method) { 372 return check_predicate(BreakCommand, method); 373 } 374 375 static OracleCommand parse_command_name(const char * line, int* bytes_read) { 376 assert(ARRAY_SIZE(command_names) == OracleCommandCount, 377 "command_names size mismatch"); 378 379 *bytes_read = 0; 380 char command[33]; 381 int result = sscanf(line, "%32[a-z]%n", command, bytes_read); 382 for (uint i = 0; i < ARRAY_SIZE(command_names); i++) { 383 if (strcmp(command, command_names[i]) == 0) { 384 return (OracleCommand)i; 385 } 386 } 387 return UnknownCommand; 388 } 389 390 static void usage() { 391 tty->cr(); 392 tty->print_cr("The CompileCommand option enables the user of the JVM to control specific"); 393 tty->print_cr("behavior of the dynamic compilers. Many commands require a pattern that defines"); 394 tty->print_cr("the set of methods the command shall be applied to. The CompileCommand"); 395 tty->print_cr("option provides the following commands:"); 396 tty->cr(); 397 tty->print_cr(" break,<pattern> - debug breakpoint in compiler and in generated code"); 398 tty->print_cr(" print,<pattern> - print assembly"); 399 tty->print_cr(" exclude,<pattern> - don't compile or inline"); 400 tty->print_cr(" inline,<pattern> - always inline"); 401 tty->print_cr(" dontinline,<pattern> - don't inline"); 402 tty->print_cr(" compileonly,<pattern> - compile only"); 403 tty->print_cr(" log,<pattern> - log compilation"); 404 tty->print_cr(" option,<pattern>,<option type>,<option name>,<value>"); 405 tty->print_cr(" - set value of custom option"); 406 tty->print_cr(" option,<pattern>,<bool option name>"); 407 tty->print_cr(" - shorthand for setting boolean flag"); 408 tty->print_cr(" quiet - silence the compile command output"); 409 tty->print_cr(" help - print this text"); 410 tty->cr(); 411 tty->print_cr("The preferred format for the method matching pattern is:"); 412 tty->print_cr(" package/Class.method()"); 413 tty->cr(); 414 tty->print_cr("For backward compatibility this form is also allowed:"); 415 tty->print_cr(" package.Class::method()"); 416 tty->cr(); 417 tty->print_cr("The signature can be separated by an optional whitespace or comma:"); 418 tty->print_cr(" package/Class.method ()"); 419 tty->cr(); 420 tty->print_cr("The class and method identifier can be used together with leading or"); 421 tty->print_cr("trailing *'s for a small amount of wildcarding:"); 422 tty->print_cr(" *ackage/Clas*.*etho*()"); 423 tty->cr(); 424 tty->print_cr("It is possible to use more than one CompileCommand on the command line:"); 425 tty->print_cr(" -XX:CompileCommand=exclude,java/*.* -XX:CompileCommand=log,java*.*"); 426 tty->cr(); 427 tty->print_cr("The CompileCommands can be loaded from a file with the flag"); 428 tty->print_cr("-XX:CompileCommandFile=<file> or be added to the file '.hotspot_compiler'"); 429 tty->print_cr("Use the same format in the file as the argument to the CompileCommand flag."); 430 tty->print_cr("Add one command on each line."); 431 tty->print_cr(" exclude java/*.*"); 432 tty->print_cr(" option java/*.* ReplayInline"); 433 tty->cr(); 434 tty->print_cr("The following commands have conflicting behavior: 'exclude', 'inline', 'dontinline',"); 435 tty->print_cr("and 'compileonly'. There is no priority of commands. Applying (a subset of) these"); 436 tty->print_cr("commands to the same method results in undefined behavior."); 437 tty->cr(); 438 }; 439 440 // Scan next flag and value in line, return MethodMatcher object on success, NULL on failure. 441 // On failure, error_msg contains description for the first error. 442 // For future extensions: set error_msg on first error. 443 static void scan_flag_and_value(const char* type, const char* line, int& total_bytes_read, 444 TypedMethodOptionMatcher* matcher, 445 char* errorbuf, const int buf_size) { 446 total_bytes_read = 0; 447 int bytes_read = 0; 448 char flag[256]; 449 450 // Read flag name. 451 if (sscanf(line, "%*[ \t]%255[a-zA-Z0-9]%n", flag, &bytes_read) == 1) { 452 line += bytes_read; 453 total_bytes_read += bytes_read; 454 455 // Read value. 456 if (strcmp(type, "intx") == 0) { 457 intx value; 458 if (sscanf(line, "%*[ \t]" INTX_FORMAT "%n", &value, &bytes_read) == 1) { 459 total_bytes_read += bytes_read; 460 add_option_string(matcher, flag, value); 461 return; 462 } else { 463 jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s ", flag, type); 464 } 465 } else if (strcmp(type, "uintx") == 0) { 466 uintx value; 467 if (sscanf(line, "%*[ \t]" UINTX_FORMAT "%n", &value, &bytes_read) == 1) { 468 total_bytes_read += bytes_read; 469 add_option_string(matcher, flag, value); 470 return; 471 } else { 472 jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type); 473 } 474 } else if (strcmp(type, "ccstr") == 0) { 475 ResourceMark rm; 476 char* value = NEW_RESOURCE_ARRAY(char, strlen(line) + 1); 477 if (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9]%n", value, &bytes_read) == 1) { 478 total_bytes_read += bytes_read; 479 add_option_string(matcher, flag, (ccstr)value); 480 return; 481 } else { 482 jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type); 483 } 484 } else if (strcmp(type, "ccstrlist") == 0) { 485 // Accumulates several strings into one. The internal type is ccstr. 486 ResourceMark rm; 487 char* value = NEW_RESOURCE_ARRAY(char, strlen(line) + 1); 488 char* next_value = value; 489 if (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9]%n", next_value, &bytes_read) == 1) { 490 total_bytes_read += bytes_read; 491 line += bytes_read; 492 next_value += bytes_read; 493 char* end_value = next_value-1; 494 while (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9]%n", next_value, &bytes_read) == 1) { 495 total_bytes_read += bytes_read; 496 line += bytes_read; 497 *end_value = ' '; // override '\0' 498 next_value += bytes_read; 499 end_value = next_value-1; 500 } 501 add_option_string(matcher, flag, (ccstr)value); 502 return; 503 } else { 504 jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type); 505 } 506 } else if (strcmp(type, "bool") == 0) { 507 char value[256]; 508 if (sscanf(line, "%*[ \t]%255[a-zA-Z]%n", value, &bytes_read) == 1) { 509 if (strcmp(value, "true") == 0) { 510 total_bytes_read += bytes_read; 511 add_option_string(matcher, flag, true); 512 return; 513 } else if (strcmp(value, "false") == 0) { 514 total_bytes_read += bytes_read; 515 add_option_string(matcher, flag, false); 516 return; 517 } else { 518 jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type); 519 } 520 } else { 521 jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type); 522 } 523 } else if (strcmp(type, "double") == 0) { 524 char buffer[2][256]; 525 // Decimal separator '.' has been replaced with ' ' or '/' earlier, 526 // so read integer and fraction part of double value separately. 527 if (sscanf(line, "%*[ \t]%255[0-9]%*[ /\t]%255[0-9]%n", buffer[0], buffer[1], &bytes_read) == 2) { 528 char value[512] = ""; 529 jio_snprintf(value, sizeof(value), "%s.%s", buffer[0], buffer[1]); 530 total_bytes_read += bytes_read; 531 add_option_string(matcher, flag, atof(value)); 532 return; 533 } else { 534 jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type); 535 } 536 } else { 537 jio_snprintf(errorbuf, buf_size, " Type %s not supported ", type); 538 } 539 } else { 540 jio_snprintf(errorbuf, buf_size, " Flag name for type %s should be alphanumeric ", type); 541 } 542 return; 543 } 544 545 int skip_whitespace(char* line) { 546 // Skip any leading spaces 547 int whitespace_read = 0; 548 sscanf(line, "%*[ \t]%n", &whitespace_read); 549 return whitespace_read; 550 } 551 552 void CompilerOracle::print_parse_error(const char*& error_msg, char* original_line) { 553 assert(error_msg != NULL, "Must have error_message"); 554 555 ttyLocker ttyl; 556 tty->print_cr("CompileCommand: An error occurred during parsing"); 557 tty->print_cr("Line: %s", original_line); 558 tty->print_cr("Error: %s", error_msg); 559 CompilerOracle::print_tip(); 560 } 561 562 void CompilerOracle::parse_from_line(char* line) { 563 if (line[0] == '\0') return; 564 if (line[0] == '#') return; 565 566 char* original_line = line; 567 int bytes_read; 568 OracleCommand command = parse_command_name(line, &bytes_read); 569 line += bytes_read; 570 ResourceMark rm; 571 572 if (command == UnknownCommand) { 573 ttyLocker ttyl; 574 tty->print_cr("CompileCommand: unrecognized command"); 575 tty->print_cr(" \"%s\"", original_line); 576 CompilerOracle::print_tip(); 577 return; 578 } 579 580 if (command == QuietCommand) { 581 _quiet = true; 582 return; 583 } 584 585 if (command == HelpCommand) { 586 usage(); 587 return; 588 } 589 590 const char* error_msg = NULL; 591 if (command == OptionCommand) { 592 // Look for trailing options. 593 // 594 // Two types of trailing options are 595 // supported: 596 // 597 // (1) CompileCommand=option,Klass::method,flag 598 // (2) CompileCommand=option,Klass::method,type,flag,value 599 // 600 // Type (1) is used to enable a boolean flag for a method. 601 // 602 // Type (2) is used to support options with a value. Values can have the 603 // the following types: intx, uintx, bool, ccstr, ccstrlist, and double. 604 // 605 // For future extensions: extend scan_flag_and_value() 606 607 char option[256]; // stores flag for Type (1) and type of Type (2) 608 line++; // skip the ',' 609 TypedMethodOptionMatcher* archetype = TypedMethodOptionMatcher::parse_method_pattern(line, error_msg); 610 if (archetype == NULL) { 611 assert(error_msg != NULL, "Must have error_message"); 612 print_parse_error(error_msg, original_line); 613 return; 614 } 615 616 line += skip_whitespace(line); 617 618 // This is unnecessarily complex. Should retire multi-option lines and skip while loop 619 while (sscanf(line, "%255[a-zA-Z0-9]%n", option, &bytes_read) == 1) { 620 line += bytes_read; 621 622 // typed_matcher is used as a blueprint for each option, deleted at the end 623 TypedMethodOptionMatcher* typed_matcher = archetype->clone(); 624 if (strcmp(option, "intx") == 0 625 || strcmp(option, "uintx") == 0 626 || strcmp(option, "bool") == 0 627 || strcmp(option, "ccstr") == 0 628 || strcmp(option, "ccstrlist") == 0 629 || strcmp(option, "double") == 0 630 ) { 631 char errorbuf[1024] = {0}; 632 // Type (2) option: parse flag name and value. 633 scan_flag_and_value(option, line, bytes_read, typed_matcher, errorbuf, sizeof(errorbuf)); 634 if (*errorbuf != '\0') { 635 error_msg = errorbuf; 636 print_parse_error(error_msg, original_line); 637 return; 638 } 639 line += bytes_read; 640 } else { 641 // Type (1) option 642 add_option_string(typed_matcher, option, true); 643 } 644 if (typed_matcher != NULL && !_quiet) { 645 // Print out the last match added 646 assert(error_msg == NULL, "No error here"); 647 ttyLocker ttyl; 648 tty->print("CompileCommand: %s ", command_names[command]); 649 typed_matcher->print(); 650 } 651 line += skip_whitespace(line); 652 } // while( 653 delete archetype; 654 } else { // not an OptionCommand) 655 assert(error_msg == NULL, "Don't call here with error_msg already set"); 656 657 BasicMatcher* matcher = BasicMatcher::parse_method_pattern(line, error_msg); 658 if (error_msg != NULL) { 659 assert(matcher == NULL, "consistency"); 660 print_parse_error(error_msg, original_line); 661 return; 662 } 663 664 add_predicate(command, matcher); 665 if (!_quiet) { 666 ttyLocker ttyl; 667 tty->print("CompileCommand: %s ", command_names[command]); 668 matcher->print(tty); 669 tty->cr(); 670 } 671 } 672 } 673 674 void CompilerOracle::print_tip() { 675 tty->cr(); 676 tty->print_cr("Usage: '-XX:CompileCommand=command,\"package/Class.method()\"'"); 677 tty->print_cr("Use: '-XX:CompileCommand=help' for more information."); 678 tty->cr(); 679 } 680 681 static const char* default_cc_file = ".hotspot_compiler"; 682 683 static const char* cc_file() { 684 #ifdef ASSERT 685 if (CompileCommandFile == NULL) 686 return default_cc_file; 687 #endif 688 return CompileCommandFile; 689 } 690 691 bool CompilerOracle::has_command_file() { 692 return cc_file() != NULL; 693 } 694 695 bool CompilerOracle::_quiet = false; 696 697 void CompilerOracle::parse_from_file() { 698 assert(has_command_file(), "command file must be specified"); 699 FILE* stream = fopen(cc_file(), "rt"); 700 if (stream == NULL) return; 701 702 char token[1024]; 703 int pos = 0; 704 int c = getc(stream); 705 while(c != EOF && pos < (int)(sizeof(token)-1)) { 706 if (c == '\n') { 707 token[pos++] = '\0'; 708 parse_from_line(token); 709 pos = 0; 710 } else { 711 token[pos++] = c; 712 } 713 c = getc(stream); 714 } 715 token[pos++] = '\0'; 716 parse_from_line(token); 717 718 fclose(stream); 719 } 720 721 void CompilerOracle::parse_from_string(const char* str, void (*parse_line)(char*)) { 722 char token[1024]; 723 int pos = 0; 724 const char* sp = str; 725 int c = *sp++; 726 while (c != '\0' && pos < (int)(sizeof(token)-1)) { 727 if (c == '\n') { 728 token[pos++] = '\0'; 729 parse_line(token); 730 pos = 0; 731 } else { 732 token[pos++] = c; 733 } 734 c = *sp++; 735 } 736 token[pos++] = '\0'; 737 parse_line(token); 738 } 739 740 void CompilerOracle::append_comment_to_file(const char* message) { 741 assert(has_command_file(), "command file must be specified"); 742 fileStream stream(fopen(cc_file(), "at")); 743 stream.print("# "); 744 for (int index = 0; message[index] != '\0'; index++) { 745 stream.put(message[index]); 746 if (message[index] == '\n') stream.print("# "); 747 } 748 stream.cr(); 749 } 750 751 void CompilerOracle::append_exclude_to_file(const methodHandle& method) { 752 assert(has_command_file(), "command file must be specified"); 753 fileStream stream(fopen(cc_file(), "at")); 754 stream.print("exclude "); 755 method->method_holder()->name()->print_symbol_on(&stream); 756 stream.print("."); 757 method->name()->print_symbol_on(&stream); 758 method->signature()->print_symbol_on(&stream); 759 stream.cr(); 760 stream.cr(); 761 } 762 763 764 void compilerOracle_init() { 765 CompilerOracle::parse_from_string(CompileCommand, CompilerOracle::parse_from_line); 766 CompilerOracle::parse_from_string(CompileOnly, CompilerOracle::parse_compile_only); 767 if (CompilerOracle::has_command_file()) { 768 CompilerOracle::parse_from_file(); 769 } else { 770 struct stat buf; 771 if (os::stat(default_cc_file, &buf) == 0) { 772 warning("%s file is present but has been ignored. " 773 "Run with -XX:CompileCommandFile=%s to load the file.", 774 default_cc_file, default_cc_file); 775 } 776 } 777 if (lists[PrintCommand] != NULL) { 778 if (PrintAssembly) { 779 warning("CompileCommand and/or %s file contains 'print' commands, but PrintAssembly is also enabled", default_cc_file); 780 } else if (FLAG_IS_DEFAULT(DebugNonSafepoints)) { 781 warning("printing of assembly code is enabled; turning on DebugNonSafepoints to gain additional output"); 782 DebugNonSafepoints = true; 783 } 784 } 785 } 786 787 788 void CompilerOracle::parse_compile_only(char * line) { 789 int i; 790 char name[1024]; 791 const char* className = NULL; 792 const char* methodName = NULL; 793 794 bool have_colon = (strstr(line, "::") != NULL); 795 char method_sep = have_colon ? ':' : '.'; 796 797 if (Verbose) { 798 tty->print_cr("%s", line); 799 } 800 801 ResourceMark rm; 802 while (*line != '\0') { 803 MethodMatcher::Mode c_match = MethodMatcher::Exact; 804 MethodMatcher::Mode m_match = MethodMatcher::Exact; 805 806 for (i = 0; 807 i < 1024 && *line != '\0' && *line != method_sep && *line != ',' && !isspace(*line); 808 line++, i++) { 809 name[i] = *line; 810 if (name[i] == '.') name[i] = '/'; // package prefix uses '/' 811 } 812 813 if (i > 0) { 814 char* newName = NEW_RESOURCE_ARRAY( char, i + 1); 815 if (newName == NULL) 816 return; 817 strncpy(newName, name, i); 818 newName[i] = '\0'; 819 820 if (className == NULL) { 821 className = newName; 822 } else { 823 methodName = newName; 824 } 825 } 826 827 if (*line == method_sep) { 828 if (className == NULL) { 829 className = ""; 830 c_match = MethodMatcher::Any; 831 } 832 } else { 833 // got foo or foo/bar 834 if (className == NULL) { 835 ShouldNotReachHere(); 836 } else { 837 // missing class name handled as "Any" class match 838 if (className[0] == '\0') { 839 c_match = MethodMatcher::Any; 840 } 841 } 842 } 843 844 // each directive is terminated by , or NUL or . followed by NUL 845 if (*line == ',' || *line == '\0' || (line[0] == '.' && line[1] == '\0')) { 846 if (methodName == NULL) { 847 methodName = ""; 848 if (*line != method_sep) { 849 m_match = MethodMatcher::Any; 850 } 851 } 852 853 EXCEPTION_MARK; 854 Symbol* c_name = SymbolTable::new_symbol(className, CHECK); 855 Symbol* m_name = SymbolTable::new_symbol(methodName, CHECK); 856 Symbol* signature = NULL; 857 858 BasicMatcher* bm = new BasicMatcher(); 859 bm->init(c_name, c_match, m_name, m_match, signature); 860 add_predicate(CompileOnlyCommand, bm); 861 if (PrintVMOptions) { 862 tty->print("CompileOnly: compileonly "); 863 lists[CompileOnlyCommand]->print_all(tty); 864 } 865 866 className = NULL; 867 methodName = NULL; 868 } 869 870 line = *line == '\0' ? line : line + 1; 871 } 872 }