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