Top


定義場所(file name)

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

名前(function name)

void TemplateTable::getfield_or_static(int byte_no, bool is_static) {

本体部(body)

  {- -------------------------------------------
  (1) (assert) (See: TemplateTable::transition())
      ---------------------------------------- -}

      transition(vtos, vtos);

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

      Register Rcache = G3_scratch;
      Register index  = G4_scratch;
      Register Rclass = Rcache;
      Register Roffset= G4_scratch;
      Register Rflags = G1_scratch;
      ByteSize cp_base_offset = constantPoolCacheOopDesc::base_offset();

  {- -------------------------------------------
  (1) TemplateTable::resolve_cache_and_index() を呼んで, 以下のようなコードを生成.
      「現在箇所のバイトコード(bcp)に対応する CPCache エントリのアドレスを Rcache に取得する.
      もし対応する CPCache エントリがまだ生成されていなければ, その生成も行う.」
      ---------------------------------------- -}

      resolve_cache_and_index(byte_no, noreg, Rcache, index, sizeof(u2));

  {- -------------------------------------------
  (1) コード生成: (JVMTI のフック点)
      ---------------------------------------- -}

      jvmti_post_field_access(Rcache, index, is_static, false);

  {- -------------------------------------------
  (1) TemplateTable::load_field_cp_cache_entry() を呼んで, 以下のようなコードを生成.
      「取得した CPCache エントリの中から, 実際のオフセット情報を Roffset に取得.
      また, 取得した CPCache エントリの中から, フラグ情報を Rflags に取得.」
      ---------------------------------------- -}

      load_field_cp_cache_entry(Rclass, Rcache, index, Roffset, Rflags, is_static);

  {- -------------------------------------------
  (1) コード生成: (NULL チェック) & (verify)
      ---------------------------------------- -}

      if (!is_static) {
        pop_and_check_object(Rclass);
      } else {
        __ verify_oop(Rclass);
      }

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

      Label exit;

  {- -------------------------------------------
  (1) もしメモリバリアの必要がある環境であれば, 
      ここに「volatile 情報を Lscratch に取得する」というコードを生成しておく (この情報は後で使用する).
      ---------------------------------------- -}

      Assembler::Membar_mask_bits membar_bits =
        Assembler::Membar_mask_bits(Assembler::LoadLoad | Assembler::LoadStore);

      if (__ membar_has_effect(membar_bits)) {
        // Get volatile flag
        __ set((1 << ConstantPoolCacheEntry::volatileField), Lscratch);
        __ and3(Rflags, Lscratch, Lscratch);
      }

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

      Label checkVolatile;

  {- -------------------------------------------
  (1) コード生成:
      「CPCache のエントリから型情報を取り出す.
       (ConstantPoolCacheEntry::tosBits ビットに格納されている模様)」
      ---------------------------------------- -}

      // compute field type
      Label notByte, notInt, notShort, notChar, notLong, notFloat, notObj;
      __ srl(Rflags, ConstantPoolCacheEntry::tosBits, Rflags);
      // Make sure we don't need to mask Rflags for tosBits after the above shift
      ConstantPoolCacheEntry::verify_tosBits();

  {- -------------------------------------------
  (1) コード生成:
      「型情報に応じた処理を行う.
        (1) まず atos かどうかをチェック.
        (1) 次に itos かどうかをチェック.
        (1) 次に ltos かどうかをチェック.
        (1) 次に btos かどうかをチェック.
        (1) 次に ctos かどうかをチェック.
        (1) 次に stos かどうかをチェック.
        (1) 次に ftos かどうかをチェック.
        (1) 以上のどれでもなければ dtos.」

      なお, それぞれの場合で高速版への rewrite 処理を行っている (See: [here](no7882vBO.html) for details)
      そのため, ここのコードはそれぞれの箇所で最初の一回だけ実行される.
      (なぜ static は最適化しない?? static は使われる比率が小さいから効果が低い?? #TODO)
      ---------------------------------------- -}

    {- -------------------------------------------
  (1.1) (ここが atos チェック)
        ---------------------------------------- -}

      // Check atos before itos for getstatic, more likely (in Queens at least)
      __ cmp(Rflags, atos);
      __ br(Assembler::notEqual, false, Assembler::pt, notObj);
      __ delayed() ->cmp(Rflags, itos);

    {- -------------------------------------------
  (1.1) (ここが atos の場合の処理)
        ---------------------------------------- -}

      // atos
      __ load_heap_oop(Rclass, Roffset, Otos_i);
      __ verify_oop(Otos_i);
      __ push(atos);
      if (!is_static) {
        patch_bytecode(Bytecodes::_fast_agetfield, G3_scratch, G4_scratch);
      }
      __ ba(false, checkVolatile);
      __ delayed()->tst(Lscratch);

    {- -------------------------------------------
  (1.1) (ここが itos チェック)
        ---------------------------------------- -}

      __ bind(notObj);

      // cmp(Rflags, itos);
      __ br(Assembler::notEqual, false, Assembler::pt, notInt);
      __ delayed() ->cmp(Rflags, ltos);

    {- -------------------------------------------
  (1.1) (ここが itos の場合の処理)
        ---------------------------------------- -}

      // itos
      __ ld(Rclass, Roffset, Otos_i);
      __ push(itos);
      if (!is_static) {
        patch_bytecode(Bytecodes::_fast_igetfield, G3_scratch, G4_scratch);
      }
      __ ba(false, checkVolatile);
      __ delayed()->tst(Lscratch);

    {- -------------------------------------------
  (1.1) (ここが ltos チェック)
        ---------------------------------------- -}

      __ bind(notInt);

      // cmp(Rflags, ltos);
      __ br(Assembler::notEqual, false, Assembler::pt, notLong);
      __ delayed() ->cmp(Rflags, btos);

    {- -------------------------------------------
  (1.1) (ここが ltos の場合の処理)
        ---------------------------------------- -}

      // ltos
      // load must be atomic
      __ ld_long(Rclass, Roffset, Otos_l);
      __ push(ltos);
      if (!is_static) {
        patch_bytecode(Bytecodes::_fast_lgetfield, G3_scratch, G4_scratch);
      }
      __ ba(false, checkVolatile);
      __ delayed()->tst(Lscratch);

    {- -------------------------------------------
  (1.1) (ここが btos チェック)
        ---------------------------------------- -}

      __ bind(notLong);

      // cmp(Rflags, btos);
      __ br(Assembler::notEqual, false, Assembler::pt, notByte);
      __ delayed() ->cmp(Rflags, ctos);

    {- -------------------------------------------
  (1.1) (ここが btos の場合の処理)
        ---------------------------------------- -}

      // btos
      __ ldsb(Rclass, Roffset, Otos_i);
      __ push(itos);
      if (!is_static) {
        patch_bytecode(Bytecodes::_fast_bgetfield, G3_scratch, G4_scratch);
      }
      __ ba(false, checkVolatile);
      __ delayed()->tst(Lscratch);

    {- -------------------------------------------
  (1.1) (ここが ctos チェック)
        ---------------------------------------- -}

      __ bind(notByte);

      // cmp(Rflags, ctos);
      __ br(Assembler::notEqual, false, Assembler::pt, notChar);
      __ delayed() ->cmp(Rflags, stos);

    {- -------------------------------------------
  (1.1) (ここが ctos の場合の処理)
        ---------------------------------------- -}

      // ctos
      __ lduh(Rclass, Roffset, Otos_i);
      __ push(itos);
      if (!is_static) {
        patch_bytecode(Bytecodes::_fast_cgetfield, G3_scratch, G4_scratch);
      }
      __ ba(false, checkVolatile);
      __ delayed()->tst(Lscratch);

    {- -------------------------------------------
  (1.1) (ここが stos チェック)
        ---------------------------------------- -}

      __ bind(notChar);

      // cmp(Rflags, stos);
      __ br(Assembler::notEqual, false, Assembler::pt, notShort);
      __ delayed() ->cmp(Rflags, ftos);

    {- -------------------------------------------
  (1.1) (ここが stos の場合の処理)
        ---------------------------------------- -}

      // stos
      __ ldsh(Rclass, Roffset, Otos_i);
      __ push(itos);
      if (!is_static) {
        patch_bytecode(Bytecodes::_fast_sgetfield, G3_scratch, G4_scratch);
      }
      __ ba(false, checkVolatile);
      __ delayed()->tst(Lscratch);

    {- -------------------------------------------
  (1.1) (ここが ftos チェック)
        ---------------------------------------- -}

      __ bind(notShort);


      // cmp(Rflags, ftos);
      __ br(Assembler::notEqual, false, Assembler::pt, notFloat);
      __ delayed() ->tst(Lscratch);

    {- -------------------------------------------
  (1.1) (ここが ftos の場合の処理)
        ---------------------------------------- -}

      // ftos
      __ ldf(FloatRegisterImpl::S, Rclass, Roffset, Ftos_f);
      __ push(ftos);
      if (!is_static) {
        patch_bytecode(Bytecodes::_fast_fgetfield, G3_scratch, G4_scratch);
      }
      __ ba(false, checkVolatile);
      __ delayed()->tst(Lscratch);

    {- -------------------------------------------
  (1.1) (以上のどれでもなければ dtos)
        ---------------------------------------- -}

      __ bind(notFloat);


    {- -------------------------------------------
  (1.1) (ここが dtos の場合の処理)
        ---------------------------------------- -}

      // dtos
      __ ldf(FloatRegisterImpl::D, Rclass, Roffset, Ftos_d);
      __ push(dtos);
      if (!is_static) {
        patch_bytecode(Bytecodes::_fast_dgetfield, G3_scratch, G4_scratch);
      }

  {- -------------------------------------------
  (1) ここで, volatile field だった場合のメモリバリア処理を行う (メモリバリアが必要な環境の場合).

      (なお, 以下のコメントにある通り, 
      それぞれのケースの遅延スロットで volatile かどうかのチェック(tst(Lscratch))を行っている.
      具体的には, ConstantPoolCacheEntry::volatileField のチェックをしている.
      そのため, この段階では volatile チェックは終わっている.)

      以下のようなコードを生成.
      「チェック結果に基づき, もし volatile であれば, volatile_barrier() が生成したメモリバリアコードを実行する.
      volatile でなければ何もしない (exit までジャンプする)」
      ---------------------------------------- -}

      __ bind(checkVolatile);
      if (__ membar_has_effect(membar_bits)) {
        // __ tst(Lscratch); executed in delay slot
        __ br(Assembler::zero, false, Assembler::pt, exit);
        __ delayed()->nop();
        volatile_barrier(membar_bits);
      }

      __ bind(exit);
    }

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