2
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.
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
25
#include "precompiled.hpp"
26
#include "ci/ciMethod.hpp"
27
#include "ci/ciUtilities.inline.hpp"
28
#include "compiler/abstractCompiler.hpp"
29
#include "compiler/compilerDefinitions.inline.hpp"
30
#include "compiler/compilerDirectives.hpp"
31
#include "compiler/compilerOracle.hpp"
32
#include "memory/allocation.inline.hpp"
33
#include "memory/resourceArea.hpp"
34
#include "opto/phasetype.hpp"
35
#include "opto/traceAutoVectorizationTag.hpp"
36
#include "runtime/globals_extension.hpp"
38
CompilerDirectives::CompilerDirectives() : _next(nullptr), _match(nullptr), _ref_count(0) {
39
_c1_store = new DirectiveSet(this);
40
_c1_store->init_control_intrinsic();
41
_c2_store = new DirectiveSet(this);
42
_c2_store->init_control_intrinsic();
45
CompilerDirectives::~CompilerDirectives() {
46
if (_c1_store != nullptr) {
49
if (_c2_store != nullptr) {
53
// remove all linked method matchers
54
BasicMatcher* tmp = _match;
55
while (tmp != nullptr) {
56
BasicMatcher* next = tmp->next();
62
void CompilerDirectives::print(outputStream* st) {
63
assert(DirectivesStack_lock->owned_by_self(), "");
64
if (_match != nullptr) {
66
st->print("Directive:");
67
if (is_default_directive()) {
68
st->print_cr(" (default)");
72
st->print(" matching: ");
74
BasicMatcher* tmp = _match->next();
75
while (tmp != nullptr) {
82
assert(0, "There should always be a match");
85
if (_c1_store != nullptr) {
86
st->print_cr(" c1 directives:");
89
if (_c2_store != nullptr) {
91
st->print_cr(" c2 directives:");
97
void CompilerDirectives::finalize(outputStream* st) {
98
if (_c1_store != nullptr) {
99
_c1_store->finalize(st);
101
if (_c2_store != nullptr) {
102
_c2_store->finalize(st);
106
void DirectiveSet::finalize(outputStream* st) {
108
if (is_c1(this->directive())) {
110
} else if (is_c2(this->directive())) {
113
ShouldNotReachHere();
116
if (LogOption && !LogCompilation) {
117
st->print_cr("Warning: %s: +LogCompilation must be set to enable compilation logging from directives", level);
119
if (PrintAssemblyOption && FLAG_IS_DEFAULT(DebugNonSafepoints)) {
120
warning("%s: printing of assembly code is enabled; turning on DebugNonSafepoints to gain additional output", level);
121
DebugNonSafepoints = true;
124
// if any flag has been modified - set directive as enabled
125
// unless it already has been explicitly set.
126
if (!_modified[EnableIndex]) {
127
if (_inlinematchers != nullptr) {
132
for (i = 0; i < number_of_flags; i++) {
141
CompilerDirectives* CompilerDirectives::next() {
145
bool CompilerDirectives::match(const methodHandle& method) {
146
if (is_default_directive()) {
149
if (method == nullptr) {
152
if (_match->match(method)) {
158
bool CompilerDirectives::add_match(char* str, const char*& error_msg) {
159
BasicMatcher* bm = BasicMatcher::parse_method_pattern(str, error_msg, false);
161
assert(error_msg != nullptr, "Must have error message");
164
bm->set_next(_match);
170
void CompilerDirectives::inc_refcount() {
171
assert(DirectivesStack_lock->owned_by_self(), "");
175
void CompilerDirectives::dec_refcount() {
176
assert(DirectivesStack_lock->owned_by_self(), "");
180
int CompilerDirectives::refcount() {
181
assert(DirectivesStack_lock->owned_by_self(), "");
185
DirectiveSet* CompilerDirectives::get_for(AbstractCompiler *comp) {
186
assert(DirectivesStack_lock->owned_by_self(), "");
187
if (comp == nullptr) { // Xint
189
} else if (comp->is_c2()) {
192
// use c1_store as default
193
assert(comp->is_c1() || comp->is_jvmci(), "");
198
bool DirectiveSet::is_c1(CompilerDirectives* directive) const {
199
return this == directive->_c1_store;
202
bool DirectiveSet::is_c2(CompilerDirectives* directive) const {
203
return this == directive->_c2_store;
206
bool DirectiveSet::should_collect_memstat() const {
207
// MemLimit requires the memory statistic to be active
208
return MemStatOption > 0 || MemLimitOption != 0;
211
bool DirectiveSet::should_print_memstat() const {
212
return MemStatOption == (uintx)MemStatAction::print;
215
size_t DirectiveSet::mem_limit() const {
216
return MemLimitOption < 0 ? -MemLimitOption : MemLimitOption;
219
bool DirectiveSet::should_crash_at_mem_limit() const {
220
// The sign encodes the action to be taken when reaching
221
// the memory limit (+ stop - crash)
222
return MemLimitOption < 0;
225
// In the list of Control/disabled intrinsics, the ID of the control intrinsics can separated:
226
// - by ',' (if -XX:Control/DisableIntrinsic is used once when invoking the VM) or
227
// - by '\n' (if -XX:Control/DisableIntrinsic is used multiple times when invoking the VM) or
228
// - by ' ' (if Control/DisableIntrinsic is used on a per-method level, e.g., with CompileCommand).
230
// To simplify the processing of the list, the canonicalize_control_intrinsic() method
231
// returns a new copy of the list in which '\n' and ' ' is replaced with ','.
232
ccstrlist DirectiveSet::canonicalize_control_intrinsic(ccstrlist option_value) {
233
char* canonicalized_list = NEW_C_HEAP_ARRAY(char, strlen(option_value) + 1, mtCompiler);
236
while ((current = option_value[i]) != '\0') {
237
if (current == '\n' || current == ' ') {
238
canonicalized_list[i] = ',';
240
canonicalized_list[i] = current;
244
canonicalized_list[i] = '\0';
245
return canonicalized_list;
248
ControlIntrinsicIter::ControlIntrinsicIter(ccstrlist option_value, bool disable_all)
249
: _disableIntrinsic(disable_all) {
250
_list = (char*)DirectiveSet::canonicalize_control_intrinsic(option_value);
254
_token = strtok_r(_saved_ptr, ",", &_saved_ptr);
258
ControlIntrinsicIter::~ControlIntrinsicIter() {
259
FREE_C_HEAP_ARRAY(char, _list);
263
ControlIntrinsicIter& ControlIntrinsicIter::operator++() {
264
_token = strtok_r(nullptr, ",", &_saved_ptr);
269
void ControlIntrinsicIter::next_token() {
270
if (_token && !_disableIntrinsic) {
273
if (ch != '+' && ch != '-') {
274
warning("failed to parse %s. must start with +/-!", _token);
276
_enabled = ch == '+';
282
void DirectiveSet::init_control_intrinsic() {
283
for (ControlIntrinsicIter iter(ControlIntrinsic); *iter != nullptr; ++iter) {
284
vmIntrinsics::ID id = vmIntrinsics::find_id(*iter);
286
if (id != vmIntrinsics::_none) {
287
_intrinsic_control_words[vmIntrinsics::as_int(id)] = iter.is_enabled();
291
// Order matters, DisableIntrinsic can overwrite ControlIntrinsic
292
for (ControlIntrinsicIter iter(DisableIntrinsic, true/*disable_all*/); *iter != nullptr; ++iter) {
293
vmIntrinsics::ID id = vmIntrinsics::find_id(*iter);
295
if (id != vmIntrinsics::_none) {
296
_intrinsic_control_words[vmIntrinsics::as_int(id)] = false;
301
DirectiveSet::DirectiveSet(CompilerDirectives* d) :
302
_inlinematchers(nullptr),
304
_ideal_phase_name_set(PHASE_NUM_TYPES, mtCompiler),
305
_trace_auto_vectorization_tags(TRACE_AUTO_VECTORIZATION_TAG_NUM, mtCompiler)
307
#define init_defaults_definition(name, type, dvalue, compiler) this->name##Option = dvalue;
308
compilerdirectives_common_flags(init_defaults_definition)
309
compilerdirectives_c2_flags(init_defaults_definition)
310
compilerdirectives_c1_flags(init_defaults_definition)
311
#undef init_defaults_definition
312
memset(_modified, 0, sizeof(_modified));
313
_intrinsic_control_words.fill_in(/*default value*/TriBool());
316
DirectiveSet::~DirectiveSet() {
317
// remove all linked methodmatchers
318
InlineMatcher* tmp = _inlinematchers;
319
while (tmp != nullptr) {
320
InlineMatcher* next = tmp->next();
325
#define free_string_flags(name, type, dvalue, cc_flag) if (_modified[name##Index]) os::free(const_cast<char*>(name##Option));
326
compilerdirectives_common_string_flags(free_string_flags)
327
compilerdirectives_c2_string_flags(free_string_flags)
328
compilerdirectives_c1_string_flags(free_string_flags)
329
#undef free_string_flags
332
// A smart pointer of DirectiveSet. It uses Copy-on-Write strategy to avoid cloning.
333
// It provides 2 accesses of the underlying raw pointer.
334
// 1) operator->() returns a pointer to a constant DirectiveSet. It's read-only.
335
// 2) cloned() returns a pointer that points to the cloned DirectiveSet.
336
// Users should only use cloned() when they need to update DirectiveSet.
338
// In the end, users need to invoke commit() to finalize the pending changes.
339
// If cloning happens, the smart pointer will return the new pointer after releasing the original
340
// one on DirectivesStack. If cloning doesn't happen, it returns the original intact pointer.
341
class DirectiveSetPtr {
343
DirectiveSet* _origin;
344
DirectiveSet* _clone;
345
NONCOPYABLE(DirectiveSetPtr);
348
DirectiveSetPtr(DirectiveSet* origin): _origin(origin), _clone(nullptr) {
349
assert(origin != nullptr, "DirectiveSetPtr cannot be initialized with a nullptr pointer.");
352
DirectiveSet const* operator->() {
353
return (_clone == nullptr) ? _origin : _clone;
356
DirectiveSet* cloned() {
357
if (_clone == nullptr) {
358
_clone = DirectiveSet::clone(_origin);
363
DirectiveSet* commit() {
364
if (_clone != nullptr) {
365
// We are returning a (parentless) copy. The originals parent don't need to account for this.
366
DirectivesStack::release(_origin);
375
// Backward compatibility for CompileCommands
376
// Breaks the abstraction and causes lots of extra complexity
377
// - if some option is changed we need to copy directiveset since it no longer can be shared
378
// - Need to free copy after use
379
// - Requires a modified bit so we don't overwrite options that is set by directives
380
DirectiveSet* DirectiveSet::compilecommand_compatibility_init(const methodHandle& method) {
381
// Early bail out - checking all options is expensive - we rely on them not being used
382
// Only set a flag if it has not been modified and value changes.
383
// Only copy set if a flag needs to be set
384
if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::has_any_command_set()) {
385
DirectiveSetPtr set(this);
389
// If the directives didn't have 'BreakAtExecute',
390
// the command 'C1Breakpoint' would become effective.
391
if (!_modified[BreakAtExecuteIndex]) {
392
set.cloned()->BreakAtExecuteOption = true;
397
// All CompileCommands are not equal so this gets a bit verbose
398
// When CompileCommands have been refactored less clutter will remain.
399
if (CompilerOracle::should_break_at(method)) {
400
// If the directives didn't have 'BreakAtCompile' or 'BreakAtExecute',
401
// the sub-command 'Break' of the 'CompileCommand' would become effective.
402
if (!_modified[BreakAtCompileIndex]) {
403
set.cloned()->BreakAtCompileOption = true;
405
if (!_modified[BreakAtExecuteIndex]) {
406
set.cloned()->BreakAtExecuteOption = true;
409
if (!_modified[LogIndex]) {
410
bool log = CompilerOracle::should_log(method);
411
if (log != set->LogOption) {
412
set.cloned()->LogOption = log;
416
if (CompilerOracle::should_print(method)) {
417
if (!_modified[PrintAssemblyIndex]) {
418
set.cloned()->PrintAssemblyOption = true;
421
// Exclude as in should not compile == Enabled
422
if (CompilerOracle::should_exclude(method)) {
423
if (!_modified[ExcludeIndex]) {
424
set.cloned()->ExcludeOption = true;
428
// inline and dontinline (including exclude) are implemented in the directiveset accessors
429
#define init_default_cc(name, type, dvalue, cc_flag) { type v; if (!_modified[name##Index] && CompileCommandEnum::cc_flag != CompileCommandEnum::Unknown && CompilerOracle::has_option_value(method, CompileCommandEnum::cc_flag, v) && v != this->name##Option) { set.cloned()->name##Option = v; } }
430
compilerdirectives_common_flags(init_default_cc)
431
compilerdirectives_c2_flags(init_default_cc)
432
compilerdirectives_c1_flags(init_default_cc)
433
#undef init_default_cc
435
// Parse PrintIdealPhaseName and create a lookup set
438
if (!_modified[TraceAutoVectorizationIndex]) {
439
// Parse ccstr and create mask
441
if (CompilerOracle::has_option_value(method, CompileCommandEnum::TraceAutoVectorization, option)) {
442
TraceAutoVectorizationTagValidator validator(option, false);
443
if (validator.is_valid()) {
444
set.cloned()->set_trace_auto_vectorization_tags(validator.tags());
448
if (!_modified[PrintIdealPhaseIndex]) {
449
// Parse ccstr and create set
451
if (CompilerOracle::has_option_value(method, CompileCommandEnum::PrintIdealPhase, option)) {
452
PhaseNameValidator validator(option);
453
if (validator.is_valid()) {
454
assert(!validator.phase_name_set().is_empty(), "Phase name set must be non-empty");
455
set.cloned()->set_ideal_phase_name_set(validator.phase_name_set());
462
// Canonicalize DisableIntrinsic to contain only ',' as a separator.
463
ccstrlist option_value;
464
bool need_reset = true; // if Control/DisableIntrinsic redefined, only need to reset control_words once
466
if (!_modified[ControlIntrinsicIndex] &&
467
CompilerOracle::has_option_value(method, CompileCommandEnum::ControlIntrinsic, option_value)) {
468
ControlIntrinsicIter iter(option_value);
471
set.cloned()->_intrinsic_control_words.fill_in(TriBool());
475
while (*iter != nullptr) {
476
vmIntrinsics::ID id = vmIntrinsics::find_id(*iter);
477
if (id != vmIntrinsics::_none) {
478
set.cloned()->_intrinsic_control_words[vmIntrinsics::as_int(id)] = iter.is_enabled();
486
if (!_modified[DisableIntrinsicIndex] &&
487
CompilerOracle::has_option_value(method, CompileCommandEnum::DisableIntrinsic, option_value)) {
488
ControlIntrinsicIter iter(option_value, true/*disable_all*/);
491
set.cloned()->_intrinsic_control_words.fill_in(TriBool());
495
while (*iter != nullptr) {
496
vmIntrinsics::ID id = vmIntrinsics::find_id(*iter);
497
if (id != vmIntrinsics::_none) {
498
set.cloned()->_intrinsic_control_words[vmIntrinsics::as_int(id)] = false;
511
CompilerDirectives* DirectiveSet::directive() {
512
assert(_directive != nullptr, "Must have been initialized");
516
bool DirectiveSet::matches_inline(const methodHandle& method, int inline_action) {
517
if (_inlinematchers != nullptr) {
518
if (_inlinematchers->match(method, inline_action)) {
525
bool DirectiveSet::should_inline(ciMethod* inlinee) {
526
inlinee->check_is_loaded();
528
methodHandle mh(THREAD, inlinee->get_Method());
530
if (_inlinematchers != nullptr) {
531
return matches_inline(mh, InlineMatcher::force_inline);
533
if (!CompilerDirectivesIgnoreCompileCommandsOption) {
534
return CompilerOracle::should_inline(mh);
539
bool DirectiveSet::should_not_inline(ciMethod* inlinee) {
540
inlinee->check_is_loaded();
542
methodHandle mh(THREAD, inlinee->get_Method());
544
if (_inlinematchers != nullptr) {
545
return matches_inline(mh, InlineMatcher::dont_inline);
547
if (!CompilerDirectivesIgnoreCompileCommandsOption) {
548
return CompilerOracle::should_not_inline(mh);
553
bool DirectiveSet::parse_and_add_inline(char* str, const char*& error_msg) {
554
InlineMatcher* m = InlineMatcher::parse_inline_pattern(str, error_msg);
556
// add matcher last in chain - the order is significant
560
assert(error_msg != nullptr, "Error message must be set");
565
void DirectiveSet::append_inline(InlineMatcher* m) {
566
if (_inlinematchers == nullptr) {
570
InlineMatcher* tmp = _inlinematchers;
571
while (tmp->next() != nullptr) {
577
void DirectiveSet::print_inline(outputStream* st) {
578
if (_inlinematchers == nullptr) {
579
st->print_cr(" inline: -");
581
st->print(" inline: ");
582
_inlinematchers->print(st);
583
InlineMatcher* tmp = _inlinematchers->next();
584
while (tmp != nullptr) {
593
bool DirectiveSet::is_intrinsic_disabled(vmIntrinsics::ID id) {
594
assert(id > vmIntrinsics::_none && id < vmIntrinsics::ID_LIMIT, "invalid intrinsic_id!");
596
TriBool b = _intrinsic_control_words[vmIntrinsics::as_int(id)];
597
if (b.is_default()) {
598
return false; // if unset, every intrinsic is enabled.
604
DirectiveSet* DirectiveSet::clone(DirectiveSet const* src) {
605
DirectiveSet* set = new DirectiveSet(nullptr);
606
// Ordinary allocations of DirectiveSet would call init_control_intrinsic()
607
// immediately to create a new copy for set->Control/DisableIntrinsicOption.
608
// However, here it does not need to because the code below creates
609
// a copy of src->Control/DisableIntrinsicOption that initializes
610
// set->Control/DisableIntrinsicOption.
612
memcpy(set->_modified, src->_modified, sizeof(src->_modified));
614
InlineMatcher* tmp = src->_inlinematchers;
615
while (tmp != nullptr) {
616
set->append_inline(tmp->clone());
620
#define copy_members_definition(name, type, dvalue, cc_flag) set->name##Option = src->name##Option;
621
compilerdirectives_common_other_flags(copy_members_definition)
622
compilerdirectives_c2_other_flags(copy_members_definition)
623
compilerdirectives_c1_other_flags(copy_members_definition)
624
#undef copy_members_definition
626
#define copy_string_members_definition(name, type, dvalue, cc_flag) \
627
if (src->_modified[name##Index]) { \
628
set->name##Option = os::strdup_check_oom(src->name##Option, mtCompiler); \
630
set->name##Option = src->name##Option; \
632
compilerdirectives_common_string_flags(copy_string_members_definition)
633
compilerdirectives_c2_string_flags(copy_string_members_definition)
634
compilerdirectives_c1_string_flags(copy_string_members_definition)
635
#undef copy_string_members_definition
637
set->_intrinsic_control_words = src->_intrinsic_control_words;
638
set->set_ideal_phase_name_set(src->_ideal_phase_name_set);
642
// Create a new dirstack and push a default directive
643
void DirectivesStack::init() {
644
CompilerDirectives* _default_directives = new CompilerDirectives();
646
const char* error_msg = nullptr;
647
_default_directives->add_match(str, error_msg);
648
#if defined(COMPILER1) || INCLUDE_JVMCI
649
_default_directives->_c1_store->EnableOption = true;
652
if (CompilerConfig::is_c2_enabled()) {
653
_default_directives->_c2_store->EnableOption = true;
656
assert(error_msg == nullptr, "Must succeed.");
657
push(_default_directives);
660
DirectiveSet* DirectivesStack::getDefaultDirective(AbstractCompiler* comp) {
661
MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
663
assert(_bottom != nullptr, "Must never be empty");
664
_bottom->inc_refcount();
665
return _bottom->get_for(comp);
668
void DirectivesStack::push(CompilerDirectives* directive) {
669
MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
671
directive->inc_refcount();
672
if (_top == nullptr) {
673
assert(_bottom == nullptr, "There can only be one default directive");
674
_bottom = directive; // default directive, can never be removed.
677
directive->set_next(_top);
682
void DirectivesStack::pop(int count) {
683
MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
684
assert(count > -1, "No negative values");
685
for (int i = 0; i < count; i++) {
690
void DirectivesStack::pop_inner() {
691
assert(DirectivesStack_lock->owned_by_self(), "");
693
if (_top->next() == nullptr) {
694
return; // Do nothing - don't allow an empty stack
696
CompilerDirectives* tmp = _top;
700
DirectivesStack::release(tmp);
703
bool DirectivesStack::check_capacity(int request_size, outputStream* st) {
704
if ((request_size + _depth) > CompilerDirectivesLimit) {
705
st->print_cr("Could not add %i more directives. Currently %i/%i directives.", request_size, _depth, CompilerDirectivesLimit);
711
void DirectivesStack::clear() {
712
// holding the lock during the whole operation ensuring consistent result
713
MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
714
while (_top->next() != nullptr) {
719
void DirectivesStack::print(outputStream* st) {
720
MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
721
CompilerDirectives* tmp = _top;
722
while (tmp != nullptr) {
729
void DirectivesStack::release(DirectiveSet* set) {
730
assert(set != nullptr, "Never nullptr");
731
MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
732
if (set->is_exclusive_copy()) {
733
// Old CompilecCmmands forced us to create an exclusive copy
736
assert(set->directive() != nullptr, "Never nullptr");
737
release(set->directive());
742
void DirectivesStack::release(CompilerDirectives* dir) {
743
assert(DirectivesStack_lock->owned_by_self(), "");
745
if (dir->refcount() == 0) {
750
DirectiveSet* DirectivesStack::getMatchingDirective(const methodHandle& method, AbstractCompiler *comp) {
751
assert(_depth > 0, "Must never be empty");
753
DirectiveSet* match = nullptr;
755
MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
757
CompilerDirectives* dir = _top;
758
assert(dir != nullptr, "Must be initialized");
760
while (dir != nullptr) {
761
if (dir->is_default_directive() || dir->match(method)) {
762
match = dir->get_for(comp);
763
assert(match != nullptr, "Consistency");
764
if (match->EnableOption || dir->is_default_directive()) {
765
// The directiveSet for this compile is also enabled -> success
773
guarantee(match != nullptr, "There should always be a default directive that matches");
775
// Check for legacy compile commands update, without DirectivesStack_lock
776
return match->compilecommand_compatibility_init(method);