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