• 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);
        }
      }
    }
    
  • 相关阅读:
    开发模型----快速原型模型
    开发模型--瀑布模型
    python_001
    Linux文件的类型与系统目录
    流程控制语句
    test命令
    排序sort && 取消重复行uniq
    sed命令——用来对文件数据的 选取、替换、删除
    颜色RGB大全
    Markdown的使用
  • 原文地址:https://www.cnblogs.com/kelthuzadx/p/15718368.html
Copyright © 2020-2023  润新知