什么时候发生
libjvm.so!RangeCheckEliminator::RangeCheckEliminator(RangeCheckEliminator * const this, IR * ir) (/home/qingfeng.yy/jdktip/src/hotspot/share/c1/c1_RangeCheckElimination.cpp:95)
libjvm.so!RangeCheckElimination::eliminate(IR * ir) (/home/qingfeng.yy/jdktip/src/hotspot/share/c1/c1_RangeCheckElimination.cpp:53)
libjvm.so!Compilation::build_hir(Compilation * const this) (/home/qingfeng.yy/jdktip/src/hotspot/share/c1/c1_Compilation.cpp:218)
libjvm.so!Compilation::compile_java_method(Compilation * const this) (/home/qingfeng.yy/jdktip/src/hotspot/share/c1/c1_Compilation.cpp:387)
libjvm.so!Compilation::compile_method(Compilation * const this) (/home/qingfeng.yy/jdktip/src/hotspot/share/c1/c1_Compilation.cpp:460)
libjvm.so!Compilation::Compilation(Compilation * const this, AbstractCompiler * compiler, ciEnv * env, ciMethod * method, int osr_bci, BufferBlob * buffer_blob, bool install_code, DirectiveSet * directive) (/home/qingfeng.yy/jdktip/src/hotspot/share/c1/c1_Compilation.cpp:584)
libjvm.so!Compiler::compile_method(Compiler * const this, ciEnv * env, ciMethod * method, int entry_bci, bool install_code, DirectiveSet * directive) (/home/qingfeng.yy/jdktip/src/hotspot/share/c1/c1_Compiler.cpp:248)
libjvm.so!CompileBroker::invoke_compiler_on_method(CompileTask * task) (/home/qingfeng.yy/jdktip/src/hotspot/share/compiler/compileBroker.cpp:2312)
libjvm.so!CompileBroker::compiler_thread_loop() (/home/qingfeng.yy/jdktip/src/hotspot/share/compiler/compileBroker.cpp:1985)
libjvm.so!CompilerThread::thread_entry(JavaThread * thread, Thread * __the_thread__) (/home/qingfeng.yy/jdktip/src/hotspot/share/compiler/compilerThread.cpp:59)
libjvm.so!JavaThread::thread_main_inner(JavaThread * const this) (/home/qingfeng.yy/jdktip/src/hotspot/share/runtime/thread.cpp:1337)
libjvm.so!JavaThread::run(JavaThread * const this) (/home/qingfeng.yy/jdktip/src/hotspot/share/runtime/thread.cpp:1320)
libjvm.so!Thread::call_run(Thread * const this) (/home/qingfeng.yy/jdktip/src/hotspot/share/runtime/thread.cpp:400)
libjvm.so!thread_native_entry(Thread * thread) (/home/qingfeng.yy/jdktip/src/hotspot/os/linux/os_linux.cpp:719)
RCE入口
RangeCheckEliminator::RangeCheckEliminator构造函数里面的calc_bounds就是RCE的本体。
// Calculate bounds for instruction in this block and children blocks in the dominator tree
void RangeCheckEliminator::calc_bounds(BlockBegin *block, BlockBegin *loop_header) {
// Ensures a valid loop_header
assert(!loop_header || loop_header->is_set(BlockBegin::linear_scan_loop_header_flag), "Loop header has to be real !");
// Tracing output
TRACE_RANGE_CHECK_ELIMINATION(
tty->fill_to(block->dominator_depth()*2);
tty->print_cr("Block B%d", block->block_id());
);
// Pushed stack for conditions
IntegerStack pushed;
// Process If
BlockBegin *parent = block->dominator();
if (parent != NULL) {
If *cond = parent->end()->as_If();
if (cond != NULL) {
process_if(pushed, block, cond);
}
}
// Interate over current block
InstructionList arrays;
AccessIndexedList accessIndexed;
Instruction *cur = block;
// 遍历当前bblock的所有指令。
while (cur) {
// Ensure cur wasn't inserted during the elimination
if (cur->id() < this->_bounds.length()) {
// Process only if it is an access indexed instruction
// 如果发现是一条AccessIndexed指令(LoadIndexed,StoreIndexed),就准备工作
AccessIndexed *ai = cur->as_AccessIndexed();
if (ai != NULL) {
// 处理AccessIndexed指令
process_access_indexed(loop_header, block, ai);
accessIndexed.append(ai);
if (!arrays.contains(ai->array())) {
arrays.append(ai->array());
}
// 获取AccessIndexed指令的bound
Bound *b = get_bound(ai->index());
// 检查bound上界
if (!b->lower_instr()) {
// Lower bound is constant
update_bound(pushed, ai->index(), Instruction::geq, NULL, 0);
}
// 检查bound下界
if (!b->has_upper()) {
if (ai->length() && ai->length()->type()->as_IntConstant()) {
int value = ai->length()->type()->as_IntConstant()->value();
update_bound(pushed, ai->index(), Instruction::lss, NULL, value);
} else {
// Has no upper bound
Instruction *instr = ai->length();
if (instr != NULL) instr = ai->array();
update_bound(pushed, ai->index(), Instruction::lss, instr, 0);
}
}
}
}
cur = cur->next();
}
// Output current condition stack
TRACE_RANGE_CHECK_ELIMINATION(dump_condition_stack(block));
// Do in block motion of range checks
in_block_motion(block, accessIndexed, arrays);
// Call all dominated blocks
for (int i=0; i<block->dominates()->length(); i++) {
BlockBegin *next = block->dominates()->at(i);
if (!next->is_set(BlockBegin::donot_eliminate_range_checks)) {
// if current block is a loop header and:
// - next block belongs to the same loop
// or
// - next block belongs to an inner loop
// then current block is the loop header for next block
if (block->is_set(BlockBegin::linear_scan_loop_header_flag) && (block->loop_index() == next->loop_index() || next->loop_depth() > block->loop_depth())) {
calc_bounds(next, block);
} else {
calc_bounds(next, loop_header);
}
}
}
// Reset stack
for (int i=0; i<pushed.length(); i++) {
_bounds.at(pushed.at(i))->pop();
}
}
process也是核心,那么process是怎么处理的呢?
void RangeCheckEliminator::process_access_indexed(BlockBegin *loop_header, BlockBegin *block, AccessIndexed *ai) {
TRACE_RANGE_CHECK_ELIMINATION(
tty->fill_to(block->dominator_depth()*2)
);
TRACE_RANGE_CHECK_ELIMINATION(
tty->print_cr("Access indexed: index=%d length=%d", ai->index()->id(), (ai->length() != NULL ? ai->length()->id() :-1 ))
);
if (ai->check_flag(Instruction::NeedsRangeCheckFlag)) {
// 先拿index,比如arr[100]这里可以拿到100,具体拿的方式是用Visitor设计模式。还是
//
// 以arr[100]为例,这里get_bounds会调用RangeCheckEliminator::Visitor::do_Constant
// 获取到index
// void RangeCheckEliminator::Visitor::do_Constant(Constant *c) {
// IntConstant *ic = c->type()->as_IntConstant();
// if (ic != NULL) {
// int value = ic->value();
// _bound = new Bound(value, NULL, value, NULL);
// }
// }
Bound *index_bound = get_bound(ai->index());
if (!index_bound->has_lower() || !index_bound->has_upper()) {
TRACE_RANGE_CHECK_ELIMINATION(
tty->fill_to(block->dominator_depth()*2);
tty->print_cr("Index instruction %d has no lower and/or no upper bound!", ai->index()->id())
);
return;
}
// 再拿array bound
Bound *array_bound;
if (ai->length()) {
array_bound = get_bound(ai->length());
} else {
array_bound = get_bound(ai->array());
}
// 比较严格的条件,检查index_bound是不是在array_bound范围内
// 且 index_bounds下界大于等于0
if (in_array_bound(index_bound, ai->array()) ||
(index_bound && array_bound && index_bound->is_smaller(array_bound) && !index_bound->lower_instr() && index_bound->lower() >= 0)) {
TRACE_RANGE_CHECK_ELIMINATION(
tty->fill_to(block->dominator_depth()*2);
tty->print_cr("Bounds check for instruction %d in block B%d can be fully eliminated!", ai->id(), ai->block()->block_id())
);
// !!!rce成功,移除range check,同时NeedsRangeCheckFlag这个flag设置为false
remove_range_check(ai);
} else if (_optimistic && loop_header) {
assert(ai->array(), "Array must not be null!");
assert(ai->index(), "Index must not be null!");
// Array instruction
Instruction *array_instr = ai->array();
if (!loop_invariant(loop_header, array_instr)) {
TRACE_RANGE_CHECK_ELIMINATION(
tty->fill_to(block->dominator_depth()*2);
tty->print_cr("Array %d is not loop invariant to header B%d", ai->array()->id(), loop_header->block_id())
);
return;
}
// Lower instruction
Value index_instr = ai->index();
Value lower_instr = index_bound->lower_instr();
if (!loop_invariant(loop_header, lower_instr)) {
TRACE_RANGE_CHECK_ELIMINATION(
tty->fill_to(block->dominator_depth()*2);
tty->print_cr("Lower instruction %d not loop invariant!", lower_instr->id())
);
return;
}
if (!lower_instr && index_bound->lower() < 0) {
TRACE_RANGE_CHECK_ELIMINATION(
tty->fill_to(block->dominator_depth()*2);
tty->print_cr("Lower bound smaller than 0 (%d)!", index_bound->lower())
);
return;
}
// Upper instruction
Value upper_instr = index_bound->upper_instr();
if (!loop_invariant(loop_header, upper_instr)) {
TRACE_RANGE_CHECK_ELIMINATION(
tty->fill_to(block->dominator_depth()*2);
tty->print_cr("Upper instruction %d not loop invariant!", upper_instr->id())
);
return;
}
// Length instruction
Value length_instr = ai->length();
if (!loop_invariant(loop_header, length_instr)) {
// Generate length instruction yourself!
length_instr = NULL;
}
TRACE_RANGE_CHECK_ELIMINATION(
tty->fill_to(block->dominator_depth()*2);
tty->print_cr("LOOP INVARIANT access indexed %d found in block B%d!", ai->id(), ai->block()->block_id())
);
BlockBegin *pred_block = loop_header->dominator();
assert(pred_block != NULL, "Every loop header has a dominator!");
BlockEnd *pred_block_end = pred_block->end();
Instruction *insert_position = pred_block_end->prev();
ValueStack *state = pred_block_end->state_before();
if (pred_block_end->as_Goto() && state == NULL) state = pred_block_end->state();
assert(state, "State must not be null");
// Add deoptimization to dominator of loop header
TRACE_RANGE_CHECK_ELIMINATION(
tty->fill_to(block->dominator_depth()*2);
tty->print_cr("Inserting deopt at bci %d in block B%d!", state->bci(), insert_position->block()->block_id())
);
if (!is_ok_for_deoptimization(insert_position, array_instr, length_instr, lower_instr, index_bound->lower(), upper_instr, index_bound->upper())) {
TRACE_RANGE_CHECK_ELIMINATION(
tty->fill_to(block->dominator_depth()*2);
tty->print_cr("Could not eliminate because of static analysis!")
);
return;
}
insert_deoptimization(state, insert_position, array_instr, length_instr, lower_instr, index_bound->lower(), upper_instr, index_bound->upper(), ai);
// Finally remove the range check!
remove_range_check(ai);
}
}
}