8151779: Some intrinsic flags could be replaced with one general flag
Add ControlIntrinsic switch Reviewed-by: neliasso, phh
This commit is contained in:
parent
6986ab256d
commit
4076ca82d2
@ -2296,10 +2296,13 @@ const bool Matcher::match_rule_supported(int opcode) {
|
||||
case Op_FmaVD:
|
||||
return (SuperwordUseVSX && UseFMA);
|
||||
case Op_Digit:
|
||||
return vmIntrinsics::is_intrinsic_available(vmIntrinsics::_isDigit);
|
||||
case Op_LowerCase:
|
||||
return vmIntrinsics::is_intrinsic_available(vmIntrinsics::_isLowerCase);
|
||||
case Op_UpperCase:
|
||||
return vmIntrinsics::is_intrinsic_available(vmIntrinsics::_isUpperCase);
|
||||
case Op_Whitespace:
|
||||
return UseCharacterCompareIntrinsics;
|
||||
return vmIntrinsics::is_intrinsic_available(vmIntrinsics::_isWhitespace);
|
||||
|
||||
case Op_CacheWB:
|
||||
case Op_CacheWBPreSync:
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "memory/metaspaceClosure.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "utilities/tribool.hpp"
|
||||
#include "utilities/xmlstream.hpp"
|
||||
|
||||
|
||||
@ -460,43 +461,7 @@ int vmIntrinsics::predicates_needed(vmIntrinsics::ID id) {
|
||||
}
|
||||
}
|
||||
|
||||
bool vmIntrinsics::is_intrinsic_available(vmIntrinsics::ID id) {
|
||||
return !vmIntrinsics::is_intrinsic_disabled(id) &&
|
||||
!vmIntrinsics::is_disabled_by_flags(id);
|
||||
}
|
||||
|
||||
bool vmIntrinsics::is_intrinsic_disabled(vmIntrinsics::ID id) {
|
||||
assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
|
||||
|
||||
// Canonicalize DisableIntrinsic to contain only ',' as a separator.
|
||||
// Note, DirectiveSet may not be created at this point yet since this code
|
||||
// is called from initial stub geenration code.
|
||||
char* local_list = (char*)DirectiveSet::canonicalize_disableintrinsic(DisableIntrinsic);
|
||||
char* save_ptr;
|
||||
bool found = false;
|
||||
|
||||
char* token = strtok_r(local_list, ",", &save_ptr);
|
||||
while (token != NULL) {
|
||||
if (strcmp(token, vmIntrinsics::name_at(id)) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
} else {
|
||||
token = strtok_r(NULL, ",", &save_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
FREE_C_HEAP_ARRAY(char, local_list);
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
bool vmIntrinsics::is_disabled_by_flags(const methodHandle& method) {
|
||||
vmIntrinsics::ID id = method->intrinsic_id();
|
||||
assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
|
||||
return is_disabled_by_flags(id);
|
||||
}
|
||||
|
||||
bool vmIntrinsics::is_disabled_by_flags(vmIntrinsics::ID id) {
|
||||
bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) {
|
||||
assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
|
||||
|
||||
// -XX:-InlineNatives disables nearly all intrinsics except the ones listed in
|
||||
@ -861,25 +826,86 @@ static const char* vm_intrinsic_name_bodies =
|
||||
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE);
|
||||
|
||||
static const char* vm_intrinsic_name_table[vmIntrinsics::ID_LIMIT];
|
||||
static TriBoolArray<vmIntrinsics::ID_LIMIT, int> vm_intrinsic_control_words;
|
||||
|
||||
static void init_vm_intrinsic_name_table() {
|
||||
const char** nt = &vm_intrinsic_name_table[0];
|
||||
char* string = (char*) &vm_intrinsic_name_bodies[0];
|
||||
for (int index = vmIntrinsics::FIRST_ID; index < vmIntrinsics::ID_LIMIT; index++) {
|
||||
nt[index] = string;
|
||||
string += strlen(string); // skip string body
|
||||
string += 1; // skip trailing null
|
||||
}
|
||||
assert(!strcmp(nt[vmIntrinsics::_hashCode], "_hashCode"), "lined up");
|
||||
nt[vmIntrinsics::_none] = "_none";
|
||||
}
|
||||
|
||||
const char* vmIntrinsics::name_at(vmIntrinsics::ID id) {
|
||||
const char** nt = &vm_intrinsic_name_table[0];
|
||||
if (nt[_none] == NULL) {
|
||||
char* string = (char*) &vm_intrinsic_name_bodies[0];
|
||||
for (int index = FIRST_ID; index < ID_LIMIT; index++) {
|
||||
nt[index] = string;
|
||||
string += strlen(string); // skip string body
|
||||
string += 1; // skip trailing null
|
||||
}
|
||||
assert(!strcmp(nt[_hashCode], "_hashCode"), "lined up");
|
||||
nt[_none] = "_none";
|
||||
init_vm_intrinsic_name_table();
|
||||
}
|
||||
|
||||
if ((uint)id < (uint)ID_LIMIT)
|
||||
return vm_intrinsic_name_table[(uint)id];
|
||||
else
|
||||
return "(unknown intrinsic)";
|
||||
}
|
||||
|
||||
vmIntrinsics::ID vmIntrinsics::find_id(const char* name) {
|
||||
const char** nt = &vm_intrinsic_name_table[0];
|
||||
if (nt[_none] == NULL) {
|
||||
init_vm_intrinsic_name_table();
|
||||
}
|
||||
|
||||
for (int index = FIRST_ID; index < ID_LIMIT; ++index) {
|
||||
if (0 == strcmp(name, nt[index])) {
|
||||
return ID_from(index);
|
||||
}
|
||||
}
|
||||
|
||||
return _none;
|
||||
}
|
||||
|
||||
bool vmIntrinsics::is_disabled_by_flags(const methodHandle& method) {
|
||||
vmIntrinsics::ID id = method->intrinsic_id();
|
||||
return is_disabled_by_flags(id);
|
||||
}
|
||||
|
||||
bool vmIntrinsics::is_disabled_by_flags(vmIntrinsics::ID id) {
|
||||
assert(id > _none && id < ID_LIMIT, "must be a VM intrinsic");
|
||||
|
||||
// not initialized yet, process Control/DisableIntrinsic
|
||||
if (vm_intrinsic_control_words[_none].is_default()) {
|
||||
for (ControlIntrinsicIter iter(ControlIntrinsic); *iter != NULL; ++iter) {
|
||||
vmIntrinsics::ID id = vmIntrinsics::find_id(*iter);
|
||||
|
||||
if (id != vmIntrinsics::_none) {
|
||||
vm_intrinsic_control_words[id] = iter.is_enabled() && !disabled_by_jvm_flags(id);
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
vm_intrinsic_control_words[id] = false;
|
||||
}
|
||||
}
|
||||
|
||||
vm_intrinsic_control_words[_none] = true;
|
||||
}
|
||||
|
||||
TriBool b = vm_intrinsic_control_words[id];
|
||||
if (b.is_default()) {
|
||||
// unknown yet, query and cache it
|
||||
b = vm_intrinsic_control_words[id] = !disabled_by_jvm_flags(id);
|
||||
}
|
||||
|
||||
return !b;
|
||||
}
|
||||
|
||||
// These are flag-matching functions:
|
||||
inline bool match_F_R(jshort flags) {
|
||||
const int req = 0;
|
||||
|
@ -1635,7 +1635,10 @@ private:
|
||||
vmSymbols::SID sig,
|
||||
jshort flags);
|
||||
|
||||
// check if the intrinsic is disabled by course-grained flags.
|
||||
static bool disabled_by_jvm_flags(vmIntrinsics::ID id);
|
||||
public:
|
||||
static ID find_id(const char* name);
|
||||
// Given a method's class, name, signature, and access flags, report its ID.
|
||||
static ID find_id(vmSymbols::SID holder,
|
||||
vmSymbols::SID name,
|
||||
@ -1685,12 +1688,25 @@ public:
|
||||
// 'method' requires predicated logic.
|
||||
static int predicates_needed(vmIntrinsics::ID id);
|
||||
|
||||
// Returns true if a compiler intrinsic is disabled by command-line flags
|
||||
// and false otherwise.
|
||||
static bool is_disabled_by_flags(const methodHandle& method);
|
||||
// There are 2 kinds of JVM options to control intrinsics.
|
||||
// 1. Disable/Control Intrinsic accepts a list of intrinsic IDs.
|
||||
// ControlIntrinsic is recommended. DisableIntrinic will be deprecated.
|
||||
// Currently, the DisableIntrinsic list prevails if an intrinsic appears on
|
||||
// both lists.
|
||||
//
|
||||
// 2. Explicit UseXXXIntrinsics options. eg. UseAESIntrinsics, UseCRC32Intrinsics etc.
|
||||
// Each option can control a group of intrinsics. The user can specify them but
|
||||
// their final values are subject to hardware inspection (VM_Version::initialize).
|
||||
// Stub generators are controlled by them.
|
||||
//
|
||||
// An intrinsic is enabled if and only if neither the fine-grained control(1) nor
|
||||
// the corresponding coarse-grained control(2) disables it.
|
||||
static bool is_disabled_by_flags(vmIntrinsics::ID id);
|
||||
static bool is_intrinsic_disabled(vmIntrinsics::ID id);
|
||||
static bool is_intrinsic_available(vmIntrinsics::ID id);
|
||||
|
||||
static bool is_disabled_by_flags(const methodHandle& method);
|
||||
static bool is_intrinsic_available(vmIntrinsics::ID id) {
|
||||
return !is_disabled_by_flags(id);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_CLASSFILE_VMSYMBOLS_HPP
|
||||
|
@ -33,9 +33,9 @@
|
||||
|
||||
CompilerDirectives::CompilerDirectives() : _next(NULL), _match(NULL), _ref_count(0) {
|
||||
_c1_store = new DirectiveSet(this);
|
||||
_c1_store->init_disableintrinsic();
|
||||
_c1_store->init_control_intrinsic();
|
||||
_c2_store = new DirectiveSet(this);
|
||||
_c2_store->init_disableintrinsic();
|
||||
_c2_store->init_control_intrinsic();
|
||||
};
|
||||
|
||||
CompilerDirectives::~CompilerDirectives() {
|
||||
@ -179,14 +179,14 @@ DirectiveSet* CompilerDirectives::get_for(AbstractCompiler *comp) {
|
||||
}
|
||||
}
|
||||
|
||||
// In the list of disabled intrinsics, the ID of the disabled intrinsics can separated:
|
||||
// - by ',' (if -XX:DisableIntrinsic is used once when invoking the VM) or
|
||||
// - by '\n' (if -XX:DisableIntrinsic is used multiple times when invoking the VM) or
|
||||
// - by ' ' (if DisableIntrinsic is used on a per-method level, e.g., with CompileCommand).
|
||||
// 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_disableintrinsic() method
|
||||
// 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_disableintrinsic(ccstrlist option_value) {
|
||||
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;
|
||||
@ -202,9 +202,57 @@ ccstrlist DirectiveSet::canonicalize_disableintrinsic(ccstrlist option_value) {
|
||||
return canonicalized_list;
|
||||
}
|
||||
|
||||
void DirectiveSet::init_disableintrinsic() {
|
||||
// Canonicalize DisableIntrinsic to contain only ',' as a separator.
|
||||
this->DisableIntrinsicOption = canonicalize_disableintrinsic(DisableIntrinsic);
|
||||
ControlIntrinsicIter::ControlIntrinsicIter(ccstrlist option_value, bool disable_all)
|
||||
: _disableIntrinsic(disable_all) {
|
||||
_list = (char*)DirectiveSet::canonicalize_control_intrinsic(option_value);
|
||||
_saved_ptr = _list;
|
||||
_enabled = false;
|
||||
|
||||
_token = strtok_r(_saved_ptr, ",", &_saved_ptr);
|
||||
next_token();
|
||||
}
|
||||
|
||||
ControlIntrinsicIter::~ControlIntrinsicIter() {
|
||||
FREE_C_HEAP_ARRAY(char, _list);
|
||||
}
|
||||
|
||||
// pre-increment
|
||||
ControlIntrinsicIter& ControlIntrinsicIter::operator++() {
|
||||
_token = strtok_r(NULL, ",", &_saved_ptr);
|
||||
next_token();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ControlIntrinsicIter::next_token() {
|
||||
if (_token && !_disableIntrinsic) {
|
||||
char ch = _token[0];
|
||||
|
||||
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[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[id] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DirectiveSet::DirectiveSet(CompilerDirectives* d) :_inlinematchers(NULL), _directive(d) {
|
||||
@ -213,6 +261,7 @@ DirectiveSet::DirectiveSet(CompilerDirectives* d) :_inlinematchers(NULL), _direc
|
||||
compilerdirectives_c2_flags(init_defaults_definition)
|
||||
compilerdirectives_c1_flags(init_defaults_definition)
|
||||
memset(_modified, 0, sizeof(_modified));
|
||||
_intrinsic_control_words.fill_in(/*default value*/TriBool());
|
||||
}
|
||||
|
||||
DirectiveSet::~DirectiveSet() {
|
||||
@ -223,12 +272,6 @@ DirectiveSet::~DirectiveSet() {
|
||||
delete tmp;
|
||||
tmp = next;
|
||||
}
|
||||
|
||||
// When constructed, DirectiveSet canonicalizes the DisableIntrinsic flag
|
||||
// into a new string. Therefore, that string is deallocated when
|
||||
// the DirectiveSet is destroyed.
|
||||
assert(this->DisableIntrinsicOption != NULL, "");
|
||||
FREE_C_HEAP_ARRAY(char, (void *)this->DisableIntrinsicOption);
|
||||
}
|
||||
|
||||
// Backward compatibility for CompileCommands
|
||||
@ -280,10 +323,6 @@ DirectiveSet* DirectiveSet::compilecommand_compatibility_init(const methodHandle
|
||||
}
|
||||
}
|
||||
|
||||
// Read old value of DisableIntrinsicOption, in case we need to free it
|
||||
// and overwrite it with a new value.
|
||||
ccstrlist old_disable_intrinsic_value = set->DisableIntrinsicOption;
|
||||
|
||||
// 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] && CompilerOracle::has_option_value(method, #cc_flag, v) && v != this->name##Option) { set->name##Option = v; changed = true;} }
|
||||
compilerdirectives_common_flags(init_default_cc)
|
||||
@ -292,11 +331,45 @@ DirectiveSet* DirectiveSet::compilecommand_compatibility_init(const methodHandle
|
||||
|
||||
// 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, "ControlIntrinsic", option_value)) {
|
||||
ControlIntrinsicIter iter(option_value);
|
||||
|
||||
if (need_reset) {
|
||||
set->_intrinsic_control_words.fill_in(TriBool());
|
||||
need_reset = false;
|
||||
}
|
||||
|
||||
while (*iter != NULL) {
|
||||
vmIntrinsics::ID id = vmIntrinsics::find_id(*iter);
|
||||
if (id != vmIntrinsics::_none) {
|
||||
set->_intrinsic_control_words[id] = iter.is_enabled();
|
||||
}
|
||||
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!_modified[DisableIntrinsicIndex] &&
|
||||
CompilerOracle::has_option_value(method, "DisableIntrinsic", option_value)) {
|
||||
set->DisableIntrinsicOption = canonicalize_disableintrinsic(option_value);
|
||||
assert(old_disable_intrinsic_value != NULL, "");
|
||||
FREE_C_HEAP_ARRAY(char, (void *)old_disable_intrinsic_value);
|
||||
ControlIntrinsicIter iter(option_value, true/*disable_all*/);
|
||||
|
||||
if (need_reset) {
|
||||
set->_intrinsic_control_words.fill_in(TriBool());
|
||||
need_reset = false;
|
||||
}
|
||||
|
||||
while (*iter != NULL) {
|
||||
vmIntrinsics::ID id = vmIntrinsics::find_id(*iter);
|
||||
if (id != vmIntrinsics::_none) {
|
||||
set->_intrinsic_control_words[id] = false;
|
||||
}
|
||||
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -397,38 +470,23 @@ void DirectiveSet::print_inline(outputStream* st) {
|
||||
|
||||
bool DirectiveSet::is_intrinsic_disabled(const methodHandle& method) {
|
||||
vmIntrinsics::ID id = method->intrinsic_id();
|
||||
assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
|
||||
assert(id > vmIntrinsics::_none && id < vmIntrinsics::ID_LIMIT, "invalid intrinsic_id!");
|
||||
|
||||
ResourceMark rm;
|
||||
|
||||
// Create a copy of the string that contains the list of disabled
|
||||
// intrinsics. The copy is created because the string
|
||||
// will be modified by strtok(). Then, the list is tokenized with
|
||||
// ',' as a separator.
|
||||
size_t length = strlen(DisableIntrinsicOption);
|
||||
char* local_list = NEW_RESOURCE_ARRAY(char, length + 1);
|
||||
strncpy(local_list, DisableIntrinsicOption, length + 1);
|
||||
char* save_ptr;
|
||||
|
||||
char* token = strtok_r(local_list, ",", &save_ptr);
|
||||
while (token != NULL) {
|
||||
if (strcmp(token, vmIntrinsics::name_at(id)) == 0) {
|
||||
return true;
|
||||
} else {
|
||||
token = strtok_r(NULL, ",", &save_ptr);
|
||||
}
|
||||
TriBool b = _intrinsic_control_words[id];
|
||||
if (b.is_default()) {
|
||||
return false; // if unset, every intrinsic is enabled.
|
||||
} else {
|
||||
return !b;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DirectiveSet* DirectiveSet::clone(DirectiveSet const* src) {
|
||||
DirectiveSet* set = new DirectiveSet(NULL);
|
||||
// Ordinary allocations of DirectiveSet would call init_disableintrinsic()
|
||||
// immediately to create a new copy for set->DisableIntrinsicOption.
|
||||
// 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->DisableIntrinsicOption that initializes
|
||||
// set->DisableIntrinsicOption.
|
||||
// a copy of src->Control/DisableIntrinsicOption that initializes
|
||||
// set->Control/DisableIntrinsicOption.
|
||||
|
||||
memcpy(set->_modified, src->_modified, sizeof(src->_modified));
|
||||
|
||||
@ -443,13 +501,7 @@ DirectiveSet* DirectiveSet::clone(DirectiveSet const* src) {
|
||||
compilerdirectives_c2_flags(copy_members_definition)
|
||||
compilerdirectives_c1_flags(copy_members_definition)
|
||||
|
||||
// Create a local copy of the DisableIntrinsicOption.
|
||||
assert(src->DisableIntrinsicOption != NULL, "");
|
||||
size_t len = strlen(src->DisableIntrinsicOption) + 1;
|
||||
char* s = NEW_C_HEAP_ARRAY(char, len, mtCompiler);
|
||||
strncpy(s, src->DisableIntrinsicOption, len);
|
||||
assert(s[len-1] == '\0', "");
|
||||
set->DisableIntrinsicOption = s;
|
||||
set->_intrinsic_control_words = src->_intrinsic_control_words;
|
||||
return set;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "compiler/methodMatcher.hpp"
|
||||
#include "compiler/compilerOracle.hpp"
|
||||
#include "utilities/exceptions.hpp"
|
||||
#include "utilities/tribool.hpp"
|
||||
|
||||
// Directives flag name, type, default value, compile command name
|
||||
#define compilerdirectives_common_flags(cflags) \
|
||||
@ -46,7 +47,8 @@
|
||||
cflags(DumpReplay, bool, false, DumpReplay) \
|
||||
cflags(DumpInline, bool, false, DumpInline) \
|
||||
cflags(CompilerDirectivesIgnoreCompileCommands, bool, CompilerDirectivesIgnoreCompileCommands, X) \
|
||||
cflags(DisableIntrinsic, ccstrlist, DisableIntrinsic, DisableIntrinsic)
|
||||
cflags(DisableIntrinsic, ccstrlist, DisableIntrinsic, DisableIntrinsic) \
|
||||
cflags(ControlIntrinsic, ccstrlist, ControlIntrinsic, ControlIntrinsic)
|
||||
|
||||
#ifdef COMPILER1
|
||||
#define compilerdirectives_c1_flags(cflags)
|
||||
@ -99,11 +101,12 @@ class DirectiveSet : public CHeapObj<mtCompiler> {
|
||||
private:
|
||||
InlineMatcher* _inlinematchers;
|
||||
CompilerDirectives* _directive;
|
||||
TriBoolArray<vmIntrinsics::ID_LIMIT, int> _intrinsic_control_words;
|
||||
|
||||
public:
|
||||
DirectiveSet(CompilerDirectives* directive);
|
||||
~DirectiveSet();
|
||||
void init_disableintrinsic();
|
||||
void init_control_intrinsic();
|
||||
CompilerDirectives* directive();
|
||||
bool parse_and_add_inline(char* str, const char*& error_msg);
|
||||
void append_inline(InlineMatcher* m);
|
||||
@ -115,7 +118,7 @@ public:
|
||||
bool matches_inline(const methodHandle& method, int inline_action);
|
||||
static DirectiveSet* clone(DirectiveSet const* src);
|
||||
bool is_intrinsic_disabled(const methodHandle& method);
|
||||
static ccstrlist canonicalize_disableintrinsic(ccstrlist option_value);
|
||||
static ccstrlist canonicalize_control_intrinsic(ccstrlist option_value);
|
||||
void finalize(outputStream* st);
|
||||
|
||||
typedef enum {
|
||||
@ -126,8 +129,10 @@ public:
|
||||
number_of_flags
|
||||
} flags;
|
||||
|
||||
private:
|
||||
bool _modified[number_of_flags]; // Records what options where set by a directive
|
||||
|
||||
public:
|
||||
#define flag_store_definition(name, type, dvalue, cc_flag) type name##Option;
|
||||
compilerdirectives_common_flags(flag_store_definition)
|
||||
compilerdirectives_c2_flags(flag_store_definition)
|
||||
@ -157,6 +162,28 @@ void print(outputStream* st) {
|
||||
}
|
||||
};
|
||||
|
||||
// Iterator of ControlIntrinsic
|
||||
// if disable_all is true, it accepts DisableIntrinsic(deprecated) and all intrinsics
|
||||
// appear in the list are to disable
|
||||
class ControlIntrinsicIter {
|
||||
private:
|
||||
bool _enabled;
|
||||
char* _token;
|
||||
char* _saved_ptr;
|
||||
char* _list;
|
||||
const bool _disableIntrinsic;
|
||||
void next_token();
|
||||
|
||||
public:
|
||||
ControlIntrinsicIter(ccstrlist option, bool disable_all = false);
|
||||
~ControlIntrinsicIter();
|
||||
|
||||
bool is_enabled() const { return _enabled; }
|
||||
const char* operator*() const { return _token; }
|
||||
|
||||
ControlIntrinsicIter& operator++();
|
||||
};
|
||||
|
||||
class CompilerDirectives : public CHeapObj<mtCompiler> {
|
||||
private:
|
||||
CompilerDirectives* _next;
|
||||
|
@ -490,12 +490,12 @@ static void scan_flag_and_value(const char* type, const char* line, int& total_b
|
||||
ResourceMark rm;
|
||||
char* value = NEW_RESOURCE_ARRAY(char, strlen(line) + 1);
|
||||
char* next_value = value;
|
||||
if (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9]%n", next_value, &bytes_read) == 1) {
|
||||
if (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9+\\-]%n", next_value, &bytes_read) == 1) {
|
||||
total_bytes_read += bytes_read;
|
||||
line += bytes_read;
|
||||
next_value += bytes_read;
|
||||
char* end_value = next_value-1;
|
||||
while (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9]%n", next_value, &bytes_read) == 1) {
|
||||
while (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9+\\-]%n", next_value, &bytes_read) == 1) {
|
||||
total_bytes_read += bytes_read;
|
||||
line += bytes_read;
|
||||
*end_value = ' '; // override '\0'
|
||||
|
@ -6522,21 +6522,21 @@ bool LibraryCallKit::inline_digestBase_implCompressMB(int predicate) {
|
||||
|
||||
switch (predicate) {
|
||||
case 0:
|
||||
if (UseSHA1Intrinsics) {
|
||||
if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_sha_implCompress)) {
|
||||
klass_SHA_name = "sun/security/provider/SHA";
|
||||
stub_name = "sha1_implCompressMB";
|
||||
stub_addr = StubRoutines::sha1_implCompressMB();
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (UseSHA256Intrinsics) {
|
||||
if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_sha2_implCompress)) {
|
||||
klass_SHA_name = "sun/security/provider/SHA2";
|
||||
stub_name = "sha256_implCompressMB";
|
||||
stub_addr = StubRoutines::sha256_implCompressMB();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (UseSHA512Intrinsics) {
|
||||
if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_sha5_implCompress)) {
|
||||
klass_SHA_name = "sun/security/provider/SHA5";
|
||||
stub_name = "sha512_implCompressMB";
|
||||
stub_addr = StubRoutines::sha512_implCompressMB();
|
||||
|
@ -350,6 +350,10 @@ const size_t minimumSymbolTableSize = 1024;
|
||||
diagnostic(ccstrlist, DisableIntrinsic, "", \
|
||||
"do not expand intrinsics whose (internal) names appear here") \
|
||||
\
|
||||
diagnostic(ccstrlist, ControlIntrinsic, "", \
|
||||
"Control intrinsics using a list of +/- (internal) names, " \
|
||||
"separated by commas") \
|
||||
\
|
||||
develop(bool, TraceCallFixup, false, \
|
||||
"Trace all call fixups") \
|
||||
\
|
||||
|
139
src/hotspot/share/utilities/tribool.hpp
Normal file
139
src/hotspot/share/utilities/tribool.hpp
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright Amazon.com Inc. 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_UTILITIES_TRIBOOL_HPP
|
||||
#define SHARE_UTILITIES_TRIBOOL_HPP
|
||||
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
// 2-bit boolean type: H|L
|
||||
// the high-bit H is set if it's not default value.
|
||||
// the low-bit L represents true and false.
|
||||
class TriBool{
|
||||
template <size_t SZ, typename T>
|
||||
friend class TriBoolArray;
|
||||
|
||||
private:
|
||||
unsigned int _value : 2;
|
||||
explicit TriBool(u1 raw) : _value(raw & 3) {}
|
||||
|
||||
public:
|
||||
TriBool() : _value(0) {}
|
||||
TriBool(bool value) : _value(((u1)value) | 2) {}
|
||||
TriBool(const TriBool& o): _value(o._value) {}
|
||||
|
||||
TriBool& operator=(bool value) {
|
||||
_value = ((u1)value) | 2;
|
||||
return *this;
|
||||
}
|
||||
|
||||
TriBool& operator=(const TriBool& o) {
|
||||
_value = o._value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool is_default() const {
|
||||
return !static_cast<bool>(_value >> 1);
|
||||
}
|
||||
|
||||
/*explicit*/ operator bool() const {
|
||||
return (_value & 1);
|
||||
}
|
||||
};
|
||||
|
||||
// compacted array of TriBool
|
||||
template <size_t SZ, typename T>
|
||||
class TriBoolArray {
|
||||
private:
|
||||
class TriBoolAssigner : public TriBool {
|
||||
public:
|
||||
TriBoolAssigner(T& slot, size_t offset) : TriBool(static_cast<u1>(slot >> offset)),
|
||||
_slot(slot), _offset(offset) {}
|
||||
|
||||
TriBoolAssigner& operator=(bool newval) {
|
||||
_slot ^= ((u1)_value) << _offset; // reset the tribool
|
||||
_value = (u1)newval| 2;
|
||||
_slot |= ((u1)_value) << _offset;
|
||||
return *this;
|
||||
};
|
||||
|
||||
TriBoolAssigner& operator=(TriBool tb) {
|
||||
_slot ^= ((u1)_value) << _offset; // reset the tribool
|
||||
_value = (u1)tb._value;
|
||||
_slot |= ((u1)_value) << _offset;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
T& _slot;
|
||||
size_t _offset;
|
||||
};
|
||||
|
||||
public:
|
||||
TriBoolArray() {}
|
||||
|
||||
TriBoolArray(const TriBool& init) {
|
||||
fill_in(init);
|
||||
}
|
||||
|
||||
TriBool operator[](size_t x) const {
|
||||
size_t index = x / (_slot_size);
|
||||
size_t offset = x % (_slot_size);
|
||||
T raw = (_array[index] >> (2 * offset)) & 3;
|
||||
return TriBool(static_cast<u1>(raw));
|
||||
}
|
||||
|
||||
TriBoolAssigner operator[](size_t x) {
|
||||
size_t index = x / (_slot_size);
|
||||
size_t offset = x % (_slot_size);
|
||||
return TriBoolAssigner(_array[index], 2 * offset);
|
||||
}
|
||||
|
||||
void fill_in(const TriBool& val) {
|
||||
if (val.is_default()) {
|
||||
memset(_array, 0, _size * sizeof(T));
|
||||
}
|
||||
else {
|
||||
for (size_t i = 0; i < SZ; ++i) {
|
||||
(*this)[i] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fill_in(const TriBool* beg, const TriBool* end) {
|
||||
size_t i = 0;
|
||||
|
||||
while (i < SZ && beg != end) {
|
||||
(*this)[i++] = *beg++;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const static size_t _bits_in_T = sizeof(T) * 8; // bits in a byte
|
||||
const static size_t _slot_size = _bits_in_T >> 1; // one TriBool occupies 2bits
|
||||
const static size_t _size = (2 * SZ + _bits_in_T - 1) / (_bits_in_T);
|
||||
T _array[_size];
|
||||
};
|
||||
|
||||
#endif // SHARE_UTILITIES_TRIBOOL_HPP
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2020, 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
|
||||
@ -93,6 +93,20 @@ TEST_VM_F(DirectivesParserTest, simple_match) {
|
||||
|
||||
}
|
||||
|
||||
TEST_VM_F(DirectivesParserTest, control_intrinsic) {
|
||||
test_positive(
|
||||
"[" "\n"
|
||||
" {" "\n"
|
||||
" match: \"foo/bar.*\"," "\n"
|
||||
" c2: {" "\n"
|
||||
" DisableIntrinsic: \"_compareToL\"," "\n"
|
||||
" ControlIntrinsic: \"+_mulAdd,+_getInt,-_arraycopy,+_compareToL\"" "\n"
|
||||
" }" "\n"
|
||||
" }" "\n"
|
||||
"]" "\n");
|
||||
|
||||
}
|
||||
|
||||
TEST_VM_F(DirectivesParserTest, nesting_arrays) {
|
||||
test_negative(
|
||||
"[" "\n"
|
||||
|
190
test/hotspot/gtest/utilities/test_tribool.cpp
Normal file
190
test/hotspot/gtest/utilities/test_tribool.cpp
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright Amazon.com Inc. 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.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "unittest.hpp"
|
||||
#include "utilities/tribool.hpp"
|
||||
|
||||
TEST(tribool, TriBool) {
|
||||
TriBool t1;
|
||||
ASSERT_EQ(t1.is_default(), true);
|
||||
ASSERT_EQ((bool)t1, false);
|
||||
|
||||
TriBool t2(false);
|
||||
ASSERT_TRUE(t2.is_default() == false && (bool)t2 == false);
|
||||
|
||||
TriBool t3(true);
|
||||
ASSERT_TRUE(t3.is_default() == false && (bool)t3 == true);
|
||||
|
||||
TriBool t4 = false;
|
||||
ASSERT_TRUE(t4.is_default() == false && (bool)t4 == false);
|
||||
|
||||
if (t2 || !t3 || t4) {
|
||||
ASSERT_TRUE(false); //boom
|
||||
}
|
||||
|
||||
TriBool flags[4];
|
||||
flags[0] = TriBool();
|
||||
flags[1] = false;
|
||||
flags[2] = true;
|
||||
|
||||
ASSERT_EQ(flags[0].is_default(), true) << "should be default";
|
||||
ASSERT_EQ(!flags[1].is_default() && !flags[1], true) << "should be not default and not set";
|
||||
ASSERT_EQ(!flags[2].is_default() && flags[2], true) << "should be not default and set";
|
||||
ASSERT_EQ(flags[3].is_default() == true, true) << "should be default";
|
||||
}
|
||||
|
||||
template <size_t SZ, typename T>
|
||||
struct Tester {
|
||||
static void doit() {
|
||||
// test fill_in(value)
|
||||
control_words.fill_in(TriBool());
|
||||
for (size_t i = 0; i < SZ; ++i) {
|
||||
EXPECT_TRUE(control_words[i].is_default());
|
||||
}
|
||||
|
||||
TriBool F = false;
|
||||
control_words.fill_in(F);
|
||||
for (size_t i = 0; i < SZ; ++i) {
|
||||
EXPECT_TRUE(!control_words[i].is_default() && control_words[i] == false);
|
||||
}
|
||||
|
||||
// test fill_in(beg, end)
|
||||
TriBool Vec[4];
|
||||
Vec[0] = TriBool();
|
||||
Vec[1] = TriBool();
|
||||
Vec[2] = true;
|
||||
Vec[3] = false;
|
||||
|
||||
control_words.fill_in(&Vec[0], Vec + 4);
|
||||
|
||||
if (0 < SZ) {
|
||||
EXPECT_TRUE(control_words[0].is_default());
|
||||
}
|
||||
|
||||
if (1 < SZ) {
|
||||
EXPECT_TRUE(control_words[1].is_default());
|
||||
}
|
||||
|
||||
if (2 < SZ) {
|
||||
EXPECT_TRUE(!control_words[2].is_default() && control_words[2] == true);
|
||||
}
|
||||
|
||||
if (3 < SZ) {
|
||||
EXPECT_TRUE(!control_words[3].is_default() && control_words[3] == false);
|
||||
}
|
||||
|
||||
// test assignment
|
||||
for (size_t i = 0; i < SZ; ++i) {
|
||||
control_words[i] = true;
|
||||
EXPECT_TRUE(!control_words[i].is_default() && control_words[i] == true);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < SZ; ++i) {
|
||||
control_words[i] = false;
|
||||
EXPECT_TRUE(!control_words[i].is_default() && control_words[i] == false);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < SZ; ++i) {
|
||||
if ((i%2) == 0) {
|
||||
control_words[i] = TriBool(true);
|
||||
}
|
||||
else {
|
||||
control_words[i] = TriBool(false);
|
||||
}
|
||||
}
|
||||
|
||||
// test copy constructor(default)
|
||||
copy = control_words;
|
||||
for (size_t i = 0; i < SZ; ++i) {
|
||||
if ((i%2) == 0) {
|
||||
EXPECT_TRUE(!copy[i].is_default() && copy[i] == true)
|
||||
<< "even value must be true.";
|
||||
}
|
||||
else {
|
||||
EXPECT_TRUE(!copy[i].is_default() && copy[i] == false)
|
||||
<< "odd value must be false.";
|
||||
}
|
||||
}
|
||||
|
||||
// test const operator[](fastpath)
|
||||
const TriBoolArray<SZ, T>& cref = control_words;
|
||||
for (size_t i = 0; i < SZ; ++i) {
|
||||
if ((i%2) == 0) {
|
||||
EXPECT_TRUE(!cref[i].is_default() && cref[i] == true)
|
||||
<< "even value must be true.";
|
||||
}
|
||||
else {
|
||||
EXPECT_TRUE(!cref[i].is_default() && cref[i] == false)
|
||||
<< "odd value must be false.";
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_GE(sizeof(control_words) * 8, (2 * SZ)) << "allocated too less";
|
||||
EXPECT_LE(sizeof(control_words), (((2 * SZ) / (sizeof(T) * 8) + 1) * sizeof(T)))
|
||||
<< "allocated too much";
|
||||
}
|
||||
|
||||
// because doit probably can't allocate jumbo arrays on stack, use static members
|
||||
static TriBoolArray<SZ, T> control_words;
|
||||
static TriBoolArray<SZ, T> copy;
|
||||
};
|
||||
|
||||
template<size_t SZ, typename T>
|
||||
TriBoolArray<SZ, T> Tester<SZ, T>::control_words;
|
||||
|
||||
template<size_t SZ, typename T>
|
||||
TriBoolArray<SZ, T> Tester<SZ, T>::copy;
|
||||
|
||||
TEST(tribool, TriBoolArray) {
|
||||
Tester<1, int>::doit();
|
||||
Tester<2, int>::doit();
|
||||
Tester<3, int>::doit();
|
||||
Tester<7, int>::doit();
|
||||
Tester<8, int>::doit();
|
||||
Tester<14, int>::doit();
|
||||
Tester<16, int>::doit();
|
||||
Tester<27, int>::doit();
|
||||
Tester<32, int>::doit();
|
||||
Tester<34, int>::doit();
|
||||
Tester<81, int>::doit();
|
||||
Tester<128, int>::doit();
|
||||
Tester<328, int>::doit(); // the no of intrinsics in jdk15
|
||||
|
||||
Tester<1024, int>::doit();
|
||||
Tester<1025, int>::doit();
|
||||
|
||||
Tester<4 <<10/*4k*/ , int>::doit();
|
||||
Tester<16<<10/*16k*/, int>::doit();
|
||||
Tester<32<<10/*32k*/, int>::doit();
|
||||
Tester<1 <<20/*1M*/ , int>::doit();
|
||||
Tester<4 <<20/*4M*/ , int>::doit();
|
||||
}
|
||||
|
||||
TriBool global_single;
|
||||
TriBoolArray<2, unsigned int> global_tuple;
|
||||
TEST(tribool, StaticInitializer) {
|
||||
EXPECT_TRUE(global_single.is_default());
|
||||
EXPECT_TRUE(global_tuple[0].is_default());
|
||||
EXPECT_TRUE(global_tuple[1].is_default());
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2020, 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
|
||||
@ -28,6 +28,9 @@
|
||||
* @run main/othervm -XX:-TieredCompilation -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:DisableIntrinsic=_getClass
|
||||
* -XX:CompileCommand=quiet -XX:CompileCommand=compileonly,compiler.escapeAnalysis.TestGetClass::test
|
||||
* -XX:+PrintCompilation compiler.escapeAnalysis.TestGetClass
|
||||
* @run main/othervm -XX:-TieredCompilation -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:ControlIntrinsic=-_getClass
|
||||
* -XX:CompileCommand=quiet -XX:CompileCommand=compileonly,compiler.escapeAnalysis.TestGetClass::test
|
||||
* -XX:+PrintCompilation compiler.escapeAnalysis.TestGetClass
|
||||
*/
|
||||
|
||||
package compiler.escapeAnalysis;
|
||||
|
@ -39,6 +39,25 @@
|
||||
* -XX:+WhiteBoxAPI
|
||||
* -XX:-UseCRC32Intrinsics
|
||||
* compiler.intrinsics.IntrinsicAvailableTest
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* -XX:ControlIntrinsic=+_updateCRC32
|
||||
* -XX:-UseCRC32Intrinsics
|
||||
* compiler.intrinsics.IntrinsicAvailableTest
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* -XX:ControlIntrinsic=-_updateCRC32
|
||||
* -XX:+UseCRC32Intrinsics
|
||||
* compiler.intrinsics.IntrinsicAvailableTest
|
||||
*
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* -XX:ControlIntrinsic=+_updateCRC32
|
||||
* -XX:+UseCRC32Intrinsics
|
||||
* compiler.intrinsics.IntrinsicAvailableTest
|
||||
*/
|
||||
|
||||
|
||||
@ -93,7 +112,17 @@ public class IntrinsicAvailableTest extends CompilerWhiteBoxTest {
|
||||
}
|
||||
|
||||
protected void checkIntrinsicForCompilationLevel(Executable method, int compLevel) throws Exception {
|
||||
boolean intrinsicEnabled = Boolean.valueOf(getVMOption("UseCRC32Intrinsics"));
|
||||
boolean intrinsicEnabled = true;
|
||||
String controlIntrinsic = getVMOption("ControlIntrinsic", "");
|
||||
|
||||
if (controlIntrinsic.contains("+_updateCRC32")) {
|
||||
intrinsicEnabled = true;
|
||||
} else if (controlIntrinsic.contains("-_updateCRC32")) {
|
||||
intrinsicEnabled = false;
|
||||
}
|
||||
|
||||
intrinsicEnabled &= Boolean.valueOf(getVMOption("UseCRC32Intrinsics"));
|
||||
|
||||
boolean intrinsicAvailable = WHITE_BOX.isIntrinsicAvailable(method,
|
||||
compLevel);
|
||||
|
||||
|
@ -39,7 +39,26 @@
|
||||
* -XX:CompileCommand=option,jdk.internal.misc.Unsafe::putChar,ccstrlist,DisableIntrinsic,_getCharVolatile,_getInt
|
||||
* -XX:CompileCommand=option,jdk.internal.misc.Unsafe::putCharVolatile,ccstrlist,DisableIntrinsic,_getIntVolatile
|
||||
* compiler.intrinsics.IntrinsicDisabledTest
|
||||
*/
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* -XX:ControlIntrinsic=-_putCharVolatile,-_putInt
|
||||
* -XX:ControlIntrinsic=-_putIntVolatile
|
||||
* -XX:CompileCommand=option,jdk.internal.misc.Unsafe::putChar,ccstrlist,ControlIntrinsic,-_getCharVolatile,-_getInt
|
||||
* -XX:CompileCommand=option,jdk.internal.misc.Unsafe::putCharVolatile,ccstrlist,ControlIntrinsic,-_getIntVolatile
|
||||
* compiler.intrinsics.IntrinsicDisabledTest
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* -XX:ControlIntrinsic=+putIntVolatile,+_putCharVolatile,+_putInt
|
||||
* -XX:DisableIntrinsic=_putCharVolatile,_putInt
|
||||
* -XX:DisableIntrinsic=_putIntVolatile
|
||||
* -XX:CompileCommand=option,jdk.internal.misc.Unsafe::putChar,ccstrlist,ControlIntrinsic,+_getCharVolatile,+_getInt
|
||||
* -XX:CompileCommand=option,jdk.internal.misc.Unsafe::putCharVolatile,ccstrlist,ControlIntrinsic,+_getIntVolatile
|
||||
* -XX:CompileCommand=option,jdk.internal.misc.Unsafe::putChar,ccstrlist,DisableIntrinsic,_getCharVolatile,_getInt
|
||||
* -XX:CompileCommand=option,jdk.internal.misc.Unsafe::putCharVolatile,ccstrlist,DisableIntrinsic,_getIntVolatile
|
||||
* compiler.intrinsics.IntrinsicDisabledTest
|
||||
*/
|
||||
|
||||
package compiler.intrinsics;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user