Top


定義場所(file name)

hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp

名前(function name)

void InterpreterMacroAssembler::test_backedge_count_for_osr( Register backedge_count,
                                                             Register branch_bcp,
                                                             Register Rtmp ) {

本体部(body)

  {- -------------------------------------------
  (1) (変数宣言など)
      ---------------------------------------- -}

      Label did_not_overflow;
      Label overflow_with_error;

  {- -------------------------------------------
  (1) (assert)
      ---------------------------------------- -}

      assert_different_registers(backedge_count, Rtmp, branch_bcp);
      assert(UseOnStackReplacement,"Must UseOnStackReplacement to test_backedge_count_for_osr");

  {- -------------------------------------------
  (1) コード生成:
      「InvocationCounter::InterpreterBackwardBranchLimit と現在の値を比較し, 
       越えてなければ did_not_overflow ラベルまで飛ぶ.」
      ---------------------------------------- -}

      AddressLiteral limit(&InvocationCounter::InterpreterBackwardBranchLimit);
      load_contents(limit, Rtmp);
      cmp(backedge_count, Rtmp);
      br(Assembler::lessUnsigned, false, Assembler::pt, did_not_overflow);
      delayed()->nop();

  {- -------------------------------------------
  (1) コード生成: (ただし, ProfileInterpreter オプションが指定されていない場合には行わない)
      「ProfileInterpreter 指定時には frequency_counter_overflow() がカウンタの値をクリアしないので,
        一度しきい値を越えると(既に JIT compiler が作業中なのに)連続してコンパイル要求を出すことになりかねない.
        そこで, overflow_frequency という間隔(今は1024)につき1度だけ呼ばれるよう調整しておく.
        (それ以外の1023回は, 何もせず did_not_overflow ラベルに飛ぶだけにする)」
      ---------------------------------------- -}

      // When ProfileInterpreter is on, the backedge_count comes from the
      // methodDataOop, which value does not get reset on the call to
      // frequency_counter_overflow().  To avoid excessive calls to the overflow
      // routine while the method is being compiled, add a second test to make sure
      // the overflow function is called only once every overflow_frequency.
      if (ProfileInterpreter) {
        const int overflow_frequency = 1024;
        andcc(backedge_count, overflow_frequency-1, Rtmp);
        brx(Assembler::notZero, false, Assembler::pt, did_not_overflow);
        delayed()->nop();
      }

  {- -------------------------------------------
  (1) コード生成:
      「InterpreterRuntime::frequency_counter_overflow() を呼び出して JIT コンパイル処理を開始する.」
      ---------------------------------------- -}

      // overflow in loop, pass branch bytecode
      set(6,Rtmp);
      call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), branch_bcp, Rtmp);

  {- -------------------------------------------
  (1) コード生成:
      「もし InterpreterRuntime::frequency_counter_overflow() の返り値が NULL だったら,
        (まだ JIT 生成されたコードがないということなので) overflow_with_error ラベルまで飛ぶ.
        また, nmethod が既に invalidate されていた場合も, overflow_with_error ラベルまで飛ぶ.」
      ---------------------------------------- -}

      // Was an OSR adapter generated?
      // O0 = osr nmethod
      tst(O0);
      brx(Assembler::zero, false, Assembler::pn, overflow_with_error);
      delayed()->nop();

      // Has the nmethod been invalidated already?
      ld(O0, nmethod::entry_bci_offset(), O2);
      cmp(O2, InvalidOSREntryBci);
      br(Assembler::equal, false, Assembler::pn, overflow_with_error);
      delayed()->nop();

  {- -------------------------------------------
  (1) (ここまで来たら, JIT 生成された nmethod が得られたということになる)
      ---------------------------------------- -}

      // migrate the interpreter frame off of the stack

  {- -------------------------------------------
  (1) コード生成:
      「SharedRuntime::OSR_migration_begin() を呼んで, 
        interpreter frame 中の局所変数とモニタを C ヒープ上に取ったバッファに退避する.
        (呼び出しの前後で G2_thread や O0(に入っている nmethod) の退避復帰を行っている)」
      ---------------------------------------- -}

      mov(G2_thread, L7);
      // save nmethod
      mov(O0, L6);
      set_last_Java_frame(SP, noreg);
      call_VM_leaf(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin), L7);
      reset_last_Java_frame();
      mov(L7, G2_thread);

  {- -------------------------------------------
  (1) コード生成:
      「nmethod や SharedRuntime::OSR_migration_begin() が返したバッファを I0/I1 に退避してから, 
       restore 命令で interpreter frame を削除する.」
      ---------------------------------------- -}

      // move OSR nmethod to I1
      mov(L6, I1);

      // OSR buffer to I0
      mov(O0, I0);

      // remove the interpreter frame
      restore(I5_savedSP, 0, SP);

  {- -------------------------------------------
  (1) コード生成:
      「nmethod からエントリポイントを取得し, osr コードにジャンプする.」
      ---------------------------------------- -}

      // Jump to the osr code.
      ld_ptr(O1, nmethod::osr_entry_point_offset(), O2);
      jmp(O2, G0);
      delayed()->nop();

  {- -------------------------------------------
  (1) コード生成:
      「(ここが overflow_with_error ラベルの位置)」
      (nmethod が得られなかった場合はここまでジャンプする)
      ---------------------------------------- -}

      bind(overflow_with_error);

      bind(did_not_overflow);
    }

This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.