Top


定義場所(file name)

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

名前(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;
        case T_LONG:    name = "jni_fast_GetLongField";    break;
        default:        ShouldNotReachHere();
      }
      ResourceMark rm;
      BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE);
      CodeBuffer cbuf(blob);
      MacroAssembler* masm = new MacroAssembler(&cbuf);

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

      address fast_entry = __ pc();

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

      Label slow;

      ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr());
      __ mov32 (rcounter, counter);
      __ mov   (robj, c_rarg1);
      __ testb (rcounter, 1);
      __ jcc (Assembler::notZero, slow);

  {- -------------------------------------------
  (1) コード生成:
      「(MP 環境であれば, ) robj を "robj ^ rcounter ^ rcounter" という値に更新する.」
      (実質上何も変わらないが, rcounter に対する data dependency が生じる)
      ---------------------------------------- -}

      if (os::is_MP()) {
        __ xorptr(robj, rcounter);
        __ xorptr(robj, rcounter);                   // obj, since
                                                    // robj ^ rcounter ^ rcounter == robj
                                                    // robj is data dependent on rcounter.
      }

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

      __ movptr(robj, Address(robj, 0));             // *obj
      __ mov   (roffset, c_rarg2);
      __ shrptr(roffset, 2);                         // offset

      assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
      speculative_load_pclist[count] = __ pc();
      switch (type) {
        case T_BOOLEAN: __ movzbl (rax, Address(robj, roffset, Address::times_1)); break;
        case T_BYTE:    __ movsbl (rax, Address(robj, roffset, Address::times_1)); break;
        case T_CHAR:    __ movzwl (rax, Address(robj, roffset, Address::times_1)); break;
        case T_SHORT:   __ movswl (rax, Address(robj, roffset, Address::times_1)); break;
        case T_INT:     __ movl   (rax, Address(robj, roffset, Address::times_1)); break;
        case T_LONG:    __ movq   (rax, Address(robj, roffset, Address::times_1)); break;
        default:        ShouldNotReachHere();
      }

  {- -------------------------------------------
  (1) コード生成:
      「(MP 環境であれば SafepointSynchronize::safepoint_counter フィールドのアドレスを
         ロードしてきたフィールド値と2回 xorptr した後)
        再度 SafepointSynchronize::safepoint_counter の値を取得する.

        値が変わっていれば, slow にジャンプして slow case へフォールバック.
        変わっていなければ, このままリターンする.」

        (この xorptr も実質上何も変わらないが, ロードしてきたフィールド値に対する data dependency が生じる)
      ---------------------------------------- -}

      if (os::is_MP()) {
        __ lea(rcounter_addr, counter);
        // ca is data dependent on rax.
        __ xorptr(rcounter_addr, rax);
        __ xorptr(rcounter_addr, rax);
        __ cmpl (rcounter, Address(rcounter_addr, 0));
      } else {
        __ cmp32 (rcounter, counter);
      }
      __ jcc (Assembler::notEqual, slow);

      __ ret (0);

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

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

  {- -------------------------------------------
  (1) コード生成:
      「対応する jni_Get<Primitive>Field_addr を末尾呼び出しする.」
      ---------------------------------------- -}

      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;
        case T_LONG:    slow_case_addr = jni_GetLongField_addr();
      }
      // tail call
      __ jump (ExternalAddress(slow_case_addr));

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

      __ flush ();

      return fast_entry;
    }

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