Skip to content

Commit

Permalink
Merge
Browse files Browse the repository at this point in the history
  • Loading branch information
theaoqi committed Jan 26, 2024
2 parents 88a9d9b + d4b472f commit ead1d6f
Show file tree
Hide file tree
Showing 32 changed files with 1,585 additions and 288 deletions.
21 changes: 12 additions & 9 deletions hotspot/src/share/vm/c1/c1_RangeCheckElimination.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,8 +379,11 @@ void RangeCheckEliminator::add_access_indexed_info(InstructionList &indices, int
aii->_max = idx;
aii->_list = new AccessIndexedList();
} else if (idx >= aii->_min && idx <= aii->_max) {
remove_range_check(ai);
return;
// Guard against underflow/overflow (see 'range_cond' check in RangeCheckEliminator::in_block_motion)
if (aii->_max < 0 || (aii->_max + min_jint) <= aii->_min) {
remove_range_check(ai);
return;
}
}
aii->_min = MIN2(aii->_min, idx);
aii->_max = MAX2(aii->_max, idx);
Expand Down Expand Up @@ -423,9 +426,9 @@ void RangeCheckEliminator::in_block_motion(BlockBegin *block, AccessIndexedList
}
}
} else {
int last_integer = 0;
jint last_integer = 0;
Instruction *last_instruction = index;
int base = 0;
jint base = 0;
ArithmeticOp *ao = index->as_ArithmeticOp();

while (ao != NULL && (ao->x()->as_Constant() || ao->y()->as_Constant()) && (ao->op() == Bytecodes::_iadd || ao->op() == Bytecodes::_isub)) {
Expand All @@ -437,12 +440,12 @@ void RangeCheckEliminator::in_block_motion(BlockBegin *block, AccessIndexedList
}

if (c) {
int value = c->type()->as_IntConstant()->value();
jint value = c->type()->as_IntConstant()->value();
if (value != min_jint) {
if (ao->op() == Bytecodes::_isub) {
value = -value;
}
base += value;
base = java_add(base, value);
last_integer = base;
last_instruction = other;
}
Expand All @@ -464,12 +467,12 @@ void RangeCheckEliminator::in_block_motion(BlockBegin *block, AccessIndexedList
assert(info != NULL, "Info must not be null");

// if idx < 0, max > 0, max + idx may fall between 0 and
// length-1 and if min < 0, min + idx may overflow and be >=
// length-1 and if min < 0, min + idx may underflow/overflow and be >=
// 0. The predicate wouldn't trigger but some accesses could
// be with a negative index. This test guarantees that for the
// min and max value that are kept the predicate can't let
// some incorrect accesses happen.
bool range_cond = (info->_max < 0 || info->_max + min_jint <= info->_min);
bool range_cond = (info->_max < 0 || (info->_max + min_jint) <= info->_min);

// Generate code only if more than 2 range checks can be eliminated because of that.
// 2 because at least 2 comparisons are done
Expand Down Expand Up @@ -809,7 +812,7 @@ void RangeCheckEliminator::process_access_indexed(BlockBegin *loop_header, Block
);

remove_range_check(ai);
} else if (_optimistic && loop_header) {
} else if (false && _optimistic && loop_header) {
assert(ai->array(), "Array must not be null!");
assert(ai->index(), "Index must not be null!");

Expand Down
5 changes: 3 additions & 2 deletions hotspot/src/share/vm/classfile/verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2093,11 +2093,12 @@ void ClassVerifier::verify_switch(
"low must be less than or equal to high in tableswitch");
return;
}
keys = high - low + 1;
if (keys < 0) {
int64_t keys64 = ((int64_t)high - low) + 1;
if (keys64 > 65535) { // Max code length
verify_error(ErrorContext::bad_code(bci), "too many keys in tableswitch");
return;
}
keys = (int)keys64;
delta = 1;
} else {
keys = (int)Bytes::get_Java_u4(aligned_bcp + jintSize);
Expand Down
22 changes: 16 additions & 6 deletions hotspot/src/share/vm/interpreter/bytecodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,18 @@ int Bytecodes::special_length_at(Bytecodes::Code code, address bcp, address end)
if (end != NULL && aligned_bcp + 3*jintSize >= end) {
return -1; // don't read past end of code buffer
}
// Promote calculation to signed 64 bits to do range checks, used by the verifier.
jlong lo = (jint)Bytes::get_Java_u4(aligned_bcp + 1*jintSize);
jlong hi = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize);
jlong len = (aligned_bcp - bcp) + (3 + hi - lo + 1)*jintSize;
// only return len if it can be represented as a positive int;
// return -1 otherwise
return (len > 0 && len == (int)len) ? len : -1;
// Only return len if it can be represented as a positive int and lo <= hi.
// The caller checks for bytecode stream overflow.
if (lo <= hi && len == (int)len) {
assert(len > 0, "must be");
return (int)len;
} else {
return -1;
}
}

case _lookupswitch: // fall through
Expand All @@ -143,9 +149,13 @@ int Bytecodes::special_length_at(Bytecodes::Code code, address bcp, address end)
}
jlong npairs = (jint)Bytes::get_Java_u4(aligned_bcp + jintSize);
jlong len = (aligned_bcp - bcp) + (2 + 2*npairs)*jintSize;
// only return len if it can be represented as a positive int;
// return -1 otherwise
return (len > 0 && len == (int)len) ? len : -1;
// Only return len if it can be represented as a positive int and npairs >= 0.
if (npairs >= 0 && len == (int)len) {
assert(len > 0, "must be");
return (int)len;
} else {
return -1;
}
}
}
// Note: Length functions must return <=0 for invalid bytecodes.
Expand Down
59 changes: 52 additions & 7 deletions hotspot/src/share/vm/opto/ifnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -882,6 +882,46 @@ Node *IfNode::Ideal(PhaseGVN *phase, bool can_reshape) {
// then we are guaranteed to fail, so just start interpreting there.
// We 'expand' the top 3 range checks to include all post-dominating
// checks.
//
// Example:
// a[i+x] // (1) 1 < x < 6
// a[i+3] // (2)
// a[i+4] // (3)
// a[i+6] // max = max of all constants
// a[i+2]
// a[i+1] // min = min of all constants
//
// If x < 3:
// (1) a[i+x]: Leave unchanged
// (2) a[i+3]: Replace with a[i+max] = a[i+6]: i+x < i+3 <= i+6 -> (2) is covered
// (3) a[i+4]: Replace with a[i+min] = a[i+1]: i+1 < i+4 <= i+6 -> (3) and all following checks are covered
// Remove all other a[i+c] checks
//
// If x >= 3:
// (1) a[i+x]: Leave unchanged
// (2) a[i+3]: Replace with a[i+min] = a[i+1]: i+1 < i+3 <= i+x -> (2) is covered
// (3) a[i+4]: Replace with a[i+max] = a[i+6]: i+1 < i+4 <= i+6 -> (3) and all following checks are covered
// Remove all other a[i+c] checks
//
// We only need the top 2 range checks if x is the min or max of all constants.
//
// This, however, only works if the interval [i+min,i+max] is not larger than max_int (i.e. abs(max - min) < max_int):
// The theoretical max size of an array is max_int with:
// - Valid index space: [0,max_int-1]
// - Invalid index space: [max_int,-1] // max_int, min_int, min_int - 1 ..., -1
//
// The size of the consecutive valid index space is smaller than the size of the consecutive invalid index space.
// If we choose min and max in such a way that:
// - abs(max - min) < max_int
// - i+max and i+min are inside the valid index space
// then all indices [i+min,i+max] must be in the valid index space. Otherwise, the invalid index space must be
// smaller than the valid index space which is never the case for any array size.
//
// Choosing a smaller array size only makes the valid index space smaller and the invalid index space larger and
// the argument above still holds.
//
// Note that the same optimization with the same maximal accepted interval size can also be found in C1.
const jlong maximum_number_of_min_max_interval_indices = (jlong)max_jint;

// The top 3 range checks seen
const int NRC =3;
Expand Down Expand Up @@ -915,13 +955,18 @@ Node *IfNode::Ideal(PhaseGVN *phase, bool can_reshape) {
found_immediate_dominator = true;
break;
}
// Gather expanded bounds
off_lo = MIN2(off_lo,offset2);
off_hi = MAX2(off_hi,offset2);
// Record top NRC range checks
prev_checks[nb_checks%NRC].ctl = prev_dom;
prev_checks[nb_checks%NRC].off = offset2;
nb_checks++;

// "x - y" -> must add one to the difference for number of elements in [x,y]
const jlong diff = (jlong)MIN2(offset2, off_lo) - (jlong)MAX2(offset2, off_hi);
if (ABS(diff) < maximum_number_of_min_max_interval_indices) {
// Gather expanded bounds
off_lo = MIN2(off_lo, offset2);
off_hi = MAX2(off_hi, offset2);
// Record top NRC range checks
prev_checks[nb_checks % NRC].ctl = prev_dom;
prev_checks[nb_checks % NRC].off = offset2;
nb_checks++;
}
}
}
prev_dom = dom;
Expand Down
Loading

0 comments on commit ead1d6f

Please sign in to comment.