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 "ci/ciMethod.hpp"
27 #include "ci/ciUtilities.inline.hpp"
28 #include "compiler/abstractCompiler.hpp"
29 #include "compiler/compilerDirectives.hpp"
30 #include "compiler/compilerOracle.hpp"
31 #include "memory/allocation.inline.hpp"
32 #include "memory/resourceArea.hpp"
33 
CompilerDirectives()34 CompilerDirectives::CompilerDirectives() :_match(NULL), _next(NULL), _ref_count(0) {
35   _c1_store = new DirectiveSet(this);
36   _c1_store->init_disableintrinsic();
37   _c2_store = new DirectiveSet(this);
38   _c2_store->init_disableintrinsic();
39 };
40 
~CompilerDirectives()41 CompilerDirectives::~CompilerDirectives() {
42   if (_c1_store != NULL) {
43     delete _c1_store;
44   }
45   if (_c2_store != NULL) {
46     delete _c2_store;
47   }
48 
49   // remove all linked method matchers
50   BasicMatcher* tmp = _match;
51   while (tmp != NULL) {
52     BasicMatcher* next = tmp->next();
53     delete tmp;
54     tmp = next;
55   }
56 }
57 
print(outputStream * st)58 void CompilerDirectives::print(outputStream* st) {
59   assert(DirectivesStack_lock->owned_by_self(), "");
60   if (_match != NULL) {
61     st->cr();
62     st->print("Directive:");
63     if (is_default_directive()) {
64       st->print_cr(" (default)");
65     } else {
66       st->cr();
67     }
68     st->print(" matching: ");
69     _match->print(st);
70     BasicMatcher* tmp = _match->next();
71     while (tmp != NULL) {
72       st->print(", ");
73       tmp->print(st);
74       tmp = tmp->next();
75     }
76     st->cr();
77   } else {
78     assert(0, "There should always be a match");
79   }
80 
81   if (_c1_store != NULL) {
82     st->print_cr(" c1 directives:");
83     _c1_store->print(st);
84   }
85   if (_c2_store != NULL) {
86     st->cr();
87     st->print_cr(" c2 directives:");
88     _c2_store->print(st);
89   }
90   //---
91 }
92 
finalize(outputStream * st)93 void CompilerDirectives::finalize(outputStream* st) {
94   if (_c1_store != NULL) {
95     _c1_store->finalize(st);
96   }
97   if (_c2_store != NULL) {
98     _c2_store->finalize(st);
99   }
100 }
101 
finalize(outputStream * st)102 void DirectiveSet::finalize(outputStream* st) {
103   // Check LogOption and warn
104   if (LogOption && !LogCompilation) {
105     st->print_cr("Warning:  +LogCompilation must be set to enable compilation logging from directives");
106   }
107 
108   // if any flag has been modified - set directive as enabled
109   // unless it already has been explicitly set.
110   if (!_modified[EnableIndex]) {
111     if (_inlinematchers != NULL) {
112       EnableOption = true;
113       return;
114     }
115     int i;
116     for (i = 0; i < number_of_flags; i++) {
117       if (_modified[i]) {
118         EnableOption = true;
119         return;
120       }
121     }
122   }
123 }
124 
next()125 CompilerDirectives* CompilerDirectives::next() {
126   return _next;
127 }
128 
match(const methodHandle & method)129 bool CompilerDirectives::match(const methodHandle& method) {
130   if (is_default_directive()) {
131     return true;
132   }
133   if (method == NULL) {
134     return false;
135   }
136   if (_match->match(method)) {
137     return true;
138   }
139   return false;
140 }
141 
add_match(char * str,const char * & error_msg)142 bool CompilerDirectives::add_match(char* str, const char*& error_msg) {
143   BasicMatcher* bm = BasicMatcher::parse_method_pattern(str, error_msg);
144   if (bm == NULL) {
145     assert(error_msg != NULL, "Must have error message");
146     return false;
147   } else {
148     bm->set_next(_match);
149     _match = bm;
150     return true;
151   }
152 }
153 
inc_refcount()154 void CompilerDirectives::inc_refcount() {
155   assert(DirectivesStack_lock->owned_by_self(), "");
156   _ref_count++;
157 }
158 
dec_refcount()159 void CompilerDirectives::dec_refcount() {
160   assert(DirectivesStack_lock->owned_by_self(), "");
161   _ref_count--;
162 }
163 
refcount()164 int CompilerDirectives::refcount() {
165   assert(DirectivesStack_lock->owned_by_self(), "");
166   return _ref_count;
167 }
168 
get_for(AbstractCompiler * comp)169 DirectiveSet* CompilerDirectives::get_for(AbstractCompiler *comp) {
170   assert(DirectivesStack_lock->owned_by_self(), "");
171   if (comp == NULL) { // Xint
172     return _c1_store;
173   } else  if (comp->is_c2()) {
174     return _c2_store;
175   } else {
176     // use c1_store as default
177     assert(comp->is_c1() || comp->is_jvmci(), "");
178     return _c1_store;
179   }
180 }
181 
182 // In the list of disabled intrinsics, the ID of the disabled intrinsics can separated:
183 // - by ',' (if -XX:DisableIntrinsic is used once when invoking the VM) or
184 // - by '\n' (if -XX:DisableIntrinsic is used multiple times when invoking the VM) or
185 // - by ' ' (if DisableIntrinsic is used on a per-method level, e.g., with CompileCommand).
186 //
187 // To simplify the processing of the list, the canonicalize_disableintrinsic() method
188 // returns a new copy of the list in which '\n' and ' ' is replaced with ','.
canonicalize_disableintrinsic(ccstrlist option_value)189 ccstrlist DirectiveSet::canonicalize_disableintrinsic(ccstrlist option_value) {
190   char* canonicalized_list = NEW_C_HEAP_ARRAY(char, strlen(option_value) + 1, mtCompiler);
191   int i = 0;
192   char current;
193   while ((current = option_value[i]) != '\0') {
194     if (current == '\n' || current == ' ') {
195       canonicalized_list[i] = ',';
196     } else {
197       canonicalized_list[i] = current;
198     }
199     i++;
200   }
201   canonicalized_list[i] = '\0';
202   return canonicalized_list;
203 }
204 
init_disableintrinsic()205 void DirectiveSet::init_disableintrinsic() {
206   // Canonicalize DisableIntrinsic to contain only ',' as a separator.
207   this->DisableIntrinsicOption = canonicalize_disableintrinsic(DisableIntrinsic);
208 }
209 
DirectiveSet(CompilerDirectives * d)210 DirectiveSet::DirectiveSet(CompilerDirectives* d) :_inlinematchers(NULL), _directive(d) {
211 #define init_defaults_definition(name, type, dvalue, compiler) this->name##Option = dvalue;
212   compilerdirectives_common_flags(init_defaults_definition)
213   compilerdirectives_c2_flags(init_defaults_definition)
214   compilerdirectives_c1_flags(init_defaults_definition)
215   memset(_modified, 0, sizeof(_modified));
216 }
217 
~DirectiveSet()218 DirectiveSet::~DirectiveSet() {
219   // remove all linked methodmatchers
220   InlineMatcher* tmp = _inlinematchers;
221   while (tmp != NULL) {
222     InlineMatcher* next = tmp->next();
223     delete tmp;
224     tmp = next;
225   }
226 
227   // When constructed, DirectiveSet canonicalizes the DisableIntrinsic flag
228   // into a new string. Therefore, that string is deallocated when
229   // the DirectiveSet is destroyed.
230   assert(this->DisableIntrinsicOption != NULL, "");
231   FREE_C_HEAP_ARRAY(char, (void *)this->DisableIntrinsicOption);
232 }
233 
234 // Backward compatibility for CompileCommands
235 // Breaks the abstraction and causes lots of extra complexity
236 // - if some option is changed we need to copy directiveset since it no longer can be shared
237 // - Need to free copy after use
238 // - Requires a modified bit so we don't overwrite options that is set by directives
239 
compilecommand_compatibility_init(const methodHandle & method)240 DirectiveSet* DirectiveSet::compilecommand_compatibility_init(const methodHandle& method) {
241   // Early bail out - checking all options is expensive - we rely on them not being used
242   // Only set a flag if it has not been modified and value changes.
243   // Only copy set if a flag needs to be set
244   if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::has_any_option()) {
245     DirectiveSet* set = DirectiveSet::clone(this);
246 
247     bool changed = false; // Track if we actually change anything
248 
249     // All CompileCommands are not equal so this gets a bit verbose
250     // When CompileCommands have been refactored less clutter will remain.
251     if (CompilerOracle::should_break_at(method)) {
252       if (!_modified[BreakAtCompileIndex]) {
253         set->BreakAtCompileOption = true;
254         changed = true;
255       }
256       if (!_modified[BreakAtExecuteIndex]) {
257         set->BreakAtExecuteOption = true;
258         changed = true;
259       }
260     }
261     if (!_modified[LogIndex]) {
262       bool log = CompilerOracle::should_log(method);
263       if (log != set->LogOption) {
264         set->LogOption = log;
265         changed = true;
266       }
267     }
268 
269     if (CompilerOracle::should_print(method)) {
270       if (!_modified[PrintAssemblyIndex]) {
271         set->PrintAssemblyOption = true;
272         changed = true;
273       }
274     }
275     // Exclude as in should not compile == Enabled
276     if (CompilerOracle::should_exclude(method)) {
277       if (!_modified[ExcludeIndex]) {
278         set->ExcludeOption = true;
279         changed = true;
280       }
281     }
282 
283     // Read old value of DisableIntrinsicOption, in case we need to free it
284     // and overwrite it with a new value.
285     ccstrlist old_disable_intrinsic_value = set->DisableIntrinsicOption;
286 
287     // inline and dontinline (including exclude) are implemented in the directiveset accessors
288 #define init_default_cc(name, type, dvalue, cc_flag) { type v; if (!_modified[name##Index] && CompilerOracle::has_option_value(method, #cc_flag, v) && v != this->name##Option) { set->name##Option = v; changed = true;} }
289     compilerdirectives_common_flags(init_default_cc)
290     compilerdirectives_c2_flags(init_default_cc)
291     compilerdirectives_c1_flags(init_default_cc)
292 
293     // Canonicalize DisableIntrinsic to contain only ',' as a separator.
294     ccstrlist option_value;
295     if (!_modified[DisableIntrinsicIndex] &&
296         CompilerOracle::has_option_value(method, "DisableIntrinsic", option_value)) {
297       set->DisableIntrinsicOption = canonicalize_disableintrinsic(option_value);
298       assert(old_disable_intrinsic_value != NULL, "");
299       FREE_C_HEAP_ARRAY(char, (void *)old_disable_intrinsic_value);
300     }
301 
302 
303     if (!changed) {
304       // We didn't actually update anything, discard.
305       delete set;
306     } else {
307       // We are returning a (parentless) copy. The originals parent don't need to account for this.
308       DirectivesStack::release(this);
309       return set;
310     }
311   }
312   // Nothing changed
313   return this;
314 }
315 
directive()316 CompilerDirectives* DirectiveSet::directive() {
317   assert(_directive != NULL, "Must have been initialized");
318   return _directive;
319 }
320 
matches_inline(const methodHandle & method,int inline_action)321 bool DirectiveSet::matches_inline(const methodHandle& method, int inline_action) {
322   if (_inlinematchers != NULL) {
323     if (_inlinematchers->match(method, inline_action)) {
324       return true;
325     }
326   }
327   return false;
328 }
329 
should_inline(ciMethod * inlinee)330 bool DirectiveSet::should_inline(ciMethod* inlinee) {
331   inlinee->check_is_loaded();
332   VM_ENTRY_MARK;
333   methodHandle mh(THREAD, inlinee->get_Method());
334 
335   if (_inlinematchers != NULL) {
336     return matches_inline(mh, InlineMatcher::force_inline);
337   }
338   if (!CompilerDirectivesIgnoreCompileCommandsOption) {
339     return CompilerOracle::should_inline(mh);
340   }
341   return false;
342 }
343 
should_not_inline(ciMethod * inlinee)344 bool DirectiveSet::should_not_inline(ciMethod* inlinee) {
345   inlinee->check_is_loaded();
346   VM_ENTRY_MARK;
347   methodHandle mh(THREAD, inlinee->get_Method());
348 
349   if (_inlinematchers != NULL) {
350     return matches_inline(mh, InlineMatcher::dont_inline);
351   }
352   if (!CompilerDirectivesIgnoreCompileCommandsOption) {
353     return CompilerOracle::should_not_inline(mh);
354   }
355   return false;
356 }
357 
parse_and_add_inline(char * str,const char * & error_msg)358 bool DirectiveSet::parse_and_add_inline(char* str, const char*& error_msg) {
359   InlineMatcher* m = InlineMatcher::parse_inline_pattern(str, error_msg);
360   if (m != NULL) {
361     // add matcher last in chain - the order is significant
362     append_inline(m);
363     return true;
364   } else {
365     assert(error_msg != NULL, "Error message must be set");
366     return false;
367   }
368 }
369 
append_inline(InlineMatcher * m)370 void DirectiveSet::append_inline(InlineMatcher* m) {
371   if (_inlinematchers == NULL) {
372     _inlinematchers = m;
373     return;
374   }
375   InlineMatcher* tmp = _inlinematchers;
376   while (tmp->next() != NULL) {
377     tmp = tmp->next();
378   }
379   tmp->set_next(m);
380 }
381 
print_inline(outputStream * st)382 void DirectiveSet::print_inline(outputStream* st) {
383   if (_inlinematchers == NULL) {
384     st->print_cr("  inline: -");
385   } else {
386     st->print("  inline: ");
387     _inlinematchers->print(st);
388     InlineMatcher* tmp = _inlinematchers->next();
389     while (tmp != NULL) {
390       st->print(", ");
391       tmp->print(st);
392       tmp = tmp->next();
393     }
394     st->cr();
395   }
396 }
397 
is_intrinsic_disabled(const methodHandle & method)398 bool DirectiveSet::is_intrinsic_disabled(const methodHandle& method) {
399   vmIntrinsics::ID id = method->intrinsic_id();
400   assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
401 
402   ResourceMark rm;
403 
404   // Create a copy of the string that contains the list of disabled
405   // intrinsics. The copy is created because the string
406   // will be modified by strtok(). Then, the list is tokenized with
407   // ',' as a separator.
408   size_t length = strlen(DisableIntrinsicOption);
409   char* local_list = NEW_RESOURCE_ARRAY(char, length + 1);
410   strncpy(local_list, DisableIntrinsicOption, length + 1);
411   char* save_ptr;
412 
413   char* token = strtok_r(local_list, ",", &save_ptr);
414   while (token != NULL) {
415     if (strcmp(token, vmIntrinsics::name_at(id)) == 0) {
416       return true;
417     } else {
418       token = strtok_r(NULL, ",", &save_ptr);
419     }
420   }
421 
422   return false;
423 }
424 
clone(DirectiveSet const * src)425 DirectiveSet* DirectiveSet::clone(DirectiveSet const* src) {
426   DirectiveSet* set = new DirectiveSet(NULL);
427   // Ordinary allocations of DirectiveSet would call init_disableintrinsic()
428   // immediately to create a new copy for set->DisableIntrinsicOption.
429   // However, here it does not need to because the code below creates
430   // a copy of src->DisableIntrinsicOption that initializes
431   // set->DisableIntrinsicOption.
432 
433   memcpy(set->_modified, src->_modified, sizeof(src->_modified));
434 
435   InlineMatcher* tmp = src->_inlinematchers;
436   while (tmp != NULL) {
437     set->append_inline(tmp->clone());
438     tmp = tmp->next();
439   }
440 
441   #define copy_members_definition(name, type, dvalue, cc_flag) set->name##Option = src->name##Option;
442     compilerdirectives_common_flags(copy_members_definition)
443     compilerdirectives_c2_flags(copy_members_definition)
444     compilerdirectives_c1_flags(copy_members_definition)
445 
446   // Create a local copy of the DisableIntrinsicOption.
447   assert(src->DisableIntrinsicOption != NULL, "");
448   size_t len = strlen(src->DisableIntrinsicOption) + 1;
449   char* s = NEW_C_HEAP_ARRAY(char, len, mtCompiler);
450   strncpy(s, src->DisableIntrinsicOption, len);
451   assert(s[len-1] == '\0', "");
452   set->DisableIntrinsicOption = s;
453   return set;
454 }
455 
456 // Create a new dirstack and push a default directive
init()457 void DirectivesStack::init() {
458   CompilerDirectives* _default_directives = new CompilerDirectives();
459   char str[] = "*.*";
460   const char* error_msg = NULL;
461   _default_directives->add_match(str, error_msg);
462 #if defined(COMPILER1) || INCLUDE_JVMCI
463   _default_directives->_c1_store->EnableOption = true;
464 #endif
465 #ifdef COMPILER2
466   if (is_server_compilation_mode_vm()) {
467     _default_directives->_c2_store->EnableOption = true;
468   }
469 #endif
470   assert(error_msg == NULL, "Must succeed.");
471   push(_default_directives);
472 }
473 
getDefaultDirective(AbstractCompiler * comp)474 DirectiveSet* DirectivesStack::getDefaultDirective(AbstractCompiler* comp) {
475   MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
476 
477   assert(_bottom != NULL, "Must never be empty");
478   _bottom->inc_refcount();
479   return _bottom->get_for(comp);
480 }
481 
push(CompilerDirectives * directive)482 void DirectivesStack::push(CompilerDirectives* directive) {
483   MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
484 
485   directive->inc_refcount();
486   if (_top == NULL) {
487     assert(_bottom == NULL, "There can only be one default directive");
488     _bottom = directive; // default directive, can never be removed.
489   }
490 
491   directive->set_next(_top);
492   _top = directive;
493   _depth++;
494 }
495 
pop(int count)496 void DirectivesStack::pop(int count) {
497   MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
498   assert(count > -1, "No negative values");
499   for (int i = 0; i < count; i++) {
500     pop_inner();
501   }
502 }
503 
pop_inner()504 void DirectivesStack::pop_inner() {
505   assert(DirectivesStack_lock->owned_by_self(), "");
506 
507   if (_top->next() == NULL) {
508     return; // Do nothing - don't allow an empty stack
509   }
510   CompilerDirectives* tmp = _top;
511   _top = _top->next();
512   _depth--;
513 
514   DirectivesStack::release(tmp);
515 }
516 
check_capacity(int request_size,outputStream * st)517 bool DirectivesStack::check_capacity(int request_size, outputStream* st) {
518   if ((request_size + _depth) > CompilerDirectivesLimit) {
519     st->print_cr("Could not add %i more directives. Currently %i/%i directives.", request_size, _depth, CompilerDirectivesLimit);
520     return false;
521   }
522   return true;
523 }
524 
clear()525 void DirectivesStack::clear() {
526   // holding the lock during the whole operation ensuring consistent result
527   MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
528   while (_top->next() != NULL) {
529     pop_inner();
530   }
531 }
532 
print(outputStream * st)533 void DirectivesStack::print(outputStream* st) {
534   MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
535   CompilerDirectives* tmp = _top;
536   while (tmp != NULL) {
537     tmp->print(st);
538     tmp = tmp->next();
539     st->cr();
540   }
541 }
542 
release(DirectiveSet * set)543 void DirectivesStack::release(DirectiveSet* set) {
544   assert(set != NULL, "Never NULL");
545   MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
546   if (set->is_exclusive_copy()) {
547     // Old CompilecCmmands forced us to create an exclusive copy
548     delete set;
549   } else {
550     assert(set->directive() != NULL, "Never NULL");
551     release(set->directive());
552   }
553 }
554 
555 
release(CompilerDirectives * dir)556 void DirectivesStack::release(CompilerDirectives* dir) {
557   assert(DirectivesStack_lock->owned_by_self(), "");
558   dir->dec_refcount();
559   if (dir->refcount() == 0) {
560     delete dir;
561   }
562 }
563 
getMatchingDirective(const methodHandle & method,AbstractCompiler * comp)564 DirectiveSet* DirectivesStack::getMatchingDirective(const methodHandle& method, AbstractCompiler *comp) {
565   assert(_depth > 0, "Must never be empty");
566 
567   DirectiveSet* match = NULL;
568   {
569     MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
570 
571     CompilerDirectives* dir = _top;
572     assert(dir != NULL, "Must be initialized");
573 
574     while (dir != NULL) {
575       if (dir->is_default_directive() || dir->match(method)) {
576         match = dir->get_for(comp);
577         assert(match != NULL, "Consistency");
578         if (match->EnableOption) {
579           // The directiveSet for this compile is also enabled -> success
580           dir->inc_refcount();
581           break;
582         }
583       }
584       dir = dir->next();
585     }
586   }
587   guarantee(match != NULL, "There should always be a default directive that matches");
588 
589   // Check for legacy compile commands update, without DirectivesStack_lock
590   return match->compilecommand_compatibility_init(method);
591 }
592