/* * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
if (LogOption && !LogCompilation) {
st->print_cr("Warning: %s: +LogCompilation must be set to enable compilation logging from directives", level);
} if (PrintAssemblyOption && FLAG_IS_DEFAULT(DebugNonSafepoints)) {
warning("%s: printing of assembly code is enabled; turning on DebugNonSafepoints to gain additional output", level);
DebugNonSafepoints = true;
}
// if any flag has been modified - set directive as enabled // unless it already has been explicitly set. if (!_modified[EnableIndex]) { if (_inlinematchers != NULL) {
EnableOption = true; return;
} int i; for (i = 0; i < number_of_flags; i++) { if (_modified[i]) {
EnableOption = true; return;
}
}
}
}
// In the list of Control/disabled intrinsics, the ID of the control intrinsics can separated: // - by ',' (if -XX:Control/DisableIntrinsic is used once when invoking the VM) or // - by '\n' (if -XX:Control/DisableIntrinsic is used multiple times when invoking the VM) or // - by ' ' (if Control/DisableIntrinsic is used on a per-method level, e.g., with CompileCommand). // // To simplify the processing of the list, the canonicalize_control_intrinsic() method // returns a new copy of the list in which '\n' and ' ' is replaced with ','.
ccstrlist DirectiveSet::canonicalize_control_intrinsic(ccstrlist option_value) { char* canonicalized_list = NEW_C_HEAP_ARRAY(char, strlen(option_value) + 1, mtCompiler); int i = 0; char current; while ((current = option_value[i]) != '\0') { if (current == '\n' || current == ' ') {
canonicalized_list[i] = ',';
} else {
canonicalized_list[i] = current;
}
i++;
}
canonicalized_list[i] = '\0'; return canonicalized_list;
}
if (ch != '+' && ch != '-') {
warning("failed to parse %s. must start with +/-!", _token);
} else {
_enabled = ch == '+';
_token++;
}
}
}
void DirectiveSet::init_control_intrinsic() { for (ControlIntrinsicIter iter(ControlIntrinsic); *iter != NULL; ++iter) {
vmIntrinsics::ID id = vmIntrinsics::find_id(*iter);
if (id != vmIntrinsics::_none) {
_intrinsic_control_words[vmIntrinsics::as_int(id)] = iter.is_enabled();
}
}
// Order matters, DisableIntrinsic can overwrite ControlIntrinsic for (ControlIntrinsicIter iter(DisableIntrinsic, true/*disable_all*/); *iter != NULL; ++iter) {
vmIntrinsics::ID id = vmIntrinsics::find_id(*iter);
if (id != vmIntrinsics::_none) {
_intrinsic_control_words[vmIntrinsics::as_int(id)] = false;
}
}
}
DirectiveSet::~DirectiveSet() { // remove all linked methodmatchers
InlineMatcher* tmp = _inlinematchers; while (tmp != NULL) {
InlineMatcher* next = tmp->next(); delete tmp;
tmp = next;
}
}
// A smart pointer of DirectiveSet. It uses Copy-on-Write strategy to avoid cloning. // It provides 2 accesses of the underlying raw pointer. // 1) operator->() returns a pointer to a constant DirectiveSet. It's read-only. // 2) cloned() returns a pointer that points to the cloned DirectiveSet. // Users should only use cloned() when they need to update DirectiveSet. // // In the end, users need to invoke commit() to finalize the pending changes. // If cloning happens, the smart pointer will return the new pointer after releasing the original // one on DirectivesStack. If cloning doesn't happen, it returns the original intact pointer. class DirectiveSetPtr { private:
DirectiveSet* _origin;
DirectiveSet* _clone;
NONCOPYABLE(DirectiveSetPtr);
public:
DirectiveSetPtr(DirectiveSet* origin): _origin(origin), _clone(nullptr) {
assert(origin != nullptr, "DirectiveSetPtr cannot be initialized with a NULL pointer.");
}
DirectiveSet* commit() { if (_clone != nullptr) { // We are returning a (parentless) copy. The originals parent don't need to account for this.
DirectivesStack::release(_origin);
_origin = _clone;
_clone = nullptr;
}
return _origin;
}
};
// Backward compatibility for CompileCommands // Breaks the abstraction and causes lots of extra complexity // - if some option is changed we need to copy directiveset since it no longer can be shared // - Need to free copy after use // - Requires a modified bit so we don't overwrite options that is set by directives
DirectiveSet* DirectiveSet::compilecommand_compatibility_init(const methodHandle& method) { // Early bail out - checking all options is expensive - we rely on them not being used // Only set a flag if it has not been modified and value changes. // Only copy set if a flag needs to be set if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::has_any_command_set()) {
DirectiveSetPtr set(this);
#ifdef COMPILER1 if (C1Breakpoint) { // If the directives didn't have 'BreakAtExecute', // the command 'C1Breakpoint' would become effective. if (!_modified[BreakAtExecuteIndex]) {
set.cloned()->BreakAtExecuteOption = true;
}
} #endif
// All CompileCommands are not equal so this gets a bit verbose // When CompileCommands have been refactored less clutter will remain. if (CompilerOracle::should_break_at(method)) { // If the directives didn't have 'BreakAtCompile' or 'BreakAtExecute', // the sub-command 'Break' of the 'CompileCommand' would become effective. if (!_modified[BreakAtCompileIndex]) {
set.cloned()->BreakAtCompileOption = true;
} if (!_modified[BreakAtExecuteIndex]) {
set.cloned()->BreakAtExecuteOption = true;
}
} if (!_modified[LogIndex]) { bool log = CompilerOracle::should_log(method); if (log != set->LogOption) {
set.cloned()->LogOption = log;
}
}
if (CompilerOracle::should_print(method)) { if (!_modified[PrintAssemblyIndex]) {
set.cloned()->PrintAssemblyOption = true;
}
} // Exclude as in should not compile == Enabled if (CompilerOracle::should_exclude(method)) { if (!_modified[ExcludeIndex]) {
set.cloned()->ExcludeOption = true;
}
}
// inline and dontinline (including exclude) are implemented in the directiveset accessors #define init_default_cc(name, type, dvalue, cc_flag) { type v; if (!_modified[name##Index] && CompileCommand::cc_flag != CompileCommand::Unknown && CompilerOracle::has_option_value(method, CompileCommand::cc_flag, v) && v != this->name##Option) { set.cloned()->name##Option = v; } }
compilerdirectives_common_flags(init_default_cc)
compilerdirectives_c2_flags(init_default_cc)
compilerdirectives_c1_flags(init_default_cc)
// Parse PrintIdealPhaseName and create an efficient lookup mask #ifndef PRODUCT #ifdef COMPILER2 if (!_modified[PrintIdealPhaseIndex]) { // Parse ccstr and create mask
ccstrlist option; if (CompilerOracle::has_option_value(method, CompileCommand::PrintIdealPhase, option)) {
uint64_t mask = 0;
PhaseNameValidator validator(option, mask); if (validator.is_valid()) {
assert(mask != 0, "Must be set");
set.cloned()->_ideal_phase_name_mask = mask;
}
}
} #endif #endif
// Canonicalize DisableIntrinsic to contain only ',' as a separator.
ccstrlist option_value; bool need_reset = true; // if Control/DisableIntrinsic redefined, only need to reset control_words once
if (!_modified[ControlIntrinsicIndex] &&
CompilerOracle::has_option_value(method, CompileCommand::ControlIntrinsic, option_value)) {
ControlIntrinsicIter iter(option_value);
if (need_reset) {
set.cloned()->_intrinsic_control_words.fill_in(TriBool());
need_reset = false;
}
while (*iter != NULL) {
vmIntrinsics::ID id = vmIntrinsics::find_id(*iter); if (id != vmIntrinsics::_none) {
set.cloned()->_intrinsic_control_words[vmIntrinsics::as_int(id)] = iter.is_enabled();
}
++iter;
}
}
if (!_modified[DisableIntrinsicIndex] &&
CompilerOracle::has_option_value(method, CompileCommand::DisableIntrinsic, option_value)) {
ControlIntrinsicIter iter(option_value, true/*disable_all*/);
if (need_reset) {
set.cloned()->_intrinsic_control_words.fill_in(TriBool());
need_reset = false;
}
while (*iter != NULL) {
vmIntrinsics::ID id = vmIntrinsics::find_id(*iter); if (id != vmIntrinsics::_none) {
set.cloned()->_intrinsic_control_words[vmIntrinsics::as_int(id)] = false;
}
if (_inlinematchers != NULL) { return matches_inline(mh, InlineMatcher::dont_inline);
} if (!CompilerDirectivesIgnoreCompileCommandsOption) { return CompilerOracle::should_not_inline(mh);
} returnfalse;
}
bool DirectiveSet::parse_and_add_inline(char* str, constchar*& error_msg) {
InlineMatcher* m = InlineMatcher::parse_inline_pattern(str, error_msg); if (m != NULL) { // add matcher last in chain - the order is significant
append_inline(m); returntrue;
} else {
assert(error_msg != NULL, "Error message must be set"); returnfalse;
}
}
void DirectiveSet::append_inline(InlineMatcher* m) { if (_inlinematchers == NULL) {
_inlinematchers = m; return;
}
InlineMatcher* tmp = _inlinematchers; while (tmp->next() != NULL) {
tmp = tmp->next();
}
tmp->set_next(m);
}
bool DirectiveSet::is_intrinsic_disabled(const methodHandle& method) {
vmIntrinsics::ID id = method->intrinsic_id();
assert(id > vmIntrinsics::_none && id < vmIntrinsics::ID_LIMIT, "invalid intrinsic_id!");
TriBool b = _intrinsic_control_words[vmIntrinsics::as_int(id)]; if (b.is_default()) { returnfalse; // if unset, every intrinsic is enabled.
} else { return !b;
}
}
DirectiveSet* DirectiveSet::clone(DirectiveSet const* src) {
DirectiveSet* set = new DirectiveSet(NULL); // Ordinary allocations of DirectiveSet would call init_control_intrinsic() // immediately to create a new copy for set->Control/DisableIntrinsicOption. // However, here it does not need to because the code below creates // a copy of src->Control/DisableIntrinsicOption that initializes // set->Control/DisableIntrinsicOption.
directive->inc_refcount(); if (_top == NULL) {
assert(_bottom == NULL, "There can only be one default directive");
_bottom = directive; // default directive, can never be removed.
}
if (_top->next() == NULL) { return; // Do nothing - don't allow an empty stack
}
CompilerDirectives* tmp = _top;
_top = _top->next();
_depth--;
DirectivesStack::release(tmp);
}
bool DirectivesStack::check_capacity(int request_size, outputStream* st) { if ((request_size + _depth) > CompilerDirectivesLimit) {
st->print_cr("Could not add %i more directives. Currently %i/%i directives.", request_size, _depth, CompilerDirectivesLimit); returnfalse;
} returntrue;
}
void DirectivesStack::clear() { // holding the lock during the whole operation ensuring consistent result
MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag); while (_top->next() != NULL) {
pop_inner();
}
}
DirectiveSet* DirectivesStack::getMatchingDirective(const methodHandle& method, AbstractCompiler *comp) {
assert(_depth > 0, "Must never be empty");
DirectiveSet* match = NULL;
{
MutexLocker locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
CompilerDirectives* dir = _top;
assert(dir != NULL, "Must be initialized");
while (dir != NULL) { if (dir->is_default_directive() || dir->match(method)) {
match = dir->get_for(comp);
assert(match != NULL, "Consistency"); if (match->EnableOption) { // The directiveSet for this compile is also enabled -> success
dir->inc_refcount(); break;
}
}
dir = dir->next();
}
}
guarantee(match != NULL, "There should always be a default directive that matches");
// Check for legacy compile commands update, without DirectivesStack_lock return match->compilecommand_compatibility_init(method);
}
¤ Dauer der Verarbeitung: 0.4 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.