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