C1 RCE

什么时候发生

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);
    }
  }
}
原文地址:https://www.cnblogs.com/kelthuzadx/p/15718368.html