mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-15 16:09:44 +00:00
8042997: Make intrinsic some or all check index/range methods
Objects.checkIndex() intrinsic Reviewed-by: vlivanov, shade
This commit is contained in:
parent
6de50f10f5
commit
baaa8f79ed
@ -109,6 +109,7 @@
|
||||
template(java_io_ByteArrayInputStream, "java/io/ByteArrayInputStream") \
|
||||
template(java_io_Serializable, "java/io/Serializable") \
|
||||
template(java_util_Arrays, "java/util/Arrays") \
|
||||
template(java_util_Objects, "java/util/Objects") \
|
||||
template(java_util_Properties, "java/util/Properties") \
|
||||
template(java_util_Vector, "java/util/Vector") \
|
||||
template(java_util_AbstractList, "java/util/AbstractList") \
|
||||
@ -883,6 +884,9 @@
|
||||
do_intrinsic(_equalsL, java_lang_StringLatin1,equals_name, equalsB_signature, F_S) \
|
||||
do_intrinsic(_equalsU, java_lang_StringUTF16, equals_name, equalsB_signature, F_S) \
|
||||
\
|
||||
do_intrinsic(_Objects_checkIndex, java_util_Objects, checkIndex_name, Objects_checkIndex_signature, F_S) \
|
||||
do_signature(Objects_checkIndex_signature, "(IILjava/util/function/BiFunction;)I") \
|
||||
\
|
||||
do_class(java_nio_Buffer, "java/nio/Buffer") \
|
||||
do_intrinsic(_checkIndex, java_nio_Buffer, checkIndex_name, int_int_signature, F_R) \
|
||||
do_name( checkIndex_name, "checkIndex") \
|
||||
|
||||
@ -451,6 +451,7 @@ bool C2Compiler::is_intrinsic_supported(methodHandle method, bool is_virtual) {
|
||||
case vmIntrinsics::_updateByteBufferAdler32:
|
||||
case vmIntrinsics::_profileBoolean:
|
||||
case vmIntrinsics::_isCompileConstant:
|
||||
case vmIntrinsics::_Objects_checkIndex:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
||||
@ -485,7 +485,7 @@ ProjNode* IfNode::range_check_trap_proj(int& flip_test, Node*& l, Node*& r) {
|
||||
return NULL;
|
||||
}
|
||||
if (l->is_top()) return NULL; // Top input means dead test
|
||||
if (r->Opcode() != Op_LoadRange) return NULL;
|
||||
if (r->Opcode() != Op_LoadRange && !is_RangeCheck()) return NULL;
|
||||
|
||||
// We have recognized one of these forms:
|
||||
// Flip 1: If (Bool[<] CmpU(l, LoadRange)) ...
|
||||
@ -525,9 +525,9 @@ int RangeCheckNode::is_range_check(Node* &range, Node* &index, jint &offset) {
|
||||
return 0;
|
||||
} else if (l->Opcode() == Op_AddI) {
|
||||
if ((off = l->in(1)->find_int_con(0)) != 0) {
|
||||
ind = l->in(2);
|
||||
ind = l->in(2)->uncast();
|
||||
} else if ((off = l->in(2)->find_int_con(0)) != 0) {
|
||||
ind = l->in(1);
|
||||
ind = l->in(1)->uncast();
|
||||
}
|
||||
} else if ((off = l->find_int_con(-1)) >= 0) {
|
||||
// constant offset with no variable index
|
||||
|
||||
@ -256,6 +256,7 @@ class LibraryCallKit : public GraphKit {
|
||||
bool inline_native_getLength();
|
||||
bool inline_array_copyOf(bool is_copyOfRange);
|
||||
bool inline_array_equals(StrIntrinsicNode::ArgEnc ae);
|
||||
bool inline_objects_checkIndex();
|
||||
void copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, bool is_array, bool card_mark);
|
||||
bool inline_native_clone(bool is_virtual);
|
||||
bool inline_native_Reflection_getCallerClass();
|
||||
@ -647,6 +648,7 @@ bool LibraryCallKit::try_to_inline(int predicate) {
|
||||
case vmIntrinsics::_copyOfRange: return inline_array_copyOf(true);
|
||||
case vmIntrinsics::_equalsB: return inline_array_equals(StrIntrinsicNode::LL);
|
||||
case vmIntrinsics::_equalsC: return inline_array_equals(StrIntrinsicNode::UU);
|
||||
case vmIntrinsics::_Objects_checkIndex: return inline_objects_checkIndex();
|
||||
case vmIntrinsics::_clone: return inline_native_clone(intrinsic()->is_virtual());
|
||||
|
||||
case vmIntrinsics::_isAssignableFrom: return inline_native_subtype_check();
|
||||
@ -1045,6 +1047,54 @@ bool LibraryCallKit::inline_hasNegatives() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LibraryCallKit::inline_objects_checkIndex() {
|
||||
Node* index = argument(0);
|
||||
Node* length = argument(1);
|
||||
if (too_many_traps(Deoptimization::Reason_intrinsic) || too_many_traps(Deoptimization::Reason_range_check)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Node* len_pos_cmp = _gvn.transform(new CmpINode(length, intcon(0)));
|
||||
Node* len_pos_bol = _gvn.transform(new BoolNode(len_pos_cmp, BoolTest::ge));
|
||||
|
||||
{
|
||||
BuildCutout unless(this, len_pos_bol, PROB_MAX);
|
||||
uncommon_trap(Deoptimization::Reason_intrinsic,
|
||||
Deoptimization::Action_make_not_entrant);
|
||||
}
|
||||
|
||||
if (stopped()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Node* rc_cmp = _gvn.transform(new CmpUNode(index, length));
|
||||
BoolTest::mask btest = BoolTest::lt;
|
||||
Node* rc_bool = _gvn.transform(new BoolNode(rc_cmp, btest));
|
||||
RangeCheckNode* rc = new RangeCheckNode(control(), rc_bool, PROB_MAX, COUNT_UNKNOWN);
|
||||
_gvn.set_type(rc, rc->Value(&_gvn));
|
||||
if (!rc_bool->is_Con()) {
|
||||
record_for_igvn(rc);
|
||||
}
|
||||
set_control(_gvn.transform(new IfTrueNode(rc)));
|
||||
{
|
||||
PreserveJVMState pjvms(this);
|
||||
set_control(_gvn.transform(new IfFalseNode(rc)));
|
||||
uncommon_trap(Deoptimization::Reason_range_check,
|
||||
Deoptimization::Action_make_not_entrant);
|
||||
}
|
||||
|
||||
if (stopped()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Node* result = new CastIINode(index, TypeInt::make(0, _gvn.type(length)->is_int()->_hi, Type::WidenMax));
|
||||
result->set_req(0, control());
|
||||
result = _gvn.transform(result);
|
||||
set_result(result);
|
||||
replace_in_map(index, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------inline_string_indexOf------------------------
|
||||
bool LibraryCallKit::inline_string_indexOf(StrIntrinsicNode::ArgEnc ae) {
|
||||
if (!Matcher::has_match_rule(Op_StrIndexOf) || !UseSSE42Intrinsics) {
|
||||
|
||||
@ -569,7 +569,7 @@ bool IdealLoopTree::is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invari
|
||||
return false;
|
||||
}
|
||||
Node* range = cmp->in(2);
|
||||
if (range->Opcode() != Op_LoadRange) {
|
||||
if (range->Opcode() != Op_LoadRange && !iff->is_RangeCheck()) {
|
||||
const TypeInt* tint = phase->_igvn.type(range)->isa_int();
|
||||
if (tint == NULL || tint->empty() || tint->_lo < 0) {
|
||||
// Allow predication on positive values that aren't LoadRanges.
|
||||
|
||||
@ -329,6 +329,9 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) {
|
||||
|
||||
Node* phi_incr = NULL;
|
||||
// Trip-counter increment must be commutative & associative.
|
||||
if (incr->Opcode() == Op_CastII) {
|
||||
incr = incr->in(1);
|
||||
}
|
||||
if (incr->is_Phi()) {
|
||||
if (incr->as_Phi()->region() != x || incr->req() != 3)
|
||||
return false; // Not simple trip counter expression
|
||||
@ -356,6 +359,9 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) {
|
||||
xphi = stride;
|
||||
stride = tmp;
|
||||
}
|
||||
if (xphi->Opcode() == Op_CastII) {
|
||||
xphi = xphi->in(1);
|
||||
}
|
||||
// Stride must be constant
|
||||
int stride_con = stride->get_int();
|
||||
if (stride_con == 0)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user