Top


定義場所(file name)

hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp

名前(function name)

void JvmtiClassFileReconstituter::copy_bytecodes(methodHandle mh,
                                                 unsigned char* bytecodes) {

本体部(body)

  {- -------------------------------------------
  (1) (この関数では BytecodeStream を用いてバイトコードに対する iterate 処理を行う.
       JVM/fast bytecodes や breakpoint bytecode は辿る際には元々のバイトコードに変換される.)
      ---------------------------------------- -}

      // use a BytecodeStream to iterate over the bytecodes. JVM/fast bytecodes
      // and the breakpoint bytecode are converted to their original bytecodes.

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

      BytecodeStream bs(mh);

      unsigned char* p = bytecodes;
      Bytecodes::Code code;
      bool is_rewritten = instanceKlass::cast(mh->method_holder())->is_rewritten();

  {- -------------------------------------------
  (1) (以下の while ループで, bytecode 全部に対して処理が終わるまでループ)
      ---------------------------------------- -}

      while ((code = bs.next()) >= 0) {

    {- -------------------------------------------
  (1.1) (assert)
        ---------------------------------------- -}

        assert(Bytecodes::is_java_code(code), "sanity check");
        assert(code != Bytecodes::_breakpoint, "sanity check");

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

        // length of bytecode (mnemonic + operands)
        address bcp = bs.bcp();
        int     len = bs.instruction_size();
        assert(len > 0, "length must be > 0");

    {- -------------------------------------------
  (1.1) バイトコードの内容をコピーする (複数 byte あれば memcpy)
        ---------------------------------------- -}

        // copy the bytecodes
        *p = (unsigned char) (bs.is_wide()? Bytecodes::_wide : code);
        if (len > 1) {
          memcpy(p+1, bcp+1, len-1);
        }

    {- -------------------------------------------
  (1.1) get/put や invoke 命令については, リンク時に書き換えた場合には元の情報をコピーする.
        ---------------------------------------- -}

        // During linking the get/put and invoke instructions are rewritten
        // with an index into the constant pool cache. The original constant
        // pool index must be returned to caller.  Rewrite the index.
        if (is_rewritten && len >= 3) {
          switch (code) {
          case Bytecodes::_getstatic       :  // fall through
          case Bytecodes::_putstatic       :  // fall through
          case Bytecodes::_getfield        :  // fall through
          case Bytecodes::_putfield        :  // fall through
          case Bytecodes::_invokevirtual   :  // fall through
          case Bytecodes::_invokespecial   :  // fall through
          case Bytecodes::_invokestatic    :  // fall through
          case Bytecodes::_invokedynamic   :  // fall through
          case Bytecodes::_invokeinterface :
            assert(len == 3 || (code == Bytecodes::_invokeinterface && len ==5),
                   "sanity check");
            int cpci = Bytes::get_native_u2(bcp+1);
            bool is_invokedynamic = (EnableInvokeDynamic && code == Bytecodes::_invokedynamic);
            if (is_invokedynamic)
              cpci = Bytes::get_native_u4(bcp+1);
            // cache cannot be pre-fetched since some classes won't have it yet
            ConstantPoolCacheEntry* entry =
              mh->constants()->cache()->main_entry_at(cpci);
            int i = entry->constant_pool_index();
            assert(i < mh->constants()->length(), "sanity check");
            Bytes::put_Java_u2((address)(p+1), (u2)i);     // java byte ordering
            if (is_invokedynamic)  *(p+3) = *(p+4) = 0;
            break;
          }
        }

        p += len;
      }
    }

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