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