1 /*
2 * Copyright (c) 1998, 2020, 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/globals_extension.hpp"
37 #include "runtime/handles.inline.hpp"
38 #include "runtime/jniHandles.hpp"
39 #include "runtime/os.hpp"
40
41 static const char* optiontype_names[] = {
42 #define enum_of_types(type, name) name,
43 OPTION_TYPES(enum_of_types)
44 #undef enum_of_types
45 };
46
optiontype2name(enum OptionType type)47 const char* optiontype2name(enum OptionType type) {
48 return optiontype_names[static_cast<int>(type)];
49 }
50
51 static enum OptionType option_types[] = {
52 #define enum_of_options(option, name, ctype) OptionType::ctype,
53 COMPILECOMMAND_OPTIONS(enum_of_options)
54 #undef enum_of_options
55 };
56
option2type(enum CompileCommand option)57 enum OptionType option2type(enum CompileCommand option) {
58 return option_types[static_cast<int>(option)];
59 }
60
61 static const char* option_names[] = {
62 #define enum_of_options(option, name, ctype) name,
63 COMPILECOMMAND_OPTIONS(enum_of_options)
64 #undef enum_of_options
65 };
66
option2name(enum CompileCommand option)67 const char* option2name(enum CompileCommand option) {
68 return option_names[static_cast<int>(option)];
69 }
70
71 /* Methods to map real type names to OptionType */
72 template<typename T>
get_type_for()73 static OptionType get_type_for() {
74 return OptionType::Unknown;
75 };
76
get_type_for()77 template<> OptionType get_type_for<intx>() {
78 return OptionType::Intx;
79 }
80
get_type_for()81 template<> OptionType get_type_for<uintx>() {
82 return OptionType::Uintx;
83 }
84
get_type_for()85 template<> OptionType get_type_for<bool>() {
86 return OptionType::Bool;
87 }
88
get_type_for()89 template<> OptionType get_type_for<ccstr>() {
90 return OptionType::Ccstr;
91 }
92
get_type_for()93 template<> OptionType get_type_for<double>() {
94 return OptionType::Double;
95 }
96
97 class MethodMatcher;
98 class TypedMethodOptionMatcher;
99
100 static TypedMethodOptionMatcher* option_list = NULL;
101 static bool any_set = false;
102
103 class TypedMethodOptionMatcher : public MethodMatcher {
104 private:
105 TypedMethodOptionMatcher* _next;
106 enum CompileCommand _option;
107 public:
108
109 union {
110 bool bool_value;
111 intx intx_value;
112 uintx uintx_value;
113 double double_value;
114 ccstr ccstr_value;
115 } _u;
116
TypedMethodOptionMatcher()117 TypedMethodOptionMatcher() : MethodMatcher(),
118 _next(NULL),
119 _option(CompileCommand::Unknown) {
120 memset(&_u, 0, sizeof(_u));
121 }
122
123 ~TypedMethodOptionMatcher();
124 static TypedMethodOptionMatcher* parse_method_pattern(char*& line, char* errorbuf, const int buf_size);
125 TypedMethodOptionMatcher* match(const methodHandle &method, enum CompileCommand option);
126
init(enum CompileCommand option,TypedMethodOptionMatcher * next)127 void init(enum CompileCommand option, TypedMethodOptionMatcher* next) {
128 _next = next;
129 _option = option;
130 }
131
init_matcher(Symbol * class_name,Mode class_mode,Symbol * method_name,Mode method_mode,Symbol * signature)132 void init_matcher(Symbol* class_name, Mode class_mode,
133 Symbol* method_name, Mode method_mode,
134 Symbol* signature) {
135 MethodMatcher::init(class_name, class_mode, method_name, method_mode, signature);
136 }
137
set_next(TypedMethodOptionMatcher * next)138 void set_next(TypedMethodOptionMatcher* next) {_next = next; }
next()139 TypedMethodOptionMatcher* next() { return _next; }
option()140 enum CompileCommand option() { return _option; }
141 template<typename T> T value();
142 template<typename T> void set_value(T value);
143 void print();
144 void print_all();
145 TypedMethodOptionMatcher* clone();
146 };
147
148 // A few templated accessors instead of a full template class.
value()149 template<> intx TypedMethodOptionMatcher::value<intx>() {
150 return _u.intx_value;
151 }
152
value()153 template<> uintx TypedMethodOptionMatcher::value<uintx>() {
154 return _u.uintx_value;
155 }
156
value()157 template<> bool TypedMethodOptionMatcher::value<bool>() {
158 return _u.bool_value;
159 }
160
value()161 template<> double TypedMethodOptionMatcher::value<double>() {
162 return _u.double_value;
163 }
164
value()165 template<> ccstr TypedMethodOptionMatcher::value<ccstr>() {
166 return _u.ccstr_value;
167 }
168
set_value(intx value)169 template<> void TypedMethodOptionMatcher::set_value(intx value) {
170 _u.intx_value = value;
171 }
172
set_value(uintx value)173 template<> void TypedMethodOptionMatcher::set_value(uintx value) {
174 _u.uintx_value = value;
175 }
176
set_value(double value)177 template<> void TypedMethodOptionMatcher::set_value(double value) {
178 _u.double_value = value;
179 }
180
set_value(bool value)181 template<> void TypedMethodOptionMatcher::set_value(bool value) {
182 _u.bool_value = value;
183 }
184
set_value(ccstr value)185 template<> void TypedMethodOptionMatcher::set_value(ccstr value) {
186 _u.ccstr_value = (const ccstr)os::strdup_check_oom(value);
187 }
188
print()189 void TypedMethodOptionMatcher::print() {
190 ttyLocker ttyl;
191 print_base(tty);
192 const char* name = option2name(_option);
193 enum OptionType type = option2type(_option);
194 switch (type) {
195 case OptionType::Intx:
196 tty->print_cr(" intx %s = " INTX_FORMAT, name, value<intx>());
197 break;
198 case OptionType::Uintx:
199 tty->print_cr(" uintx %s = " UINTX_FORMAT, name, value<uintx>());
200 break;
201 case OptionType::Bool:
202 tty->print_cr(" bool %s = %s", name, value<bool>() ? "true" : "false");
203 break;
204 case OptionType::Double:
205 tty->print_cr(" double %s = %f", name, value<double>());
206 break;
207 case OptionType::Ccstr:
208 case OptionType::Ccstrlist:
209 tty->print_cr(" const char* %s = '%s'", name, value<ccstr>());
210 break;
211 default:
212 ShouldNotReachHere();
213 }
214 }
215
print_all()216 void TypedMethodOptionMatcher::print_all() {
217 print();
218 if (_next != NULL) {
219 tty->print(" ");
220 _next->print_all();
221 }
222 }
223
clone()224 TypedMethodOptionMatcher* TypedMethodOptionMatcher::clone() {
225 TypedMethodOptionMatcher* m = new TypedMethodOptionMatcher();
226 m->_class_mode = _class_mode;
227 m->_class_name = _class_name;
228 m->_method_mode = _method_mode;
229 m->_method_name = _method_name;
230 m->_signature = _signature;
231 // Need to ref count the symbols
232 if (_class_name != NULL) {
233 _class_name->increment_refcount();
234 }
235 if (_method_name != NULL) {
236 _method_name->increment_refcount();
237 }
238 if (_signature != NULL) {
239 _signature->increment_refcount();
240 }
241 return m;
242 }
243
~TypedMethodOptionMatcher()244 TypedMethodOptionMatcher::~TypedMethodOptionMatcher() {
245 enum OptionType type = option2type(_option);
246 if (type == OptionType::Ccstr || type == OptionType::Ccstrlist) {
247 ccstr v = value<ccstr>();
248 os::free((void*)v);
249 }
250 }
251
parse_method_pattern(char * & line,char * errorbuf,const int buf_size)252 TypedMethodOptionMatcher* TypedMethodOptionMatcher::parse_method_pattern(char*& line, char* errorbuf, const int buf_size) {
253 assert(*errorbuf == '\0', "Dont call here with error_msg already set");
254 const char* error_msg = NULL;
255 TypedMethodOptionMatcher* tom = new TypedMethodOptionMatcher();
256 MethodMatcher::parse_method_pattern(line, error_msg, tom);
257 if (error_msg != NULL) {
258 jio_snprintf(errorbuf, buf_size, error_msg);
259 delete tom;
260 return NULL;
261 }
262 return tom;
263 }
264
match(const methodHandle & method,enum CompileCommand option)265 TypedMethodOptionMatcher* TypedMethodOptionMatcher::match(const methodHandle& method, enum CompileCommand option) {
266 TypedMethodOptionMatcher* current = this;
267 while (current != NULL) {
268 if (current->_option == option) {
269 if (current->matches(method)) {
270 return current;
271 }
272 }
273 current = current->next();
274 }
275 return NULL;
276 }
277
278 template<typename T>
register_command(TypedMethodOptionMatcher * matcher,enum CompileCommand option,T value)279 static void register_command(TypedMethodOptionMatcher* matcher,
280 enum CompileCommand option,
281 T value) {
282 assert(matcher != option_list, "No circular lists please");
283 if (option == CompileCommand::Log && !LogCompilation) {
284 tty->print_cr("Warning: +LogCompilation must be enabled in order for individual methods to be logged with ");
285 tty->print_cr(" CompileCommand=log,<method pattern>");
286 }
287 assert(CompilerOracle::option_matches_type(option, value), "Value must match option type");
288
289 matcher->init(option, option_list);
290 matcher->set_value<T>(value);
291 option_list = matcher;
292 if ((option != CompileCommand::DontInline) &&
293 (option != CompileCommand::Inline) &&
294 (option != CompileCommand::Log)) {
295 any_set = true;
296 }
297 if (!CompilerOracle::be_quiet()) {
298 // Print out the succesful registration of a comile command
299 ttyLocker ttyl;
300 tty->print("CompileCommand: %s ", option2name(option));
301 matcher->print();
302 }
303 return;
304 }
305
306 template<typename T>
has_option_value(const methodHandle & method,enum CompileCommand option,T & value)307 bool CompilerOracle::has_option_value(const methodHandle& method, enum CompileCommand option, T& value) {
308 assert(option_matches_type(option, value), "Value must match option type");
309 if (option_list != NULL) {
310 TypedMethodOptionMatcher* m = option_list->match(method, option);
311 if (m != NULL) {
312 value = m->value<T>();
313 return true;
314 }
315 }
316 return false;
317 }
318
check_predicate(enum CompileCommand option,const methodHandle & method)319 static bool check_predicate(enum CompileCommand option, const methodHandle& method) {
320 bool value = false;
321 if (CompilerOracle::has_option_value(method, option, value)) {
322 return value;
323 }
324 return false;
325 }
326
has_command(enum CompileCommand option)327 static bool has_command(enum CompileCommand option) {
328 TypedMethodOptionMatcher* m = option_list;
329 while (m != NULL) {
330 if (m->option() == option) {
331 return true;
332 } else {
333 m = m->next();
334 }
335 }
336 return false;
337 }
338
has_any_command_set()339 bool CompilerOracle::has_any_command_set() {
340 return any_set;
341 }
342
343 // Explicit instantiation for all OptionTypes supported.
344 template bool CompilerOracle::has_option_value<intx>(const methodHandle& method, enum CompileCommand option, intx& value);
345 template bool CompilerOracle::has_option_value<uintx>(const methodHandle& method, enum CompileCommand option, uintx& value);
346 template bool CompilerOracle::has_option_value<bool>(const methodHandle& method, enum CompileCommand option, bool& value);
347 template bool CompilerOracle::has_option_value<ccstr>(const methodHandle& method, enum CompileCommand option, ccstr& value);
348 template bool CompilerOracle::has_option_value<double>(const methodHandle& method, enum CompileCommand option, double& value);
349
350 template<typename T>
option_matches_type(enum CompileCommand option,T & value)351 bool CompilerOracle::option_matches_type(enum CompileCommand option, T& value) {
352 enum OptionType option_type = option2type(option);
353 if (option_type == OptionType::Unknown) {
354 return false; // Can't query options with type Unknown.
355 }
356 if (option_type == OptionType::Ccstrlist) {
357 option_type = OptionType::Ccstr; // CCstrList type options are stored as Ccstr
358 }
359 return (get_type_for<T>() == option_type);
360 }
361
362 template bool CompilerOracle::option_matches_type<intx>(enum CompileCommand option, intx& value);
363 template bool CompilerOracle::option_matches_type<uintx>(enum CompileCommand option, uintx& value);
364 template bool CompilerOracle::option_matches_type<bool>(enum CompileCommand option, bool& value);
365 template bool CompilerOracle::option_matches_type<ccstr>(enum CompileCommand option, ccstr& value);
366 template bool CompilerOracle::option_matches_type<double>(enum CompileCommand option, double& value);
367
has_option(const methodHandle & method,enum CompileCommand option)368 bool CompilerOracle::has_option(const methodHandle& method, enum CompileCommand option) {
369 bool value = false;
370 has_option_value(method, option, value);
371 return value;
372 }
373
should_exclude(const methodHandle & method)374 bool CompilerOracle::should_exclude(const methodHandle& method) {
375 if (check_predicate(CompileCommand::Exclude, method)) {
376 return true;
377 }
378 if (has_command(CompileCommand::CompileOnly)) {
379 return !check_predicate(CompileCommand::CompileOnly, method);
380 }
381 return false;
382 }
383
should_inline(const methodHandle & method)384 bool CompilerOracle::should_inline(const methodHandle& method) {
385 return (check_predicate(CompileCommand::Inline, method));
386 }
387
should_not_inline(const methodHandle & method)388 bool CompilerOracle::should_not_inline(const methodHandle& method) {
389 return check_predicate(CompileCommand::DontInline, method) || check_predicate(CompileCommand::Exclude, method);
390 }
391
should_print(const methodHandle & method)392 bool CompilerOracle::should_print(const methodHandle& method) {
393 return check_predicate(CompileCommand::Print, method);
394 }
395
should_print_methods()396 bool CompilerOracle::should_print_methods() {
397 return has_command(CompileCommand::Print);
398 }
399
should_log(const methodHandle & method)400 bool CompilerOracle::should_log(const methodHandle& method) {
401 if (!LogCompilation) return false;
402 if (!has_command(CompileCommand::Log)) {
403 return true; // by default, log all
404 }
405 return (check_predicate(CompileCommand::Log, method));
406 }
407
should_break_at(const methodHandle & method)408 bool CompilerOracle::should_break_at(const methodHandle& method) {
409 return check_predicate(CompileCommand::Break, method);
410 }
411
parse_option_name(const char * line,int * bytes_read,char * errorbuf,int bufsize)412 static enum CompileCommand parse_option_name(const char* line, int* bytes_read, char* errorbuf, int bufsize) {
413 assert(ARRAY_SIZE(option_names) == static_cast<int>(CompileCommand::Count), "option_names size mismatch");
414
415 *bytes_read = 0;
416 char option_buf[256];
417 int matches = sscanf(line, "%255[a-zA-Z0-9]%n", option_buf, bytes_read);
418 if (matches > 0) {
419 for (uint i = 0; i < ARRAY_SIZE(option_names); i++) {
420 if (strcasecmp(option_buf, option_names[i]) == 0) {
421 return static_cast<enum CompileCommand>(i);
422 }
423 }
424 }
425 jio_snprintf(errorbuf, bufsize, "Unrecognized option '%s'", option_buf);
426 return CompileCommand::Unknown;
427 }
428
print_tip()429 void print_tip() { // CMH Update info
430 tty->cr();
431 tty->print_cr("Usage: '-XX:CompileCommand=<option>,<method pattern>' - to set boolean option to true");
432 tty->print_cr("Usage: '-XX:CompileCommand=<option>,<method pattern>,<value>'");
433 tty->print_cr("Use: '-XX:CompileCommand=help' for more information and to list all option.");
434 tty->cr();
435 }
436
print_option(enum CompileCommand option,const char * name,enum OptionType type)437 void print_option(enum CompileCommand option, const char* name, enum OptionType type) {
438 if (type != OptionType::Unknown) {
439 tty->print_cr(" %s (%s)", name, optiontype2name(type));
440 }
441 }
442
print_commands()443 void print_commands() {
444 tty->cr();
445 tty->print_cr("All available options:");
446 #define enum_of_options(option, name, ctype) print_option(CompileCommand::option, name, OptionType::ctype);
447 COMPILECOMMAND_OPTIONS(enum_of_options)
448 #undef enum_of_options
449 tty->cr();
450 }
451
usage()452 static void usage() {
453 tty->cr();
454 tty->print_cr("The CompileCommand option enables the user of the JVM to control specific");
455 tty->print_cr("behavior of the dynamic compilers.");
456 tty->cr();
457 tty->print_cr("Compile commands has this general form:");
458 tty->print_cr("-XX:CompileCommand=<option><method pattern><value>");
459 tty->print_cr(" Sets <option> to the specified value for methods matching <method pattern>");
460 tty->print_cr(" All options are typed");
461 tty->cr();
462 tty->print_cr("-XX:CompileCommand=<option><method pattern>");
463 tty->print_cr(" Sets <option> to true for methods matching <method pattern>");
464 tty->print_cr(" Only applies to boolean options.");
465 tty->cr();
466 tty->print_cr("-XX:CompileCommand=quiet");
467 tty->print_cr(" Silence the compile command output");
468 tty->cr();
469 tty->print_cr("-XX:CompileCommand=help");
470 tty->print_cr(" Prints this help text");
471 tty->cr();
472 print_commands();
473 tty->cr();
474 tty->print_cr("Method patterns has the format:");
475 tty->print_cr(" package/Class.method()");
476 tty->cr();
477 tty->print_cr("For backward compatibility this form is also allowed:");
478 tty->print_cr(" package.Class::method()");
479 tty->cr();
480 tty->print_cr("The signature can be separated by an optional whitespace or comma:");
481 tty->print_cr(" package/Class.method ()");
482 tty->cr();
483 tty->print_cr("The class and method identifier can be used together with leading or");
484 tty->print_cr("trailing *'s for wildcard matching:");
485 tty->print_cr(" *ackage/Clas*.*etho*()");
486 tty->cr();
487 tty->print_cr("It is possible to use more than one CompileCommand on the command line:");
488 tty->print_cr(" -XX:CompileCommand=exclude,java/*.* -XX:CompileCommand=log,java*.*");
489 tty->cr();
490 tty->print_cr("The CompileCommands can be loaded from a file with the flag");
491 tty->print_cr("-XX:CompileCommandFile=<file> or be added to the file '.hotspot_compiler'");
492 tty->print_cr("Use the same format in the file as the argument to the CompileCommand flag.");
493 tty->print_cr("Add one command on each line.");
494 tty->print_cr(" exclude java/*.*");
495 tty->print_cr(" option java/*.* ReplayInline");
496 tty->cr();
497 tty->print_cr("The following commands have conflicting behavior: 'exclude', 'inline', 'dontinline',");
498 tty->print_cr("and 'compileonly'. There is no priority of commands. Applying (a subset of) these");
499 tty->print_cr("commands to the same method results in undefined behavior.");
500 tty->cr();
501 };
502
skip_whitespace(char * & line)503 int skip_whitespace(char* &line) {
504 // Skip any leading spaces
505 int whitespace_read = 0;
506 sscanf(line, "%*[ \t]%n", &whitespace_read);
507 line += whitespace_read;
508 return whitespace_read;
509 }
510
skip_comma(char * & line)511 void skip_comma(char* &line) {
512 // Skip any leading spaces
513 if (*line == ',') {
514 line++;
515 }
516 }
517
scan_value(enum OptionType type,char * line,int & total_bytes_read,TypedMethodOptionMatcher * matcher,enum CompileCommand option,char * errorbuf,const int buf_size)518 static void scan_value(enum OptionType type, char* line, int& total_bytes_read,
519 TypedMethodOptionMatcher* matcher, enum CompileCommand option, char* errorbuf, const int buf_size) {
520 int bytes_read = 0;
521 const char* ccname = option2name(option);
522 const char* type_str = optiontype2name(type);
523 int skipped = skip_whitespace(line);
524 total_bytes_read += skipped;
525 if (type == OptionType::Intx) {
526 intx value;
527 if (sscanf(line, "" INTX_FORMAT "%n", &value, &bytes_read) == 1) {
528 total_bytes_read += bytes_read;
529 line += bytes_read;
530 register_command(matcher, option, value);
531 return;
532 } else {
533 jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
534 }
535 } else if (type == OptionType::Uintx) {
536 uintx value;
537 if (sscanf(line, "" UINTX_FORMAT "%n", &value, &bytes_read) == 1) {
538 total_bytes_read += bytes_read;
539 line += bytes_read;
540 register_command(matcher, option, value);
541 return;
542 } else {
543 jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
544 }
545 } else if (type == OptionType::Ccstr) {
546 ResourceMark rm;
547 char* value = NEW_RESOURCE_ARRAY(char, strlen(line) + 1);
548 if (sscanf(line, "%255[_a-zA-Z0-9]%n", value, &bytes_read) == 1) {
549 total_bytes_read += bytes_read;
550 line += bytes_read;
551 register_command(matcher, option, (ccstr) value);
552 return;
553 } else {
554 jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
555 }
556 } else if (type == OptionType::Ccstrlist) {
557 // Accumulates several strings into one. The internal type is ccstr.
558 ResourceMark rm;
559 char* value = NEW_RESOURCE_ARRAY(char, strlen(line) + 1);
560 char* next_value = value;
561 if (sscanf(line, "%255[_a-zA-Z0-9+\\-]%n", next_value, &bytes_read) == 1) {
562 total_bytes_read += bytes_read;
563 line += bytes_read;
564 next_value += bytes_read + 1;
565 char* end_value = next_value - 1;
566 while (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9+\\-]%n", next_value, &bytes_read) == 1) {
567 total_bytes_read += bytes_read;
568 line += bytes_read;
569 *end_value = ' '; // override '\0'
570 next_value += bytes_read;
571 end_value = next_value-1;
572 }
573 register_command(matcher, option, (ccstr) value);
574 return;
575 } else {
576 jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
577 }
578 } else if (type == OptionType::Bool) {
579 char value[256];
580 if (*line == '\0') {
581 // Short version of a CompileCommand sets a boolean Option to true
582 // -XXCompileCommand=<Option>,<method pattern>
583 register_command(matcher, option, true);
584 return;
585 }
586 if (sscanf(line, "%255[a-zA-Z]%n", value, &bytes_read) == 1) {
587 if (strcasecmp(value, "true") == 0) {
588 total_bytes_read += bytes_read;
589 line += bytes_read;
590 register_command(matcher, option, true);
591 return;
592 } else if (strcasecmp(value, "false") == 0) {
593 total_bytes_read += bytes_read;
594 line += bytes_read;
595 register_command(matcher, option, false);
596 return;
597 } else {
598 jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
599 }
600 } else {
601 jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
602 }
603 } else if (type == OptionType::Double) {
604 char buffer[2][256];
605 // Decimal separator '.' has been replaced with ' ' or '/' earlier,
606 // so read integer and fraction part of double value separately.
607 if (sscanf(line, "%255[0-9]%*[ /\t]%255[0-9]%n", buffer[0], buffer[1], &bytes_read) == 2) {
608 char value[512] = "";
609 jio_snprintf(value, sizeof(value), "%s.%s", buffer[0], buffer[1]);
610 total_bytes_read += bytes_read;
611 line += bytes_read;
612 register_command(matcher, option, atof(value));
613 return;
614 } else {
615 jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
616 }
617 } else {
618 jio_snprintf(errorbuf, buf_size, "Type '%s' not supported ", type_str);
619 }
620 }
621
622 // Scan next option and value in line, return MethodMatcher object on success, NULL on failure.
623 // On failure, error_msg contains description for the first error.
624 // For future extensions: set error_msg on first error.
scan_option_and_value(enum OptionType type,char * line,int & total_bytes_read,TypedMethodOptionMatcher * matcher,char * errorbuf,const int buf_size)625 static void scan_option_and_value(enum OptionType type, char* line, int& total_bytes_read,
626 TypedMethodOptionMatcher* matcher,
627 char* errorbuf, const int buf_size) {
628 total_bytes_read = 0;
629 int bytes_read = 0;
630 char option_buf[256];
631
632 // Read option name.
633 if (sscanf(line, "%*[ \t]%255[a-zA-Z0-9]%n", option_buf, &bytes_read) == 1) {
634 line += bytes_read;
635 total_bytes_read += bytes_read;
636 int bytes_read2 = 0;
637 total_bytes_read += skip_whitespace(line);
638 enum CompileCommand option = parse_option_name(option_buf, &bytes_read2, errorbuf, buf_size);
639 if (option == CompileCommand::Unknown) {
640 assert(*errorbuf != '\0', "error must have been set");
641 return;
642 }
643 enum OptionType optiontype = option2type(option);
644 if (option2type(option) != type) {
645 const char* optiontype_name = optiontype2name(optiontype);
646 const char* type_name = optiontype2name(type);
647 jio_snprintf(errorbuf, buf_size, "Option '%s' with type '%s' doesn't match supplied type '%s'", option_buf, optiontype_name, type_name);
648 return;
649 }
650 scan_value(type, line, total_bytes_read, matcher, option, errorbuf, buf_size);
651 } else {
652 const char* type_str = optiontype2name(type);
653 jio_snprintf(errorbuf, buf_size, "Option name for type '%s' should be alphanumeric ", type_str);
654 }
655 return;
656 }
657
print_parse_error(char * error_msg,char * original_line)658 void CompilerOracle::print_parse_error(char* error_msg, char* original_line) {
659 assert(*error_msg != '\0', "Must have error_message");
660 ttyLocker ttyl;
661 tty->print_cr("CompileCommand: An error occurred during parsing");
662 tty->print_cr("Error: %s", error_msg);
663 tty->print_cr("Line: '%s'", original_line);
664 print_tip();
665 }
666
parse_option_type(const char * type_str)667 enum OptionType parse_option_type(const char* type_str) {
668 for (uint i = 0; i < ARRAY_SIZE(optiontype_names); i++) {
669 if (strcasecmp(type_str, optiontype_names[i]) == 0) {
670 return static_cast<enum OptionType>(i);
671 }
672 }
673 return OptionType::Unknown;
674 }
675
676 class LineCopy : StackObj {
677 const char* _copy;
678 public:
LineCopy(char * line)679 LineCopy(char* line) {
680 _copy = os::strdup(line, mtInternal);
681 }
~LineCopy()682 ~LineCopy() {
683 os::free((void*)_copy);
684 }
get()685 char* get() {
686 return (char*)_copy;
687 }
688 };
689
parse_from_line(char * line)690 void CompilerOracle::parse_from_line(char* line) {
691 if (line[0] == '\0') return;
692 if (line[0] == '#') return;
693
694 LineCopy original(line);
695 int bytes_read;
696 char error_buf[1024] = {0};
697
698 enum CompileCommand option = parse_option_name(line, &bytes_read, error_buf, sizeof(error_buf));
699 line += bytes_read;
700 ResourceMark rm;
701
702 if (option == CompileCommand::Unknown) {
703 print_parse_error(error_buf, original.get());
704 return;
705 }
706
707 if (option == CompileCommand::Quiet) {
708 _quiet = true;
709 return;
710 }
711
712 if (option == CompileCommand::Help) {
713 usage();
714 return;
715 }
716
717 if (option == CompileCommand::Option) {
718 // Look for trailing options.
719 //
720 // Two types of trailing options are
721 // supported:
722 //
723 // (1) CompileCommand=option,Klass::method,option
724 // (2) CompileCommand=option,Klass::method,type,option,value
725 //
726 // Type (1) is used to enable a boolean option for a method.
727 //
728 // Type (2) is used to support options with a value. Values can have the
729 // the following types: intx, uintx, bool, ccstr, ccstrlist, and double.
730
731 char option_type[256]; // stores option for Type (1) and type of Type (2)
732 skip_comma(line);
733 TypedMethodOptionMatcher* archetype = TypedMethodOptionMatcher::parse_method_pattern(line, error_buf, sizeof(error_buf));
734 if (archetype == NULL) {
735 print_parse_error(error_buf, original.get());
736 return;
737 }
738
739 skip_whitespace(line);
740
741 // This is unnecessarily complex. Should retire multi-option lines and skip while loop
742 while (sscanf(line, "%255[a-zA-Z0-9]%n", option_type, &bytes_read) == 1) {
743 line += bytes_read;
744
745 // typed_matcher is used as a blueprint for each option, deleted at the end
746 TypedMethodOptionMatcher* typed_matcher = archetype->clone();
747 enum OptionType type = parse_option_type(option_type);
748 if (type != OptionType::Unknown) {
749 // Type (2) option: parse option name and value.
750 scan_option_and_value(type, line, bytes_read, typed_matcher, error_buf, sizeof(error_buf));
751 if (*error_buf != '\0') {
752 print_parse_error(error_buf, original.get());
753 return;
754 }
755 line += bytes_read;
756 } else {
757 // Type (1) option - option_type contains the option name -> bool value = true is implied
758 int bytes_read;
759 enum CompileCommand option = parse_option_name(option_type, &bytes_read, error_buf, sizeof(error_buf));
760 if (option == CompileCommand::Unknown) {
761 print_parse_error(error_buf, original.get());
762 return;
763 }
764 register_command(typed_matcher, option, true);
765 }
766 assert(typed_matcher != NULL, "sanity");
767 assert(*error_buf == '\0', "No error here");
768 skip_whitespace(line);
769 } // while(
770 delete archetype;
771 } else { // not an OptionCommand
772 // Command has the following form:
773 // CompileCommand=<option>,<method pattern><value>
774 // CompileCommand=<option>,<method pattern> (implies option is bool and value is true)
775 assert(*error_buf == '\0', "Don't call here with error_buf already set");
776 enum OptionType type = option2type(option);
777 int bytes_read = 0;
778 skip_comma(line);
779 TypedMethodOptionMatcher* matcher = TypedMethodOptionMatcher::parse_method_pattern(line, error_buf, sizeof(error_buf));
780 if (matcher == NULL) {
781 print_parse_error(error_buf, original.get());
782 return;
783 }
784 skip_whitespace(line);
785 if (*line == '\0') {
786 // if this is a bool option this implies true
787 if (option2type(option) == OptionType::Bool) {
788 register_command(matcher, option, true);
789 return;
790 } else {
791 jio_snprintf(error_buf, sizeof(error_buf), " Option '%s' is not followed by a value", option2name(option));
792 print_parse_error(error_buf, original.get());
793 return;
794 }
795 }
796 scan_value(type, line, bytes_read, matcher, option, error_buf, sizeof(error_buf));
797 if (*error_buf != '\0') {
798 print_parse_error(error_buf, original.get());
799 return;
800 }
801 assert(matcher != NULL, "consistency");
802 }
803 }
804
805 static const char* default_cc_file = ".hotspot_compiler";
806
cc_file()807 static const char* cc_file() {
808 #ifdef ASSERT
809 if (CompileCommandFile == NULL)
810 return default_cc_file;
811 #endif
812 return CompileCommandFile;
813 }
814
has_command_file()815 bool CompilerOracle::has_command_file() {
816 return cc_file() != NULL;
817 }
818
819 bool CompilerOracle::_quiet = false;
820
parse_from_file()821 void CompilerOracle::parse_from_file() {
822 assert(has_command_file(), "command file must be specified");
823 FILE* stream = fopen(cc_file(), "rt");
824 if (stream == NULL) return;
825
826 char token[1024];
827 int pos = 0;
828 int c = getc(stream);
829 while(c != EOF && pos < (int)(sizeof(token)-1)) {
830 if (c == '\n') {
831 token[pos++] = '\0';
832 parse_from_line(token);
833 pos = 0;
834 } else {
835 token[pos++] = c;
836 }
837 c = getc(stream);
838 }
839 token[pos++] = '\0';
840 parse_from_line(token);
841
842 fclose(stream);
843 }
844
parse_from_string(const char * str,void (* parse_line)(char *))845 void CompilerOracle::parse_from_string(const char* str, void (*parse_line)(char*)) {
846 char token[1024];
847 int pos = 0;
848 const char* sp = str;
849 int c = *sp++;
850 while (c != '\0' && pos < (int)(sizeof(token)-1)) {
851 if (c == '\n') {
852 token[pos++] = '\0';
853 parse_line(token);
854 pos = 0;
855 } else {
856 token[pos++] = c;
857 }
858 c = *sp++;
859 }
860 token[pos++] = '\0';
861 parse_line(token);
862 }
863
compilerOracle_init()864 void compilerOracle_init() {
865 CompilerOracle::parse_from_string(CompileCommand, CompilerOracle::parse_from_line);
866 CompilerOracle::parse_from_string(CompileOnly, CompilerOracle::parse_compile_only);
867 if (CompilerOracle::has_command_file()) {
868 CompilerOracle::parse_from_file();
869 } else {
870 struct stat buf;
871 if (os::stat(default_cc_file, &buf) == 0) {
872 warning("%s file is present but has been ignored. "
873 "Run with -XX:CompileCommandFile=%s to load the file.",
874 default_cc_file, default_cc_file);
875 }
876 }
877 if (has_command(CompileCommand::Print)) {
878 if (PrintAssembly) {
879 warning("CompileCommand and/or %s file contains 'print' commands, but PrintAssembly is also enabled", default_cc_file);
880 } else if (FLAG_IS_DEFAULT(DebugNonSafepoints)) {
881 warning("printing of assembly code is enabled; turning on DebugNonSafepoints to gain additional output");
882 DebugNonSafepoints = true;
883 }
884 }
885 }
886
parse_compile_only(char * line)887 void CompilerOracle::parse_compile_only(char* line) {
888 int i;
889 char name[1024];
890 const char* className = NULL;
891 const char* methodName = NULL;
892
893 bool have_colon = (strstr(line, "::") != NULL);
894 char method_sep = have_colon ? ':' : '.';
895
896 if (Verbose) {
897 tty->print_cr("%s", line);
898 }
899
900 ResourceMark rm;
901 while (*line != '\0') {
902 MethodMatcher::Mode c_match = MethodMatcher::Exact;
903 MethodMatcher::Mode m_match = MethodMatcher::Exact;
904
905 for (i = 0;
906 i < 1024 && *line != '\0' && *line != method_sep && *line != ',' && !isspace(*line);
907 line++, i++) {
908 name[i] = *line;
909 if (name[i] == '.') name[i] = '/'; // package prefix uses '/'
910 }
911
912 if (i > 0) {
913 char* newName = NEW_RESOURCE_ARRAY( char, i + 1);
914 if (newName == NULL)
915 return;
916 strncpy(newName, name, i);
917 newName[i] = '\0';
918
919 if (className == NULL) {
920 className = newName;
921 } else {
922 methodName = newName;
923 }
924 }
925
926 if (*line == method_sep) {
927 if (className == NULL) {
928 className = "";
929 c_match = MethodMatcher::Any;
930 }
931 } else {
932 // got foo or foo/bar
933 if (className == NULL) {
934 ShouldNotReachHere();
935 } else {
936 // missing class name handled as "Any" class match
937 if (className[0] == '\0') {
938 c_match = MethodMatcher::Any;
939 }
940 }
941 }
942
943 // each directive is terminated by , or NUL or . followed by NUL
944 if (*line == ',' || *line == '\0' || (line[0] == '.' && line[1] == '\0')) {
945 if (methodName == NULL) {
946 methodName = "";
947 if (*line != method_sep) {
948 m_match = MethodMatcher::Any;
949 }
950 }
951
952 EXCEPTION_MARK;
953 Symbol* c_name = SymbolTable::new_symbol(className);
954 Symbol* m_name = SymbolTable::new_symbol(methodName);
955 Symbol* signature = NULL;
956
957 TypedMethodOptionMatcher* tom = new TypedMethodOptionMatcher();
958 tom->init_matcher(c_name, c_match, m_name, m_match, signature);
959 register_command(tom, CompileCommand::CompileOnly, true);
960 if (PrintVMOptions) {
961 tty->print("CompileOnly: compileonly ");
962 tom->print();
963 }
964
965 className = NULL;
966 methodName = NULL;
967 }
968
969 line = *line == '\0' ? line : line + 1;
970 }
971 }
972
string_to_option(const char * name)973 enum CompileCommand CompilerOracle::string_to_option(const char* name) {
974 int bytes_read = 0;
975 char errorbuf[1024] = {0};
976 return parse_option_name(name, &bytes_read, errorbuf, sizeof(errorbuf));
977 }
978