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 
  34 CompilerDirectives::CompilerDirectives() : _next(NULL), _match(NULL), _ref_count(0) {
  35   _c1_store = new DirectiveSet(this);
  36   _c1_store->init_control_intrinsic();
  37   _c2_store = new DirectiveSet(this);
  38   _c2_store->init_control_intrinsic();
  39 };
  40 
  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 
  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 
  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 
 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 
 125 CompilerDirectives* CompilerDirectives::next() {
 126   return _next;
 127 }
 128 
 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 
 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 
 154 void CompilerDirectives::inc_refcount() {
 155   assert(DirectivesStack_lock->owned_by_self(), "");
 156   _ref_count++;
 157 }
 158 
 159 void CompilerDirectives::dec_refcount() {
 160   assert(DirectivesStack_lock->owned_by_self(), "");
 161   _ref_count--;
 162 }
 163 
 164 int CompilerDirectives::refcount() {
 165   assert(DirectivesStack_lock->owned_by_self(), "");
 166   return _ref_count;
 167 }
 168 
 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 Control/disabled intrinsics, the ID of the control intrinsics can separated:
 183 // - by ',' (if -XX:Control/DisableIntrinsic is used once when invoking the VM) or
 184 // - by '\n' (if -XX:Control/DisableIntrinsic is used multiple times when invoking the VM) or
 185 // - by ' ' (if Control/DisableIntrinsic is used on a per-method level, e.g., with CompileCommand).
 186 //
 187 // To simplify the processing of the list, the canonicalize_control_intrinsic() method
 188 // returns a new copy of the list in which '\n' and ' ' is replaced with ','.
 189 ccstrlist DirectiveSet::canonicalize_control_intrinsic(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 
 205 ControlIntrinsicIter::ControlIntrinsicIter(ccstrlist option_value, bool disable_all)
 206   : _disableIntrinsic(disable_all) {
 207   _list = (char*)DirectiveSet::canonicalize_control_intrinsic(option_value);
 208   _saved_ptr = _list;
 209   _enabled = false;
 210 
 211   _token = strtok_r(_saved_ptr, ",", &_saved_ptr);
 212   next_token();
 213 }
 214 
 215 ControlIntrinsicIter::~ControlIntrinsicIter() {
 216   FREE_C_HEAP_ARRAY(char, _list);
 217 }
 218 
 219 // pre-increment
 220 ControlIntrinsicIter& ControlIntrinsicIter::operator++() {
 221   _token = strtok_r(NULL, ",", &_saved_ptr);
 222   next_token();
 223   return *this;
 224 }
 225 
 226 void ControlIntrinsicIter::next_token() {
 227   if (_token && !_disableIntrinsic) {
 228     char ch = _token[0];
 229 
 230     if (ch != '+' && ch != '-') {
 231       warning("failed to parse %s. must start with +/-!", _token);
 232     } else {
 233       _enabled = ch == '+';
 234       _token++;
 235     }
 236   }
 237 }
 238 
 239 void DirectiveSet::init_control_intrinsic() {
 240   for (ControlIntrinsicIter iter(ControlIntrinsic); *iter != NULL; ++iter) {
 241     vmIntrinsics::ID id = vmIntrinsics::find_id(*iter);
 242 
 243     if (id != vmIntrinsics::_none) {
 244       _intrinsic_control_words[id] = iter.is_enabled();
 245     }
 246   }
 247 
 248   // Order matters, DisableIntrinsic can overwrite ControlIntrinsic
 249   for (ControlIntrinsicIter iter(DisableIntrinsic, true/*disable_all*/); *iter != NULL; ++iter) {
 250     vmIntrinsics::ID id = vmIntrinsics::find_id(*iter);
 251 
 252     if (id != vmIntrinsics::_none) {
 253       _intrinsic_control_words[id] = false;
 254     }
 255   }
 256 }
 257 
 258 DirectiveSet::DirectiveSet(CompilerDirectives* d) :_inlinematchers(NULL), _directive(d) {
 259 #define init_defaults_definition(name, type, dvalue, compiler) this->name##Option = dvalue;
 260   compilerdirectives_common_flags(init_defaults_definition)
 261   compilerdirectives_c2_flags(init_defaults_definition)
 262   compilerdirectives_c1_flags(init_defaults_definition)
 263   memset(_modified, 0, sizeof(_modified));
 264   _intrinsic_control_words.fill_in(/*default value*/TriBool());
 265 }
 266 
 267 DirectiveSet::~DirectiveSet() {
 268   // remove all linked methodmatchers
 269   InlineMatcher* tmp = _inlinematchers;
 270   while (tmp != NULL) {
 271     InlineMatcher* next = tmp->next();
 272     delete tmp;
 273     tmp = next;
 274   }
 275 }
 276 
 277 // Backward compatibility for CompileCommands
 278 // Breaks the abstraction and causes lots of extra complexity
 279 // - if some option is changed we need to copy directiveset since it no longer can be shared
 280 // - Need to free copy after use
 281 // - Requires a modified bit so we don't overwrite options that is set by directives
 282 
 283 DirectiveSet* DirectiveSet::compilecommand_compatibility_init(const methodHandle& method) {
 284   // Early bail out - checking all options is expensive - we rely on them not being used
 285   // Only set a flag if it has not been modified and value changes.
 286   // Only copy set if a flag needs to be set
 287   if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::has_any_option()) {
 288     DirectiveSet* set = DirectiveSet::clone(this);
 289 
 290     bool changed = false; // Track if we actually change anything
 291 
 292     // All CompileCommands are not equal so this gets a bit verbose
 293     // When CompileCommands have been refactored less clutter will remain.
 294     if (CompilerOracle::should_break_at(method)) {
 295       if (!_modified[BreakAtCompileIndex]) {
 296         set->BreakAtCompileOption = true;
 297         changed = true;
 298       }
 299       if (!_modified[BreakAtExecuteIndex]) {
 300         set->BreakAtExecuteOption = true;
 301         changed = true;
 302       }
 303     }
 304     if (!_modified[LogIndex]) {
 305       bool log = CompilerOracle::should_log(method);
 306       if (log != set->LogOption) {
 307         set->LogOption = log;
 308         changed = true;
 309       }
 310     }
 311 
 312     if (CompilerOracle::should_print(method)) {
 313       if (!_modified[PrintAssemblyIndex]) {
 314         set->PrintAssemblyOption = true;
 315         changed = true;
 316       }
 317     }
 318     // Exclude as in should not compile == Enabled
 319     if (CompilerOracle::should_exclude(method)) {
 320       if (!_modified[ExcludeIndex]) {
 321         set->ExcludeOption = true;
 322         changed = true;
 323       }
 324     }
 325 
 326     // inline and dontinline (including exclude) are implemented in the directiveset accessors
 327 #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;} }
 328     compilerdirectives_common_flags(init_default_cc)
 329     compilerdirectives_c2_flags(init_default_cc)
 330     compilerdirectives_c1_flags(init_default_cc)
 331 
 332     // Canonicalize DisableIntrinsic to contain only ',' as a separator.
 333     ccstrlist option_value;
 334     bool need_reset = true; // if Control/DisableIntrinsic redefined, only need to reset control_words once
 335 
 336     if (!_modified[ControlIntrinsicIndex] &&
 337         CompilerOracle::has_option_value(method, "ControlIntrinsic", option_value)) {
 338       ResourceMark rm;
 339       ControlIntrinsicValidator validator(option_value, false/*disable_all*/);
 340       ControlIntrinsicIter iter(option_value);
 341 
 342       guarantee(validator.is_valid(), "An unrecognized intrinsic is detected in the directive of ControlIntrinsic %s : %s",
 343                                       method->external_name_short(), validator.what());
 344       if (need_reset) {
 345         set->_intrinsic_control_words.fill_in(TriBool());
 346         need_reset = false;
 347       }
 348 
 349       while (*iter != NULL) {
 350         vmIntrinsics::ID id = vmIntrinsics::find_id(*iter);
 351         if (id != vmIntrinsics::_none) {
 352           set->_intrinsic_control_words[id] = iter.is_enabled();
 353         }
 354 
 355         ++iter;
 356       }
 357     }
 358 
 359 
 360     if (!_modified[DisableIntrinsicIndex] &&
 361         CompilerOracle::has_option_value(method, "DisableIntrinsic", option_value)) {
 362       ResourceMark rm;
 363       ControlIntrinsicValidator validator(option_value, true/*disable_all*/);
 364       ControlIntrinsicIter iter(option_value, true/*disable_all*/);
 365 
 366       guarantee(validator.is_valid(), "An unrecognized intrinsic is detected in the directive of DisableIntrinsic %s : %s",
 367                                       method->external_name_short(), validator.what());
 368       if (need_reset) {
 369         set->_intrinsic_control_words.fill_in(TriBool());
 370         need_reset = false;
 371       }
 372 
 373       while (*iter != NULL) {
 374         vmIntrinsics::ID id = vmIntrinsics::find_id(*iter);
 375         if (id != vmIntrinsics::_none) {
 376           set->_intrinsic_control_words[id] = false;
 377         }
 378 
 379         ++iter;
 380       }
 381     }
 382 
 383 
 384     if (!changed) {
 385       // We didn't actually update anything, discard.
 386       delete set;
 387     } else {
 388       // We are returning a (parentless) copy. The originals parent don't need to account for this.
 389       DirectivesStack::release(this);
 390       return set;
 391     }
 392   }
 393   // Nothing changed
 394   return this;
 395 }
 396 
 397 CompilerDirectives* DirectiveSet::directive() {
 398   assert(_directive != NULL, "Must have been initialized");
 399   return _directive;
 400 }
 401 
 402 bool DirectiveSet::matches_inline(const methodHandle& method, int inline_action) {
 403   if (_inlinematchers != NULL) {
 404     if (_inlinematchers->match(method, inline_action)) {
 405       return true;
 406     }
 407   }
 408   return false;
 409 }
 410 
 411 bool DirectiveSet::should_inline(ciMethod* inlinee) {
 412   inlinee->check_is_loaded();
 413   VM_ENTRY_MARK;
 414   methodHandle mh(THREAD, inlinee->get_Method());
 415 
 416   if (_inlinematchers != NULL) {
 417     return matches_inline(mh, InlineMatcher::force_inline);
 418   }
 419   if (!CompilerDirectivesIgnoreCompileCommandsOption) {
 420     return CompilerOracle::should_inline(mh);
 421   }
 422   return false;
 423 }
 424 
 425 bool DirectiveSet::should_not_inline(ciMethod* inlinee) {
 426   inlinee->check_is_loaded();
 427   VM_ENTRY_MARK;
 428   methodHandle mh(THREAD, inlinee->get_Method());
 429 
 430   if (_inlinematchers != NULL) {
 431     return matches_inline(mh, InlineMatcher::dont_inline);
 432   }
 433   if (!CompilerDirectivesIgnoreCompileCommandsOption) {
 434     return CompilerOracle::should_not_inline(mh);
 435   }
 436   return false;
 437 }
 438 
 439 bool DirectiveSet::parse_and_add_inline(char* str, const char*& error_msg) {
 440   InlineMatcher* m = InlineMatcher::parse_inline_pattern(str, error_msg);
 441   if (m != NULL) {
 442     // add matcher last in chain - the order is significant
 443     append_inline(m);
 444     return true;
 445   } else {
 446     assert(error_msg != NULL, "Error message must be set");
 447     return false;
 448   }
 449 }
 450 
 451 void DirectiveSet::append_inline(InlineMatcher* m) {
 452   if (_inlinematchers == NULL) {
 453     _inlinematchers = m;
 454     return;
 455   }
 456   InlineMatcher* tmp = _inlinematchers;
 457   while (tmp->next() != NULL) {
 458     tmp = tmp->next();
 459   }
 460   tmp->set_next(m);
 461 }
 462 
 463 void DirectiveSet::print_inline(outputStream* st) {
 464   if (_inlinematchers == NULL) {
 465     st->print_cr("  inline: -");
 466   } else {
 467     st->print("  inline: ");
 468     _inlinematchers->print(st);
 469     InlineMatcher* tmp = _inlinematchers->next();
 470     while (tmp != NULL) {
 471       st->print(", ");
 472       tmp->print(st);
 473       tmp = tmp->next();
 474     }
 475     st->cr();
 476   }
 477 }
 478 
 479 bool DirectiveSet::is_intrinsic_disabled(const methodHandle& method) {
 480   vmIntrinsics::ID id = method->intrinsic_id();
 481   assert(id > vmIntrinsics::_none && id < vmIntrinsics::ID_LIMIT, "invalid intrinsic_id!");
 482 
 483   TriBool b = _intrinsic_control_words[id];
 484   if (b.is_default()) {
 485     return false; // if unset, every intrinsic is enabled.
 486   } else {
 487     return !b;
 488   }
 489 }
 490 
 491 DirectiveSet* DirectiveSet::clone(DirectiveSet const* src) {
 492   DirectiveSet* set = new DirectiveSet(NULL);
 493   // Ordinary allocations of DirectiveSet would call init_control_intrinsic()
 494   // immediately to create a new copy for set->Control/DisableIntrinsicOption.
 495   // However, here it does not need to because the code below creates
 496   // a copy of src->Control/DisableIntrinsicOption that initializes
 497   // set->Control/DisableIntrinsicOption.
 498 
 499   memcpy(set->_modified, src->_modified, sizeof(src->_modified));
 500 
 501   InlineMatcher* tmp = src->_inlinematchers;
 502   while (tmp != NULL) {
 503     set->append_inline(tmp->clone());
 504     tmp = tmp->next();
 505   }
 506 
 507   #define copy_members_definition(name, type, dvalue, cc_flag) set->name##Option = src->name##Option;
 508     compilerdirectives_common_flags(copy_members_definition)
 509     compilerdirectives_c2_flags(copy_members_definition)
 510     compilerdirectives_c1_flags(copy_members_definition)
 511 
 512   set->_intrinsic_control_words = src->_intrinsic_control_words;
 513   return set;
 514 }
 515 
 516 // Create a new dirstack and push a default directive
 517 void DirectivesStack::init() {
 518   CompilerDirectives* _default_directives = new CompilerDirectives();
 519   char str[] = "*.*";
 520   const char* error_msg = NULL;
 521   _default_directives->add_match(str, error_msg);
 522 #if defined(COMPILER1) || INCLUDE_JVMCI
 523   _default_directives->_c1_store->EnableOption = true;
 524 #endif
 525 #ifdef COMPILER2
 526   if (is_server_compilation_mode_vm()) {
 527     _default_directives->_c2_store->EnableOption = true;
 528   }
 529 #endif
 530   assert(error_msg == NULL, "Must succeed.");
 531   push(_default_directives);
 532 }
 533 
 534 DirectiveSet* DirectivesStack::getDefaultDirective(AbstractCompiler* comp) {
 535   MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
 536 
 537   assert(_bottom != NULL, "Must never be empty");
 538   _bottom->inc_refcount();
 539   return _bottom->get_for(comp);
 540 }
 541 
 542 void DirectivesStack::push(CompilerDirectives* directive) {
 543   MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
 544 
 545   directive->inc_refcount();
 546   if (_top == NULL) {
 547     assert(_bottom == NULL, "There can only be one default directive");
 548     _bottom = directive; // default directive, can never be removed.
 549   }
 550 
 551   directive->set_next(_top);
 552   _top = directive;
 553   _depth++;
 554 }
 555 
 556 void DirectivesStack::pop(int count) {
 557   MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
 558   assert(count > -1, "No negative values");
 559   for (int i = 0; i < count; i++) {
 560     pop_inner();
 561   }
 562 }
 563 
 564 void DirectivesStack::pop_inner() {
 565   assert(DirectivesStack_lock->owned_by_self(), "");
 566 
 567   if (_top->next() == NULL) {
 568     return; // Do nothing - don't allow an empty stack
 569   }
 570   CompilerDirectives* tmp = _top;
 571   _top = _top->next();
 572   _depth--;
 573 
 574   DirectivesStack::release(tmp);
 575 }
 576 
 577 bool DirectivesStack::check_capacity(int request_size, outputStream* st) {
 578   if ((request_size + _depth) > CompilerDirectivesLimit) {
 579     st->print_cr("Could not add %i more directives. Currently %i/%i directives.", request_size, _depth, CompilerDirectivesLimit);
 580     return false;
 581   }
 582   return true;
 583 }
 584 
 585 void DirectivesStack::clear() {
 586   // holding the lock during the whole operation ensuring consistent result
 587   MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
 588   while (_top->next() != NULL) {
 589     pop_inner();
 590   }
 591 }
 592 
 593 void DirectivesStack::print(outputStream* st) {
 594   MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
 595   CompilerDirectives* tmp = _top;
 596   while (tmp != NULL) {
 597     tmp->print(st);
 598     tmp = tmp->next();
 599     st->cr();
 600   }
 601 }
 602 
 603 void DirectivesStack::release(DirectiveSet* set) {
 604   assert(set != NULL, "Never NULL");
 605   MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
 606   if (set->is_exclusive_copy()) {
 607     // Old CompilecCmmands forced us to create an exclusive copy
 608     delete set;
 609   } else {
 610     assert(set->directive() != NULL, "Never NULL");
 611     release(set->directive());
 612   }
 613 }
 614 
 615 
 616 void DirectivesStack::release(CompilerDirectives* dir) {
 617   assert(DirectivesStack_lock->owned_by_self(), "");
 618   dir->dec_refcount();
 619   if (dir->refcount() == 0) {
 620     delete dir;
 621   }
 622 }
 623 
 624 DirectiveSet* DirectivesStack::getMatchingDirective(const methodHandle& method, AbstractCompiler *comp) {
 625   assert(_depth > 0, "Must never be empty");
 626 
 627   DirectiveSet* match = NULL;
 628   {
 629     MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
 630 
 631     CompilerDirectives* dir = _top;
 632     assert(dir != NULL, "Must be initialized");
 633 
 634     while (dir != NULL) {
 635       if (dir->is_default_directive() || dir->match(method)) {
 636         match = dir->get_for(comp);
 637         assert(match != NULL, "Consistency");
 638         if (match->EnableOption) {
 639           // The directiveSet for this compile is also enabled -> success
 640           dir->inc_refcount();
 641           break;
 642         }
 643       }
 644       dir = dir->next();
 645     }
 646   }
 647   guarantee(match != NULL, "There should always be a default directive that matches");
 648 
 649   // Check for legacy compile commands update, without DirectivesStack_lock
 650   return match->compilecommand_compatibility_init(method);
 651 }