compilerOracle.cpp revision 1472:c18cbe5936b8
1/* 2 * Copyright (c) 1998, 2007, 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 "incls/_precompiled.incl" 26#include "incls/_compilerOracle.cpp.incl" 27 28class MethodMatcher : public CHeapObj { 29 public: 30 enum Mode { 31 Exact, 32 Prefix = 1, 33 Suffix = 2, 34 Substring = Prefix | Suffix, 35 Any, 36 Unknown = -1 37 }; 38 39 protected: 40 jobject _class_name; 41 Mode _class_mode; 42 jobject _method_name; 43 Mode _method_mode; 44 jobject _signature; 45 MethodMatcher* _next; 46 47 static bool match(symbolHandle candidate, symbolHandle match, Mode match_mode); 48 49 symbolHandle class_name() const { return (symbolOop)JNIHandles::resolve_non_null(_class_name); } 50 symbolHandle method_name() const { return (symbolOop)JNIHandles::resolve_non_null(_method_name); } 51 symbolHandle signature() const { return (symbolOop)JNIHandles::resolve(_signature); } 52 53 public: 54 MethodMatcher(symbolHandle class_name, Mode class_mode, 55 symbolHandle method_name, Mode method_mode, 56 symbolHandle signature, MethodMatcher* next); 57 MethodMatcher(symbolHandle class_name, symbolHandle method_name, MethodMatcher* next); 58 59 // utility method 60 MethodMatcher* find(methodHandle method) { 61 symbolHandle class_name = Klass::cast(method->method_holder())->name(); 62 symbolHandle method_name = method->name(); 63 for (MethodMatcher* current = this; current != NULL; current = current->_next) { 64 if (match(class_name, current->class_name(), current->_class_mode) && 65 match(method_name, current->method_name(), current->_method_mode) && 66 (current->signature().is_null() || current->signature()() == method->signature())) { 67 return current; 68 } 69 } 70 return NULL; 71 } 72 73 bool match(methodHandle method) { 74 return find(method) != NULL; 75 } 76 77 MethodMatcher* next() const { return _next; } 78 79 static void print_symbol(symbolHandle h, Mode mode) { 80 ResourceMark rm; 81 82 if (mode == Suffix || mode == Substring || mode == Any) { 83 tty->print("*"); 84 } 85 if (mode != Any) { 86 h()->print_symbol_on(tty); 87 } 88 if (mode == Prefix || mode == Substring) { 89 tty->print("*"); 90 } 91 } 92 93 void print_base() { 94 print_symbol(class_name(), _class_mode); 95 tty->print("."); 96 print_symbol(method_name(), _method_mode); 97 if (!signature().is_null()) { 98 tty->print(" "); 99 signature()->print_symbol_on(tty); 100 } 101 } 102 103 virtual void print() { 104 print_base(); 105 tty->cr(); 106 } 107}; 108 109MethodMatcher::MethodMatcher(symbolHandle class_name, symbolHandle method_name, MethodMatcher* next) { 110 _class_name = JNIHandles::make_global(class_name); 111 _method_name = JNIHandles::make_global(method_name); 112 _next = next; 113 _class_mode = MethodMatcher::Exact; 114 _method_mode = MethodMatcher::Exact; 115 _signature = NULL; 116} 117 118 119MethodMatcher::MethodMatcher(symbolHandle class_name, Mode class_mode, 120 symbolHandle method_name, Mode method_mode, 121 symbolHandle signature, MethodMatcher* next): 122 _class_mode(class_mode) 123 , _method_mode(method_mode) 124 , _next(next) 125 , _class_name(JNIHandles::make_global(class_name())) 126 , _method_name(JNIHandles::make_global(method_name())) 127 , _signature(JNIHandles::make_global(signature())) { 128} 129 130bool MethodMatcher::match(symbolHandle candidate, symbolHandle match, Mode match_mode) { 131 if (match_mode == Any) { 132 return true; 133 } 134 135 if (match_mode == Exact) { 136 return candidate() == match(); 137 } 138 139 ResourceMark rm; 140 const char * candidate_string = candidate->as_C_string(); 141 const char * match_string = match->as_C_string(); 142 143 switch (match_mode) { 144 case Prefix: 145 return strstr(candidate_string, match_string) == candidate_string; 146 147 case Suffix: { 148 size_t clen = strlen(candidate_string); 149 size_t mlen = strlen(match_string); 150 return clen >= mlen && strcmp(candidate_string + clen - mlen, match_string) == 0; 151 } 152 153 case Substring: 154 return strstr(candidate_string, match_string) != NULL; 155 156 default: 157 return false; 158 } 159} 160 161 162class MethodOptionMatcher: public MethodMatcher { 163 const char * option; 164 public: 165 MethodOptionMatcher(symbolHandle class_name, Mode class_mode, 166 symbolHandle method_name, Mode method_mode, 167 symbolHandle signature, const char * opt, MethodMatcher* next): 168 MethodMatcher(class_name, class_mode, method_name, method_mode, signature, next) { 169 option = opt; 170 } 171 172 bool match(methodHandle method, const char* opt) { 173 MethodOptionMatcher* current = this; 174 while (current != NULL) { 175 current = (MethodOptionMatcher*)current->find(method); 176 if (current == NULL) { 177 return false; 178 } 179 if (strcmp(current->option, opt) == 0) { 180 return true; 181 } 182 current = current->next(); 183 } 184 return false; 185 } 186 187 MethodOptionMatcher* next() { 188 return (MethodOptionMatcher*)_next; 189 } 190 191 virtual void print() { 192 print_base(); 193 tty->print(" %s", option); 194 tty->cr(); 195 } 196}; 197 198 199 200// this must parallel the command_names below 201enum OracleCommand { 202 UnknownCommand = -1, 203 OracleFirstCommand = 0, 204 BreakCommand = OracleFirstCommand, 205 PrintCommand, 206 ExcludeCommand, 207 InlineCommand, 208 DontInlineCommand, 209 CompileOnlyCommand, 210 LogCommand, 211 OptionCommand, 212 QuietCommand, 213 HelpCommand, 214 OracleCommandCount 215}; 216 217// this must parallel the enum OracleCommand 218static const char * command_names[] = { 219 "break", 220 "print", 221 "exclude", 222 "inline", 223 "dontinline", 224 "compileonly", 225 "log", 226 "option", 227 "quiet", 228 "help" 229}; 230 231static const char * command_name(OracleCommand command) { 232 if (command < OracleFirstCommand || command >= OracleCommandCount) { 233 return "unknown command"; 234 } 235 return command_names[command]; 236} 237 238class MethodMatcher; 239static MethodMatcher* lists[OracleCommandCount] = { 0, }; 240 241 242static bool check_predicate(OracleCommand command, methodHandle method) { 243 return ((lists[command] != NULL) && 244 !method.is_null() && 245 lists[command]->match(method)); 246} 247 248 249static MethodMatcher* add_predicate(OracleCommand command, 250 symbolHandle class_name, MethodMatcher::Mode c_mode, 251 symbolHandle method_name, MethodMatcher::Mode m_mode, 252 symbolHandle signature) { 253 assert(command != OptionCommand, "must use add_option_string"); 254 if (command == LogCommand && !LogCompilation && lists[LogCommand] == NULL) 255 tty->print_cr("Warning: +LogCompilation must be enabled in order for individual methods to be logged."); 256 lists[command] = new MethodMatcher(class_name, c_mode, method_name, m_mode, signature, lists[command]); 257 return lists[command]; 258} 259 260 261 262static MethodMatcher* add_option_string(symbolHandle class_name, MethodMatcher::Mode c_mode, 263 symbolHandle method_name, MethodMatcher::Mode m_mode, 264 symbolHandle signature, 265 const char* option) { 266 lists[OptionCommand] = new MethodOptionMatcher(class_name, c_mode, method_name, m_mode, 267 signature, option, lists[OptionCommand]); 268 return lists[OptionCommand]; 269} 270 271 272bool CompilerOracle::has_option_string(methodHandle method, const char* option) { 273 return lists[OptionCommand] != NULL && 274 ((MethodOptionMatcher*)lists[OptionCommand])->match(method, option); 275} 276 277 278bool CompilerOracle::should_exclude(methodHandle method, bool& quietly) { 279 quietly = true; 280 if (lists[ExcludeCommand] != NULL) { 281 if (lists[ExcludeCommand]->match(method)) { 282 quietly = _quiet; 283 return true; 284 } 285 } 286 287 if (lists[CompileOnlyCommand] != NULL) { 288 return !lists[CompileOnlyCommand]->match(method); 289 } 290 return false; 291} 292 293 294bool CompilerOracle::should_inline(methodHandle method) { 295 return (check_predicate(InlineCommand, method)); 296} 297 298 299bool CompilerOracle::should_not_inline(methodHandle method) { 300 return (check_predicate(DontInlineCommand, method)); 301} 302 303 304bool CompilerOracle::should_print(methodHandle method) { 305 return (check_predicate(PrintCommand, method)); 306} 307 308 309bool CompilerOracle::should_log(methodHandle method) { 310 if (!LogCompilation) return false; 311 if (lists[LogCommand] == NULL) return true; // by default, log all 312 return (check_predicate(LogCommand, method)); 313} 314 315 316bool CompilerOracle::should_break_at(methodHandle method) { 317 return check_predicate(BreakCommand, method); 318} 319 320 321static OracleCommand parse_command_name(const char * line, int* bytes_read) { 322 assert(ARRAY_SIZE(command_names) == OracleCommandCount, 323 "command_names size mismatch"); 324 325 *bytes_read = 0; 326 char command[32]; 327 int result = sscanf(line, "%32[a-z]%n", command, bytes_read); 328 for (uint i = 0; i < ARRAY_SIZE(command_names); i++) { 329 if (strcmp(command, command_names[i]) == 0) { 330 return (OracleCommand)i; 331 } 332 } 333 return UnknownCommand; 334} 335 336 337static void usage() { 338 tty->print_cr(" CompileCommand and the CompilerOracle allows simple control over"); 339 tty->print_cr(" what's allowed to be compiled. The standard supported directives"); 340 tty->print_cr(" are exclude and compileonly. The exclude directive stops a method"); 341 tty->print_cr(" from being compiled and compileonly excludes all methods except for"); 342 tty->print_cr(" the ones mentioned by compileonly directives. The basic form of"); 343 tty->print_cr(" all commands is a command name followed by the name of the method"); 344 tty->print_cr(" in one of two forms: the standard class file format as in"); 345 tty->print_cr(" class/name.methodName or the PrintCompilation format"); 346 tty->print_cr(" class.name::methodName. The method name can optionally be followed"); 347 tty->print_cr(" by a space then the signature of the method in the class file"); 348 tty->print_cr(" format. Otherwise the directive applies to all methods with the"); 349 tty->print_cr(" same name and class regardless of signature. Leading and trailing"); 350 tty->print_cr(" *'s in the class and/or method name allows a small amount of"); 351 tty->print_cr(" wildcarding. "); 352 tty->cr(); 353 tty->print_cr(" Examples:"); 354 tty->cr(); 355 tty->print_cr(" exclude java/lang/StringBuffer.append"); 356 tty->print_cr(" compileonly java/lang/StringBuffer.toString ()Ljava/lang/String;"); 357 tty->print_cr(" exclude java/lang/String*.*"); 358 tty->print_cr(" exclude *.toString"); 359} 360 361 362// The characters allowed in a class or method name. All characters > 0x7f 363// are allowed in order to handle obfuscated class files (e.g. Volano) 364#define RANGEBASE "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789$_<>" \ 365 "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" \ 366 "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" \ 367 "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf" \ 368 "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" \ 369 "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" \ 370 "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" \ 371 "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" \ 372 "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" 373 374#define RANGE0 "[*" RANGEBASE "]" 375#define RANGEDOT "[*" RANGEBASE ".]" 376#define RANGESLASH "[*" RANGEBASE "/]" 377 378 379// Accept several syntaxes for these patterns 380// original syntax 381// cmd java.lang.String foo 382// PrintCompilation syntax 383// cmd java.lang.String::foo 384// VM syntax 385// cmd java/lang/String[. ]foo 386// 387 388static const char* patterns[] = { 389 "%*[ \t]%255" RANGEDOT " " "%255" RANGE0 "%n", 390 "%*[ \t]%255" RANGEDOT "::" "%255" RANGE0 "%n", 391 "%*[ \t]%255" RANGESLASH "%*[ .]" "%255" RANGE0 "%n", 392}; 393 394static MethodMatcher::Mode check_mode(char name[], const char*& error_msg) { 395 int match = MethodMatcher::Exact; 396 while (name[0] == '*') { 397 match |= MethodMatcher::Suffix; 398 strcpy(name, name + 1); 399 } 400 401 if (strcmp(name, "*") == 0) return MethodMatcher::Any; 402 403 size_t len = strlen(name); 404 while (len > 0 && name[len - 1] == '*') { 405 match |= MethodMatcher::Prefix; 406 name[--len] = '\0'; 407 } 408 409 if (strstr(name, "*") != NULL) { 410 error_msg = " Embedded * not allowed"; 411 return MethodMatcher::Unknown; 412 } 413 return (MethodMatcher::Mode)match; 414} 415 416static bool scan_line(const char * line, 417 char class_name[], MethodMatcher::Mode* c_mode, 418 char method_name[], MethodMatcher::Mode* m_mode, 419 int* bytes_read, const char*& error_msg) { 420 *bytes_read = 0; 421 error_msg = NULL; 422 for (uint i = 0; i < ARRAY_SIZE(patterns); i++) { 423 if (2 == sscanf(line, patterns[i], class_name, method_name, bytes_read)) { 424 *c_mode = check_mode(class_name, error_msg); 425 *m_mode = check_mode(method_name, error_msg); 426 return *c_mode != MethodMatcher::Unknown && *m_mode != MethodMatcher::Unknown; 427 } 428 } 429 return false; 430} 431 432 433 434void CompilerOracle::parse_from_line(char* line) { 435 if (line[0] == '\0') return; 436 if (line[0] == '#') return; 437 438 bool have_colon = (strstr(line, "::") != NULL); 439 for (char* lp = line; *lp != '\0'; lp++) { 440 // Allow '.' to separate the class name from the method name. 441 // This is the preferred spelling of methods: 442 // exclude java/lang/String.indexOf(I)I 443 // Allow ',' for spaces (eases command line quoting). 444 // exclude,java/lang/String.indexOf 445 // For backward compatibility, allow space as separator also. 446 // exclude java/lang/String indexOf 447 // exclude,java/lang/String,indexOf 448 // For easy cut-and-paste of method names, allow VM output format 449 // as produced by methodOopDesc::print_short_name: 450 // exclude java.lang.String::indexOf 451 // For simple implementation convenience here, convert them all to space. 452 if (have_colon) { 453 if (*lp == '.') *lp = '/'; // dots build the package prefix 454 if (*lp == ':') *lp = ' '; 455 } 456 if (*lp == ',' || *lp == '.') *lp = ' '; 457 } 458 459 char* original_line = line; 460 int bytes_read; 461 OracleCommand command = parse_command_name(line, &bytes_read); 462 line += bytes_read; 463 464 if (command == QuietCommand) { 465 _quiet = true; 466 return; 467 } 468 469 if (command == HelpCommand) { 470 usage(); 471 return; 472 } 473 474 MethodMatcher::Mode c_match = MethodMatcher::Exact; 475 MethodMatcher::Mode m_match = MethodMatcher::Exact; 476 char class_name[256]; 477 char method_name[256]; 478 char sig[1024]; 479 char errorbuf[1024]; 480 const char* error_msg = NULL; 481 MethodMatcher* match = NULL; 482 483 if (scan_line(line, class_name, &c_match, method_name, &m_match, &bytes_read, error_msg)) { 484 EXCEPTION_MARK; 485 symbolHandle c_name = oopFactory::new_symbol_handle(class_name, CHECK); 486 symbolHandle m_name = oopFactory::new_symbol_handle(method_name, CHECK); 487 symbolHandle signature; 488 489 line += bytes_read; 490 // there might be a signature following the method. 491 // signatures always begin with ( so match that by hand 492 if (1 == sscanf(line, "%*[ \t](%254[);/" RANGEBASE "]%n", sig + 1, &bytes_read)) { 493 sig[0] = '('; 494 line += bytes_read; 495 signature = oopFactory::new_symbol_handle(sig, CHECK); 496 } 497 498 if (command == OptionCommand) { 499 // Look for trailing options to support 500 // ciMethod::has_option("string") to control features in the 501 // compiler. Multiple options may follow the method name. 502 char option[256]; 503 while (sscanf(line, "%*[ \t]%255[a-zA-Z0-9]%n", option, &bytes_read) == 1) { 504 if (match != NULL && !_quiet) { 505 // Print out the last match added 506 tty->print("CompilerOracle: %s ", command_names[command]); 507 match->print(); 508 } 509 match = add_option_string(c_name, c_match, m_name, m_match, signature, strdup(option)); 510 line += bytes_read; 511 } 512 } else { 513 bytes_read = 0; 514 sscanf(line, "%*[ \t]%n", &bytes_read); 515 if (line[bytes_read] != '\0') { 516 jio_snprintf(errorbuf, sizeof(errorbuf), " Unrecognized text after command: %s", line); 517 error_msg = errorbuf; 518 } else { 519 match = add_predicate(command, c_name, c_match, m_name, m_match, signature); 520 } 521 } 522 } 523 524 if (match != NULL) { 525 if (!_quiet) { 526 tty->print("CompilerOracle: %s ", command_names[command]); 527 match->print(); 528 } 529 } else { 530 tty->print_cr("CompilerOracle: unrecognized line"); 531 tty->print_cr(" \"%s\"", original_line); 532 if (error_msg != NULL) { 533 tty->print_cr(error_msg); 534 } 535 } 536} 537 538static const char* cc_file() { 539 if (CompileCommandFile == NULL) 540 return ".hotspot_compiler"; 541 return CompileCommandFile; 542} 543bool CompilerOracle::_quiet = false; 544 545void CompilerOracle::parse_from_file() { 546 FILE* stream = fopen(cc_file(), "rt"); 547 if (stream == NULL) return; 548 549 char token[1024]; 550 int pos = 0; 551 int c = getc(stream); 552 while(c != EOF) { 553 if (c == '\n') { 554 token[pos++] = '\0'; 555 parse_from_line(token); 556 pos = 0; 557 } else { 558 token[pos++] = c; 559 } 560 c = getc(stream); 561 } 562 token[pos++] = '\0'; 563 parse_from_line(token); 564 565 fclose(stream); 566} 567 568void CompilerOracle::parse_from_string(const char* str, void (*parse_line)(char*)) { 569 char token[1024]; 570 int pos = 0; 571 const char* sp = str; 572 int c = *sp++; 573 while (c != '\0') { 574 if (c == '\n') { 575 token[pos++] = '\0'; 576 parse_line(token); 577 pos = 0; 578 } else { 579 token[pos++] = c; 580 } 581 c = *sp++; 582 } 583 token[pos++] = '\0'; 584 parse_line(token); 585} 586 587void CompilerOracle::append_comment_to_file(const char* message) { 588 fileStream stream(fopen(cc_file(), "at")); 589 stream.print("# "); 590 for (int index = 0; message[index] != '\0'; index++) { 591 stream.put(message[index]); 592 if (message[index] == '\n') stream.print("# "); 593 } 594 stream.cr(); 595} 596 597void CompilerOracle::append_exclude_to_file(methodHandle method) { 598 fileStream stream(fopen(cc_file(), "at")); 599 stream.print("exclude "); 600 Klass::cast(method->method_holder())->name()->print_symbol_on(&stream); 601 stream.print("."); 602 method->name()->print_symbol_on(&stream); 603 method->signature()->print_symbol_on(&stream); 604 stream.cr(); 605 stream.cr(); 606} 607 608 609void compilerOracle_init() { 610 CompilerOracle::parse_from_string(CompileCommand, CompilerOracle::parse_from_line); 611 CompilerOracle::parse_from_string(CompileOnly, CompilerOracle::parse_compile_only); 612 CompilerOracle::parse_from_file(); 613 if (lists[PrintCommand] != NULL) { 614 if (PrintAssembly) { 615 warning("CompileCommand and/or .hotspot_compiler file contains 'print' commands, but PrintAssembly is also enabled"); 616 } else if (FLAG_IS_DEFAULT(DebugNonSafepoints)) { 617 warning("printing of assembly code is enabled; turning on DebugNonSafepoints to gain additional output"); 618 DebugNonSafepoints = true; 619 } 620 } 621} 622 623 624void CompilerOracle::parse_compile_only(char * line) { 625 int i; 626 char name[1024]; 627 const char* className = NULL; 628 const char* methodName = NULL; 629 630 bool have_colon = (strstr(line, "::") != NULL); 631 char method_sep = have_colon ? ':' : '.'; 632 633 if (Verbose) { 634 tty->print_cr(line); 635 } 636 637 ResourceMark rm; 638 while (*line != '\0') { 639 MethodMatcher::Mode c_match = MethodMatcher::Exact; 640 MethodMatcher::Mode m_match = MethodMatcher::Exact; 641 642 for (i = 0; 643 i < 1024 && *line != '\0' && *line != method_sep && *line != ',' && !isspace(*line); 644 line++, i++) { 645 name[i] = *line; 646 if (name[i] == '.') name[i] = '/'; // package prefix uses '/' 647 } 648 649 if (i > 0) { 650 char* newName = NEW_RESOURCE_ARRAY( char, i + 1); 651 if (newName == NULL) 652 return; 653 strncpy(newName, name, i); 654 newName[i] = '\0'; 655 656 if (className == NULL) { 657 className = newName; 658 c_match = MethodMatcher::Prefix; 659 } else { 660 methodName = newName; 661 } 662 } 663 664 if (*line == method_sep) { 665 if (className == NULL) { 666 className = ""; 667 c_match = MethodMatcher::Any; 668 } else { 669 // foo/bar.blah is an exact match on foo/bar, bar.blah is a suffix match on bar 670 if (strchr(className, '/') != NULL) { 671 c_match = MethodMatcher::Exact; 672 } else { 673 c_match = MethodMatcher::Suffix; 674 } 675 } 676 } else { 677 // got foo or foo/bar 678 if (className == NULL) { 679 ShouldNotReachHere(); 680 } else { 681 // got foo or foo/bar 682 if (strchr(className, '/') != NULL) { 683 c_match = MethodMatcher::Prefix; 684 } else if (className[0] == '\0') { 685 c_match = MethodMatcher::Any; 686 } else { 687 c_match = MethodMatcher::Substring; 688 } 689 } 690 } 691 692 // each directive is terminated by , or NUL or . followed by NUL 693 if (*line == ',' || *line == '\0' || (line[0] == '.' && line[1] == '\0')) { 694 if (methodName == NULL) { 695 methodName = ""; 696 if (*line != method_sep) { 697 m_match = MethodMatcher::Any; 698 } 699 } 700 701 EXCEPTION_MARK; 702 symbolHandle c_name = oopFactory::new_symbol_handle(className, CHECK); 703 symbolHandle m_name = oopFactory::new_symbol_handle(methodName, CHECK); 704 symbolHandle signature; 705 706 add_predicate(CompileOnlyCommand, c_name, c_match, m_name, m_match, signature); 707 if (PrintVMOptions) { 708 tty->print("CompileOnly: compileonly "); 709 lists[CompileOnlyCommand]->print(); 710 } 711 712 className = NULL; 713 methodName = NULL; 714 } 715 716 line = *line == '\0' ? line : line + 1; 717 } 718} 719