Top


定義場所(file name)

hotspot/src/share/vm/classfile/classFileParser.cpp

名前(function name)

void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int length, TRAPS) {

本体部(body)

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

      // Use a local copy of ClassFileStream. It helps the C++ compiler to optimize
      // this function (_current can be allocated in a register, with scalar
      // replacement of aggregates). The _current pointer is copied back to
      // stream() when this function returns. DON'T call another method within
      // this method that uses stream().
      ClassFileStream* cfs0 = stream();
      ClassFileStream cfs1 = *cfs0;
      ClassFileStream* cfs = &cfs1;
    #ifdef ASSERT
      assert(cfs->allocated_on_stack(),"should be local");
      u1* old_current = cfs0->current();
    #endif

      // Used for batching symbol allocations.
      const char* names[SymbolTable::symbol_alloc_batch_size];
      int lengths[SymbolTable::symbol_alloc_batch_size];
      int indices[SymbolTable::symbol_alloc_batch_size];
      unsigned int hashValues[SymbolTable::symbol_alloc_batch_size];
      int names_count = 0;

  {- -------------------------------------------
  (1) 以下の for ループ中で constant pool の要素全部に対して iterate.
      各要素の先頭の tag を見て対応するエントリ用のパース処理を行い,
      constantPoolOop の klass_index_at_put(), field_at_put(), method_at_put() 等のメソッドでパース結果を格納していく.

      (constantPoolOop の klass_index_at_put(), field_at_put(), method_at_put(), 等のメソッドでは,
      格納している各要素の種別を示す tags 配列にそれぞれの対応する種別を設定し, さらに
      constantPoolOop オブジェクトの末尾(のフィールド宣言もされてない領域)に値を登録する)

      (なお, klass_index_at_put() と string_index_at_put() については, ここの段階では一時的な登録.
       後の verify の処理で設定し直す)

      (また JVM_CONSTANT_Utf8 については, SymbolTable に新しいシンボルとして登録している.
       これは, 処理途中である程度たまったらバッチ的に登録しており, 
       処理終了後に未登録のものをまとめて登録している)

      (#TODO)
      ---------------------------------------- -}

      // parsing  Index 0 is unused
      for (int index = 1; index < length; index++) {
        // Each of the following case guarantees one more byte in the stream
        // for the following tag or the access_flags following constant pool,
        // so we don't need bounds-check for reading tag.
        u1 tag = cfs->get_u1_fast();
        switch (tag) {
          case JVM_CONSTANT_Class :
            {
              cfs->guarantee_more(3, CHECK);  // name_index, tag/access_flags
              u2 name_index = cfs->get_u2_fast();
              cp->klass_index_at_put(index, name_index);
            }
            break;
          case JVM_CONSTANT_Fieldref :
            {
              cfs->guarantee_more(5, CHECK);  // class_index, name_and_type_index, tag/access_flags
              u2 class_index = cfs->get_u2_fast();
              u2 name_and_type_index = cfs->get_u2_fast();
              cp->field_at_put(index, class_index, name_and_type_index);
            }
            break;
          case JVM_CONSTANT_Methodref :
            {
              cfs->guarantee_more(5, CHECK);  // class_index, name_and_type_index, tag/access_flags
              u2 class_index = cfs->get_u2_fast();
              u2 name_and_type_index = cfs->get_u2_fast();
              cp->method_at_put(index, class_index, name_and_type_index);
            }
            break;
          case JVM_CONSTANT_InterfaceMethodref :
            {
              cfs->guarantee_more(5, CHECK);  // class_index, name_and_type_index, tag/access_flags
              u2 class_index = cfs->get_u2_fast();
              u2 name_and_type_index = cfs->get_u2_fast();
              cp->interface_method_at_put(index, class_index, name_and_type_index);
            }
            break;
          case JVM_CONSTANT_String :
            {
              cfs->guarantee_more(3, CHECK);  // string_index, tag/access_flags
              u2 string_index = cfs->get_u2_fast();
              cp->string_index_at_put(index, string_index);
            }
            break;
          case JVM_CONSTANT_MethodHandle :
          case JVM_CONSTANT_MethodType :
            if (_major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
              classfile_parse_error(
                "Class file version does not support constant tag %u in class file %s",
                tag, CHECK);
            }
            if (!EnableInvokeDynamic) {
              classfile_parse_error(
                "This JVM does not support constant tag %u in class file %s",
                tag, CHECK);
            }
            if (tag == JVM_CONSTANT_MethodHandle) {
              cfs->guarantee_more(4, CHECK);  // ref_kind, method_index, tag/access_flags
              u1 ref_kind = cfs->get_u1_fast();
              u2 method_index = cfs->get_u2_fast();
              cp->method_handle_index_at_put(index, ref_kind, method_index);
            } else if (tag == JVM_CONSTANT_MethodType) {
              cfs->guarantee_more(3, CHECK);  // signature_index, tag/access_flags
              u2 signature_index = cfs->get_u2_fast();
              cp->method_type_index_at_put(index, signature_index);
            } else {
              ShouldNotReachHere();
            }
            break;
          case JVM_CONSTANT_InvokeDynamic :
            {
              if (_major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
                classfile_parse_error(
                  "Class file version does not support constant tag %u in class file %s",
                  tag, CHECK);
              }
              if (!EnableInvokeDynamic) {
                classfile_parse_error(
                  "This JVM does not support constant tag %u in class file %s",
                  tag, CHECK);
              }
              cfs->guarantee_more(5, CHECK);  // bsm_index, nt, tag/access_flags
              u2 bootstrap_specifier_index = cfs->get_u2_fast();
              u2 name_and_type_index = cfs->get_u2_fast();
              if (_max_bootstrap_specifier_index < (int) bootstrap_specifier_index)
                _max_bootstrap_specifier_index = (int) bootstrap_specifier_index;  // collect for later
              cp->invoke_dynamic_at_put(index, bootstrap_specifier_index, name_and_type_index);
            }
            break;
          case JVM_CONSTANT_Integer :
            {
              cfs->guarantee_more(5, CHECK);  // bytes, tag/access_flags
              u4 bytes = cfs->get_u4_fast();
              cp->int_at_put(index, (jint) bytes);
            }
            break;
          case JVM_CONSTANT_Float :
            {
              cfs->guarantee_more(5, CHECK);  // bytes, tag/access_flags
              u4 bytes = cfs->get_u4_fast();
              cp->float_at_put(index, *(jfloat*)&bytes);
            }
            break;
          case JVM_CONSTANT_Long :
            // A mangled type might cause you to overrun allocated memory
            guarantee_property(index+1 < length,
                               "Invalid constant pool entry %u in class file %s",
                               index, CHECK);
            {
              cfs->guarantee_more(9, CHECK);  // bytes, tag/access_flags
              u8 bytes = cfs->get_u8_fast();
              cp->long_at_put(index, bytes);
            }
            index++;   // Skip entry following eigth-byte constant, see JVM book p. 98
            break;
          case JVM_CONSTANT_Double :
            // A mangled type might cause you to overrun allocated memory
            guarantee_property(index+1 < length,
                               "Invalid constant pool entry %u in class file %s",
                               index, CHECK);
            {
              cfs->guarantee_more(9, CHECK);  // bytes, tag/access_flags
              u8 bytes = cfs->get_u8_fast();
              cp->double_at_put(index, *(jdouble*)&bytes);
            }
            index++;   // Skip entry following eigth-byte constant, see JVM book p. 98
            break;
          case JVM_CONSTANT_NameAndType :
            {
              cfs->guarantee_more(5, CHECK);  // name_index, signature_index, tag/access_flags
              u2 name_index = cfs->get_u2_fast();
              u2 signature_index = cfs->get_u2_fast();
              cp->name_and_type_at_put(index, name_index, signature_index);
            }
            break;
          case JVM_CONSTANT_Utf8 :
            {
              cfs->guarantee_more(2, CHECK);  // utf8_length
              u2  utf8_length = cfs->get_u2_fast();
              u1* utf8_buffer = cfs->get_u1_buffer();
              assert(utf8_buffer != NULL, "null utf8 buffer");
              // Got utf8 string, guarantee utf8_length+1 bytes, set stream position forward.
              cfs->guarantee_more(utf8_length+1, CHECK);  // utf8 string, tag/access_flags
              cfs->skip_u1_fast(utf8_length);

              // Before storing the symbol, make sure it's legal
              if (_need_verify) {
                verify_legal_utf8((unsigned char*)utf8_buffer, utf8_length, CHECK);
              }

              if (EnableInvokeDynamic && has_cp_patch_at(index)) {
                Handle patch = clear_cp_patch_at(index);
                guarantee_property(java_lang_String::is_instance(patch()),
                                   "Illegal utf8 patch at %d in class file %s",
                                   index, CHECK);
                char* str = java_lang_String::as_utf8_string(patch());
                // (could use java_lang_String::as_symbol instead, but might as well batch them)
                utf8_buffer = (u1*) str;
                utf8_length = (int) strlen(str);
              }

              unsigned int hash;
              Symbol* result = SymbolTable::lookup_only((char*)utf8_buffer, utf8_length, hash);
              if (result == NULL) {
                names[names_count] = (char*)utf8_buffer;
                lengths[names_count] = utf8_length;
                indices[names_count] = index;
                hashValues[names_count++] = hash;
                if (names_count == SymbolTable::symbol_alloc_batch_size) {
                  SymbolTable::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK);
                  names_count = 0;
                }
              } else {
                cp->symbol_at_put(index, result);
              }
            }
            break;
          default:
            classfile_parse_error(
              "Unknown constant tag %u in class file %s", tag, CHECK);
            break;
        }
      }

  {- -------------------------------------------
  (1) 見つかった JVM_CONSTANT_Utf8 要素 (の中でまだ SymbolTable に登録していないもの) を登録しておく.
      ---------------------------------------- -}

      // Allocate the remaining symbols
      if (names_count > 0) {
        SymbolTable::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK);
      }

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

      // Copy _current pointer of local copy back to stream().
    #ifdef ASSERT
      assert(cfs0->current() == old_current, "non-exclusive use of stream()");
    #endif
      cfs0->set_current(cfs1.current());

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