Top


定義場所(file name)

hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp

名前(function name)

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

本体部(body)

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

      transition(vtos, vtos);

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

      const Register cache = rcx;
      const Register index = rdx;
      const Register obj   = c_rarg3;
      const Register off   = rbx;
      const Register flags = rax;
      const Register bc = c_rarg3; // uses same reg as obj, so don't mix them

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

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

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

      jvmti_post_field_access(cache, index, is_static, false);

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

      load_field_cp_cache_entry(obj, cache, index, off, flags, is_static);

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

      if (!is_static) {
        // obj is on the stack
        pop_and_check_object(obj);
      }

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

      const Address field(obj, off, Address::times_1);

      Label Done, notByte, notInt, notShort, notChar,
                  notLong, notFloat, notObj, notDouble;

  {- -------------------------------------------
  (1) CPCache のエントリから型情報を取り出す.
      ---------------------------------------- -}

      __ shrl(flags, ConstantPoolCacheEntry::tosBits);

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

      assert(btos == 0, "change code, btos != 0");

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

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

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

      __ andl(flags, 0x0F);
      __ jcc(Assembler::notZero, notByte);

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

      // btos
      __ load_signed_byte(rax, field);
      __ push(btos);
      // Rewrite bytecode to be faster
      if (!is_static) {
        patch_bytecode(Bytecodes::_fast_bgetfield, bc, rbx);
      }
      __ jmp(Done);

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

      __ bind(notByte);
      __ cmpl(flags, atos);
      __ jcc(Assembler::notEqual, notObj);

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

      // atos
      __ load_heap_oop(rax, field);
      __ push(atos);
      if (!is_static) {
        patch_bytecode(Bytecodes::_fast_agetfield, bc, rbx);
      }
      __ jmp(Done);

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

      __ bind(notObj);
      __ cmpl(flags, itos);
      __ jcc(Assembler::notEqual, notInt);

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

      // itos
      __ movl(rax, field);
      __ push(itos);
      // Rewrite bytecode to be faster
      if (!is_static) {
        patch_bytecode(Bytecodes::_fast_igetfield, bc, rbx);
      }
      __ jmp(Done);

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

      __ bind(notInt);
      __ cmpl(flags, ctos);
      __ jcc(Assembler::notEqual, notChar);

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

      // ctos
      __ load_unsigned_short(rax, field);
      __ push(ctos);
      // Rewrite bytecode to be faster
      if (!is_static) {
        patch_bytecode(Bytecodes::_fast_cgetfield, bc, rbx);
      }
      __ jmp(Done);

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

      __ bind(notChar);
      __ cmpl(flags, stos);
      __ jcc(Assembler::notEqual, notShort);

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

      // stos
      __ load_signed_short(rax, field);
      __ push(stos);
      // Rewrite bytecode to be faster
      if (!is_static) {
        patch_bytecode(Bytecodes::_fast_sgetfield, bc, rbx);
      }
      __ jmp(Done);

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

      __ bind(notShort);
      __ cmpl(flags, ltos);
      __ jcc(Assembler::notEqual, notLong);

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

      // ltos
      __ movq(rax, field);
      __ push(ltos);
      // Rewrite bytecode to be faster
      if (!is_static) {
        patch_bytecode(Bytecodes::_fast_lgetfield, bc, rbx);
      }
      __ jmp(Done);

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

      __ bind(notLong);
      __ cmpl(flags, ftos);
      __ jcc(Assembler::notEqual, notFloat);

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

      // ftos
      __ movflt(xmm0, field);
      __ push(ftos);
      // Rewrite bytecode to be faster
      if (!is_static) {
        patch_bytecode(Bytecodes::_fast_fgetfield, bc, rbx);
      }
      __ jmp(Done);

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

      __ bind(notFloat);
    #ifdef ASSERT
      __ cmpl(flags, dtos);
      __ jcc(Assembler::notEqual, notDouble);
    #endif

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

      // dtos
      __ movdbl(xmm0, field);
      __ push(dtos);
      // Rewrite bytecode to be faster
      if (!is_static) {
        patch_bytecode(Bytecodes::_fast_dgetfield, bc, rbx);
      }
    #ifdef ASSERT
      __ jmp(Done);

      __ bind(notDouble);
      __ stop("Bad state");
    #endif

  {- -------------------------------------------
  (1) (ここで終了)
      (なお, 現状の x86 ではメモリバリアは不要なので張っていない)
      ---------------------------------------- -}

      __ bind(Done);
      // [jk] not needed currently
      // volatile_barrier(Assembler::Membar_mask_bits(Assembler::LoadLoad |
      //                                              Assembler::LoadStore));
    }

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