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 }