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