rev 47445 : 8171853: Remove Shark compiler

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