8042997: Make intrinsic some or all check index/range methods
Summary: Objects.checkIndex() intrinsic
Reviewed-by: vlivanov, shade
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Fri Nov 13 18:14:41 2015 +0300
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Mon Nov 16 09:55:25 2015 +0100
@@ -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") \
--- a/hotspot/src/share/vm/opto/c2compiler.cpp Fri Nov 13 18:14:41 2015 +0300
+++ b/hotspot/src/share/vm/opto/c2compiler.cpp Mon Nov 16 09:55:25 2015 +0100
@@ -451,6 +451,7 @@
case vmIntrinsics::_updateByteBufferAdler32:
case vmIntrinsics::_profileBoolean:
case vmIntrinsics::_isCompileConstant:
+ case vmIntrinsics::_Objects_checkIndex:
break;
default:
return false;
--- a/hotspot/src/share/vm/opto/ifnode.cpp Fri Nov 13 18:14:41 2015 +0300
+++ b/hotspot/src/share/vm/opto/ifnode.cpp Mon Nov 16 09:55:25 2015 +0100
@@ -485,7 +485,7 @@
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 @@
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
--- a/hotspot/src/share/vm/opto/library_call.cpp Fri Nov 13 18:14:41 2015 +0300
+++ b/hotspot/src/share/vm/opto/library_call.cpp Mon Nov 16 09:55:25 2015 +0100
@@ -256,6 +256,7 @@
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 @@
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 @@
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) {
--- a/hotspot/src/share/vm/opto/loopPredicate.cpp Fri Nov 13 18:14:41 2015 +0300
+++ b/hotspot/src/share/vm/opto/loopPredicate.cpp Mon Nov 16 09:55:25 2015 +0100
@@ -569,7 +569,7 @@
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.
--- a/hotspot/src/share/vm/opto/loopnode.cpp Fri Nov 13 18:14:41 2015 +0300
+++ b/hotspot/src/share/vm/opto/loopnode.cpp Mon Nov 16 09:55:25 2015 +0100
@@ -329,6 +329,9 @@
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 @@
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)