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