Top


定義場所(file name)

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

説明(description)

// Common register usage:
// O0: env
// O1: obj
// O2: jfieldID
// O4: offset (O2 >> 2)
// G4: old safepoint counter

名前(function name)

address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {

本体部(body)

  {- -------------------------------------------
  (1) 型に応じた名前の BufferBlob を新規に作成し, そこにマシン語を書き出すための MacroAssembler も作成する.
      ---------------------------------------- -}

      const char *name;
      switch (type) {
        case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break;
        case T_BYTE:    name = "jni_fast_GetByteField";    break;
        case T_CHAR:    name = "jni_fast_GetCharField";    break;
        case T_SHORT:   name = "jni_fast_GetShortField";   break;
        case T_INT:     name = "jni_fast_GetIntField";     break;
        default:        ShouldNotReachHere();
      }
      ResourceMark rm;
      BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize);
      CodeBuffer cbuf(blob);
      MacroAssembler* masm = new MacroAssembler(&cbuf);

  {- -------------------------------------------
  (1) (ここからが生成するコードの始まり)
      ---------------------------------------- -}

      address fast_entry = __ pc();

  {- -------------------------------------------
  (1) コード生成:
      「SafepointSynchronize::safepoint_counter の値を取得し, 奇数かどうかをチェック.
      奇数であれば label1 までジャンプして slow case にフォールバック.」
      ---------------------------------------- -}

      Label label1, label2;

      AddressLiteral cnt_addrlit(SafepointSynchronize::safepoint_counter_addr());
      __ sethi (cnt_addrlit, O3);
      Address cnt_addr(O3, cnt_addrlit.low10());
      __ ld (cnt_addr, G4);
      __ andcc (G4, 1, G0);
      __ br (Assembler::notZero, false, Assembler::pn, label1);

  {- -------------------------------------------
  (1) コード生成:
      「オブジェクト内での対象フィールドのオフセットを計算.
        (といっても O2(jfieldID) の値を 2つシフトさせるだけ)」
      ---------------------------------------- -}

      __ delayed()->srl (O2, 2, O4);

  {- -------------------------------------------
  (1) コード生成:
      「(SafepointSynchronize::safepoint_counter が奇数でなかった場合には)
      引数の Handle から実際のオブジェクトへのポインタを取得し, 
      計算したオフセット位置からのロードを行う.
      ロードする bit 幅は, 型に応じて適切なものを選ぶ.」
      (なお, ここのロード命令アドレスを speculative_load_pclist に登録する)
      ---------------------------------------- -}

      __ ld_ptr (O1, 0, O5);

      assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
      speculative_load_pclist[count] = __ pc();
      switch (type) {
        case T_BOOLEAN: __ ldub (O5, O4, G3);  break;
        case T_BYTE:    __ ldsb (O5, O4, G3);  break;
        case T_CHAR:    __ lduh (O5, O4, G3);  break;
        case T_SHORT:   __ ldsh (O5, O4, G3);  break;
        case T_INT:     __ ld (O5, O4, G3);    break;
        default:        ShouldNotReachHere();
      }

  {- -------------------------------------------
  (1) コード生成:
      「再度 SafepointSynchronize::safepoint_counter の値を取得する.
      値が変わっていれば, label2 にジャンプして slow case へフォールバック.
      変わっていなければ, 取得した値を O0 に移しつつ, このままリターンする.」

      (label1 ではなく label2 なのは, delayed slot で mov(O7, G1) できてしまうので, 
       その分の処理が終わったところまで飛んで効率化するため)
      ---------------------------------------- -}

      __ ld (cnt_addr, O5);
      __ cmp (O5, G4);
      __ br (Assembler::notEqual, false, Assembler::pn, label2);
      __ delayed()->mov (O7, G1);
      __ retl ();
      __ delayed()->mov (G3, O0);

  {- -------------------------------------------
  (1) (ここから先は jni_GetXXXField() にフォールバックする処理)
      (なお, slowcase_entry_pclist にはここのアドレスを登録する)
      ---------------------------------------- -}

      slowcase_entry_pclist[count++] = __ pc();
      __ bind (label1);

  {- -------------------------------------------
  (1) コード生成:
      「対応する jni_Get<Primitive>Field_addr をコールする.」
      (リターン時にはこのコール点ではなく Get<Primitive>Field() を呼び出した caller 側に戻れるよう,
       コール前後で, リターンアドレスを G1 にいったん待避して復帰させている (要は末尾呼び出しになるようにしている))
      ---------------------------------------- -}

      __ mov (O7, G1);

      address slow_case_addr;
      switch (type) {
        case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break;
        case T_BYTE:    slow_case_addr = jni_GetByteField_addr();    break;
        case T_CHAR:    slow_case_addr = jni_GetCharField_addr();    break;
        case T_SHORT:   slow_case_addr = jni_GetShortField_addr();   break;
        case T_INT:     slow_case_addr = jni_GetIntField_addr();     break;
        default:        ShouldNotReachHere();
      }
      __ bind (label2);
      __ call (slow_case_addr, relocInfo::none);
      __ delayed()->mov (G1, O7);

  {- -------------------------------------------
  (1) 以上のコードを flush() し, 生成したコードのエントリポイントをリターン.
      ---------------------------------------- -}

      __ flush ();

      return fast_entry;
    }

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