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 33CompilerDirectives::CompilerDirectives() :_match(NULL), _next(NULL), _ref_count(0) { 34 _c1_store = new DirectiveSet(this); 35 _c2_store = new DirectiveSet(this); 36}; 37 38CompilerDirectives::~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 55void 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 90void 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 99void 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 122CompilerDirectives* CompilerDirectives::next() { 123 return _next; 124} 125 126bool 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 139bool 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 151void CompilerDirectives::inc_refcount() { 152 assert(DirectivesStack_lock->owned_by_self(), ""); 153 _ref_count++; 154} 155 156void CompilerDirectives::dec_refcount() { 157 assert(DirectivesStack_lock->owned_by_self(), ""); 158 _ref_count--; 159} 160 161int CompilerDirectives::refcount() { 162 assert(DirectivesStack_lock->owned_by_self(), ""); 163 return _ref_count; 164} 165 166DirectiveSet* 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 ','. 186ccstrlist 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 202DirectiveSet::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 213DirectiveSet::~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 235DirectiveSet* 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 305CompilerDirectives* DirectiveSet::directive() { 306 assert(_directive != NULL, "Must have been initialized"); 307 return _directive; 308} 309 310bool 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 319bool 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 333bool 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 347bool 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 359void 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 371void 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 387bool 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 413DirectiveSet* 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 439void 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 456DirectiveSet* 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 464void 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 478void 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 486void 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 499bool 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 507void 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 515void 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 525void 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 538void 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 546DirectiveSet* 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} 574