--- a/hotspot/src/share/vm/opto/graphKit.cpp Mon Jan 18 08:34:14 2016 +0100
+++ b/hotspot/src/share/vm/opto/graphKit.cpp Mon Jan 18 08:40:25 2016 +0100
@@ -1658,7 +1658,7 @@
//-------------------------array_element_address-------------------------
Node* GraphKit::array_element_address(Node* ary, Node* idx, BasicType elembt,
- const TypeInt* sizetype) {
+ const TypeInt* sizetype, Node* ctrl) {
uint shift = exact_log2(type2aelembytes(elembt));
uint header = arrayOopDesc::base_offset_in_bytes(elembt);
@@ -1671,7 +1671,7 @@
// must be correct type for alignment purposes
Node* base = basic_plus_adr(ary, header);
- idx = Compile::conv_I2X_index(&_gvn, idx, sizetype);
+ idx = Compile::conv_I2X_index(&_gvn, idx, sizetype, ctrl);
Node* scale = _gvn.transform( new LShiftXNode(idx, intcon(shift)) );
return basic_plus_adr(ary, base, scale);
}
@@ -3506,10 +3506,6 @@
Node* initial_slow_cmp = _gvn.transform( new CmpUNode( length, intcon( fast_size_limit ) ) );
Node* initial_slow_test = _gvn.transform( new BoolNode( initial_slow_cmp, BoolTest::gt ) );
- if (initial_slow_test->is_Bool()) {
- // Hide it behind a CMoveI, or else PhaseIdealLoop::split_up will get sick.
- initial_slow_test = initial_slow_test->as_Bool()->as_int_value(&_gvn);
- }
// --- Size Computation ---
// array_size = round_to_heap(array_header + (length << elem_shift));
@@ -3555,13 +3551,35 @@
Node* lengthx = ConvI2X(length);
Node* headerx = ConvI2X(header_size);
#ifdef _LP64
- { const TypeLong* tllen = _gvn.find_long_type(lengthx);
- if (tllen != NULL && tllen->_lo < 0) {
+ { const TypeInt* tilen = _gvn.find_int_type(length);
+ if (tilen != NULL && tilen->_lo < 0) {
// Add a manual constraint to a positive range. Cf. array_element_address.
- jlong size_max = arrayOopDesc::max_array_length(T_BYTE);
- if (size_max > tllen->_hi) size_max = tllen->_hi;
- const TypeLong* tlcon = TypeLong::make(CONST64(0), size_max, Type::WidenMin);
- lengthx = _gvn.transform( new ConvI2LNode(length, tlcon));
+ jint size_max = fast_size_limit;
+ if (size_max > tilen->_hi) size_max = tilen->_hi;
+ const TypeInt* tlcon = TypeInt::make(0, size_max, Type::WidenMin);
+
+ // Only do a narrow I2L conversion if the range check passed.
+ IfNode* iff = new IfNode(control(), initial_slow_test, PROB_MIN, COUNT_UNKNOWN);
+ _gvn.transform(iff);
+ RegionNode* region = new RegionNode(3);
+ _gvn.set_type(region, Type::CONTROL);
+ lengthx = new PhiNode(region, TypeLong::LONG);
+ _gvn.set_type(lengthx, TypeLong::LONG);
+
+ // Range check passed. Use ConvI2L node with narrow type.
+ Node* passed = IfFalse(iff);
+ region->init_req(1, passed);
+ // Make I2L conversion control dependent to prevent it from
+ // floating above the range check during loop optimizations.
+ lengthx->init_req(1, C->constrained_convI2L(&_gvn, length, tlcon, passed));
+
+ // Range check failed. Use ConvI2L with wide type because length may be invalid.
+ region->init_req(2, IfTrue(iff));
+ lengthx->init_req(2, ConvI2X(length));
+
+ set_control(region);
+ record_for_igvn(region);
+ record_for_igvn(lengthx);
}
}
#endif
@@ -3592,6 +3610,11 @@
Node *mem = reset_memory();
set_all_memory(mem); // Create new memory state
+ if (initial_slow_test->is_Bool()) {
+ // Hide it behind a CMoveI, or else PhaseIdealLoop::split_up will get sick.
+ initial_slow_test = initial_slow_test->as_Bool()->as_int_value(&_gvn);
+ }
+
// Create the AllocateArrayNode and its result projections
AllocateArrayNode* alloc
= new AllocateArrayNode(C, AllocateArrayNode::alloc_type(TypeInt::INT),