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