zoukankan      html  css  js  c++  java
  • jvm源码解读--11 ldc指令的解读

    写一个java文件

        public static void main(String[] args) {
            String str1="abc";
            String str2 ="abc";
            String str3=new String("abc");
            boolean b1= str1==str2;
            boolean b2= str1==str3;
    
        }

    查看字节码code

     0 ldc #4 <abc>
     2 astore_1
     3 ldc #4 <abc>
     5 astore_2
     6 new #5 <java/lang/String>
     9 dup
    10 ldc #4 <abc>
    12 invokespecial #6 <java/lang/String.<init>>
    15 astore_3
    16 aload_1
    17 aload_2
    18 if_acmpne 25 (+7)
    21 iconst_1
    22 goto 26 (+4)
    25 iconst_0
    26 istore 4
    28 aload_1
    29 aload_3
    30 if_acmpne 37 (+7)
    33 iconst_1
    34 goto 38 (+4)
    37 iconst_0
    38 istore 5
    40 getstatic #7 <java/lang/System.out>
    43 ldc #8 <helloworld!>

    能看待这个一个是ldc #4,其中#4的类型是

    JVM_CONSTANT_String

    然后对于String类的解析,会比较明白,先加载java/lang/String类,在生成oop对象,而ldc #4查看字节码的解析如下:

    void TemplateTable::ldc(bool wide) {
      transition(vtos, vtos);
      Label call_ldc, notFloat, notClass, Done;
    
      if (wide) {
        __ get_unsigned_2_byte_index_at_bcp(rbx, 1);
      } else {
        __ load_unsigned_byte(rbx, at_bcp(1));
      }
      __ get_cpool_and_tags(rcx, rax);
      const int base_offset = ConstantPool::header_size() * wordSize;
      const int tags_offset = Array<u1>::base_offset_in_bytes();
    
      // get type
      __ xorptr(rdx, rdx);
      __ movb(rdx, Address(rax, rbx, Address::times_1, tags_offset));
    
      // unresolved class - get the resolved class
      __ cmpl(rdx, JVM_CONSTANT_UnresolvedClass);
      __ jccb(Assembler::equal, call_ldc);
    
      // unresolved class in error (resolution failed) - call into runtime
      // so that the same error from first resolution attempt is thrown.
      __ cmpl(rdx, JVM_CONSTANT_UnresolvedClassInError);
      __ jccb(Assembler::equal, call_ldc);
    
      // resolved class - need to call vm to get java mirror of the class
      __ cmpl(rdx, JVM_CONSTANT_Class);
      __ jcc(Assembler::notEqual, notClass);
    
      __ bind(call_ldc);
      __ movl(rcx, wide);
      call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::ldc), rcx);
      __ push(atos);
      __ jmp(Done);
    
      __ bind(notClass);
      __ cmpl(rdx, JVM_CONSTANT_Float);
      __ jccb(Assembler::notEqual, notFloat);
      // ftos
      __ fld_s(    Address(rcx, rbx, Address::times_ptr, base_offset));
      __ push(ftos);
      __ jmp(Done);
    
      __ bind(notFloat);
    #ifdef ASSERT
      { Label L;
        __ cmpl(rdx, JVM_CONSTANT_Integer);
        __ jcc(Assembler::equal, L);
        // String and Object are rewritten to fast_aldc
        __ stop("unexpected tag type in ldc");
        __ bind(L);
      }
    #endif
      // itos JVM_CONSTANT_Integer only
      __ movl(rax, Address(rcx, rbx, Address::times_ptr, base_offset));
      __ push(itos);
      __ bind(Done);
    }

    就算加上了汇编完成的东西

    ----------------------------------------------------------------------
    ldc  18 ldc  [0x00000000033c7840, 0x00000000033c79a0]  352 bytes
    
    0x00000000033c7840: push   %rax
    0x00000000033c7841: jmpq   0x00000000033c7870
    0x00000000033c7846: sub    $0x8,%rsp
    0x00000000033c784a: vmovss %xmm0,(%rsp)
    0x00000000033c784f: jmpq   0x00000000033c7870
    0x00000000033c7854: sub    $0x10,%rsp
    0x00000000033c7858: vmovsd %xmm0,(%rsp)
    0x00000000033c785d: jmpq   0x00000000033c7870
    0x00000000033c7862: sub    $0x10,%rsp
    0x00000000033c7866: mov    %rax,(%rsp)
    0x00000000033c786a: jmpq   0x00000000033c7870
    0x00000000033c786f: push   %rax
    0x00000000033c7870: movzbl 0x1(%r13),%ebx
    0x00000000033c7875: mov    -0x18(%rbp),%rcx
    0x00000000033c7879: mov    0x8(%rcx),%rcx
    0x00000000033c787d: mov    0x8(%rcx),%rcx
    0x00000000033c7881: mov    0x8(%rcx),%rax
    0x00000000033c7885: movzbl 0x4(%rax,%rbx,1),%edx
    // unresolved class - get the resolved class
    __ cmpl(rdx, JVM_CONSTANT_UnresolvedClass);
    __ jccb(Assembler::equal, call_ldc);
    0x00000000033c788a: cmp    $0x64,%edx
    0x00000000033c788d: je     0x00000000033c789d
    // unresolved class in error state - call into runtime to throw the error
    // from the first resolution attempt
    __ cmpl(rdx, JVM_CONSTANT_UnresolvedClassInError);
    __ jccb(Assembler::equal, call_ldc);
    0x00000000033c788f: cmp    $0x67,%edx
    0x00000000033c7892: je     0x00000000033c789d
    // resolved class - need to call vm to get java mirror of the class
    __ cmpl(rdx, JVM_CONSTANT_Class);
    __ jcc(Assembler::notEqual, notClass);
    0x00000000033c7894: cmp    $0x7,%edx
    0x00000000033c7897: jne    0x00000000033c794d
    __ movl(c_rarg1, wide); wide=false
    0x00000000033c789d: mov    $0x0,%edx
    0x00000000033c78a2: callq  0x00000000033c78ac
    0x00000000033c78a7: jmpq   0x00000000033c7947
    0x00000000033c78ac: lea    0x8(%rsp),%rax
    0x00000000033c78b1: mov    %r13,-0x38(%rbp)
    0x00000000033c78b5: mov    %r15,%rcx
    0x00000000033c78b8: mov    %rbp,0x1e8(%r15)
    0x00000000033c78bf: mov    %rax,0x1d8(%r15)
    0x00000000033c78c6: sub    $0x20,%rsp
    0x00000000033c78ca: test   $0xf,%esp
    0x00000000033c78d0: je     0x00000000033c78e8
    0x00000000033c78d6: sub    $0x8,%rsp
    0x00000000033c78da: callq  0x000000006aad9cd0
    0x00000000033c78df: add    $0x8,%rsp
    0x00000000033c78e3: jmpq   0x00000000033c78ed
    0x00000000033c78e8: callq  0x000000006aad9cd0
    0x00000000033c78ed: add    $0x20,%rsp
    0x00000000033c78f1: movabs $0x0,%r10
    0x00000000033c78fb: mov    %r10,0x1d8(%r15)
    0x00000000033c7902: movabs $0x0,%r10
    0x00000000033c790c: mov    %r10,0x1e8(%r15)
    0x00000000033c7913: cmpq   $0x0,0x8(%r15)
    0x00000000033c791b: je     0x00000000033c7926
    0x00000000033c7921: jmpq   0x00000000033b07e0
    0x00000000033c7926: mov    0x238(%r15),%rax
    0x00000000033c792d: movabs $0x0,%r10
    0x00000000033c7937: mov    %r10,0x238(%r15)
    0x00000000033c793e: mov    -0x38(%rbp),%r13
    0x00000000033c7942: mov    -0x30(%rbp),%r14
    0x00000000033c7946: retq
    0x00000000033c7947: push   %rax
    0x00000000033c7948: jmpq   0x00000000033c796b
    __ bind(notClass);
    __ cmpl(rdx, JVM_CONSTANT_Float); 常量值为4
            __ jccb(Assembler::notEqual, notFloat);
    0x00000000033c794d: cmp    $0x4,%edx
    0x00000000033c7950: jne    0x00000000033c7966
    0x00000000033c7952: vmovss 0x50(%rcx,%rbx,8),%xmm0
    0x00000000033c7958: sub    $0x8,%rsp
    0x00000000033c795c: vmovss %xmm0,(%rsp)
    0x00000000033c7961: jmpq   0x00000000033c796b
    
    __ bind(notFloat);
    
    0x00000000033c7966: mov    0x50(%rcx,%rbx,8),%eax
    0x00000000033c796a: push   %rax
    
    //下一条指令取指
    0x00000000033c796b: movzbl 0x2(%r13),%ebx
    0x00000000033c7970: add    $0x2,%r13
    0x00000000033c7974: movabs $0x6b2143f0,%r10
    0x00000000033c797e: jmpq   *(%r10,%rbx,8)
    0x00000000033c7982: nopw   0x0(%rax,%rax,1)
    0x00000000033c7988: add    %al,(%rax)
    0x00000000033c798a: add    %al,(%rax)
    0x00000000033c798c: add    %al,(%rax)
    0x00000000033c798e: add    %al,(%rax)
    0x00000000033c7990: add    %al,(%rax)
    0x00000000033c7992: add    %al,(%rax)
    0x00000000033c7994: add    %al,(%rax)
    0x00000000033c7996: add    %al,(%rax)
    0x00000000033c7998: add    %al,(%rax)
    0x00000000033c799a: add    %al,(%rax)
    0x00000000033c799c: add    %al,(%rax)
    0x00000000033c799e: add    %al,(%rax)
    ----------------------------------------------------------------------

    也分析不出来,打断点始终打不到,对于ldc  加载类,却可以打到断点,真是迷惑,查了一圈看了一篇文章说会调用StringTable::intern

    文章链接:iizhihu.com/question/60778124

    但是也没说明白调用链,开头就直接说了

    给出以下逻辑

    查看源码也是在bytecodeInterpreter.cpp找到了这段内容

          CASE(_ldc_w):
          CASE(_ldc):
            {
              u2 index;
              bool wide = false;
              int incr = 2; // frequent case
              if (opcode == Bytecodes::_ldc) {
                index = pc[1];
              } else {
                index = Bytes::get_Java_u2(pc+1);
                incr = 3;
                wide = true;
              }
    
              ConstantPool* constants = METHOD->constants();
              switch (constants->tag_at(index).value()) {
              case JVM_CONSTANT_Integer:
                SET_STACK_INT(constants->int_at(index), 0);
                break;
    
              case JVM_CONSTANT_Float:
                SET_STACK_FLOAT(constants->float_at(index), 0);
                break;
    
              case JVM_CONSTANT_String:
                {
                  oop result = constants->resolved_references()->obj_at(index);
                  if (result == NULL) {
                    CALL_VM(InterpreterRuntime::resolve_ldc(THREAD, (Bytecodes::Code) opcode), handle_exception);
                    SET_STACK_OBJECT(THREAD->vm_result(), 0);
                    THREAD->set_vm_result(NULL);
                  } else {
                    VERIFY_OOP(result);
                    SET_STACK_OBJECT(result, 0);
                  }
                break;
                }
    
              case JVM_CONSTANT_Class:
                VERIFY_OOP(constants->resolved_klass_at(index)->java_mirror());
                SET_STACK_OBJECT(constants->resolved_klass_at(index)->java_mirror(), 0);
                break;
    
              case JVM_CONSTANT_UnresolvedClass:
              case JVM_CONSTANT_UnresolvedClassInError:
                CALL_VM(InterpreterRuntime::ldc(THREAD, wide), handle_exception);
                SET_STACK_OBJECT(THREAD->vm_result(), 0);
                THREAD->set_vm_result(NULL);
                break;
    
              default:  ShouldNotReachHere();
              }
              UPDATE_PC_AND_TOS_AND_CONTINUE(incr, 1);
            }

    这个在里面打不了断点呢,上便的逻辑一点都不清楚,如何是好? 这个cpp文件都是灰色的,最后有这个 #ifndef CC_INTERP ,感觉不是模板编译器,

    那么,参考知乎的文章,打了断点 发现bytecode 是fast_aldc,并且要加载的字符串是"system",与ldc 指令对上了呢,没想明白怎么出来的一个_fast_ldc指令,对于指令的解析,已经看过了没有对应的Constant String ,tag保存的类型为08的,最后还是让我发现了,hotspot在方法链接的时候将ldc 重写成了_fast_aldc,自己没看方法重写的代码,不知道呢

    为什么呢?其实这不怪你,因为这是在连接的时候重写了,自己没看这部分内容,看来还要补起来
    
    // Rewrites a method given the index_map information
    void Rewriter::scan_method(Method* method, bool reverse, bool* invokespecial_error) {
        ..
        case Bytecodes::_ldc:
        case Bytecodes::_fast_aldc:  // if reverse=true
            maybe_rewrite_ldc(bcp, prefix_length+1, false, reverse);
        ..
    }
    
    // Rewrite some ldc bytecodes to _fast_aldc
    void Rewriter::maybe_rewrite_ldc(address bcp, int offset, bool is_wide,
                                     bool reverse) {
        if (!reverse) {
            assert((*bcp) == (is_wide ? Bytecodes::_ldc_w : Bytecodes::_ldc), "not ldc bytecode");
            address p = bcp + offset;
            int cp_index = is_wide ? Bytes::get_Java_u2(p) : (u1)(*p);
            constantTag tag = _pool->tag_at(cp_index).value();
            /**
             *   bool is_method_handle() const { return _tag == JVM_CONSTANT_MethodHandle; }
             *     bool is_method_type() const { return _tag == JVM_CONSTANT_MethodType; }
             *     bool is_string() const { return _tag == JVM_CONSTANT_String; }
             */
    
            if (tag.is_method_handle() || tag.is_method_type() || tag.is_string()) {
    
                int ref_index = cp_entry_to_resolved_references(cp_index);
                if (is_wide) {
                    (*bcp) = Bytecodes::_fast_aldc_w;
                    assert(ref_index == (u2)ref_index, "index overflow");
                    Bytes::put_native_u2(p, ref_index);
                } else {
                    (*bcp) = Bytecodes::_fast_aldc;//将ldc转化成_fast_aldc,这个你不看到这里,怎么也跟踪不到呢??
                    assert(ref_index == (u1)ref_index, "index overflow");
                    (*p) = (u1)ref_index;
                }
            }
        } else {
            Bytecodes::Code rewritten_bc =
                    (is_wide ? Bytecodes::_fast_aldc_w : Bytecodes::_fast_aldc);
            if ((*bcp) == rewritten_bc) {
                address p = bcp + offset;
                int ref_index = is_wide ? Bytes::get_native_u2(p) : (u1)(*p);
                int pool_index = resolved_references_entry_to_pool_index(ref_index);
                if (is_wide) {
                    (*bcp) = Bytecodes::_ldc_w;
                    assert(pool_index == (u2)pool_index, "index overflow");
                    Bytes::put_Java_u2(p, pool_index);
                } else {
                    (*bcp) = Bytecodes::_ldc;
                    assert(pool_index == (u1)pool_index, "index overflow");
                    (*p) = (u1)pool_index;
                }
            }
        }
    }

    接着就是

    那看ldc和fast_aldc的汇编器,这里面写着生成oop对象

    // Fast path for caching oop constants.
    void TemplateTable::fast_aldc(bool wide) {
      transition(vtos, atos);
    
      Register result = rax;
      Register tmp = rdx;
      int index_size = wide ? sizeof(u2) : sizeof(u1);
    
      Label resolved;
    
      // We are resolved if the resolved reference cache entry contains a
      // non-null object (String, MethodType, etc.)
      assert_different_registers(result, tmp);
      __ get_cache_index_at_bcp(tmp, 1, index_size);
      __ load_resolved_reference_at_index(result, tmp);
      __ testl(result, result);
      __ jcc(Assembler::notZero, resolved);
    
      address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
    
      // first time invocation - must resolve first
      __ movl(tmp, (int)bytecode());
      __ call_VM(result, entry, tmp);
    
      __ bind(resolved);
    
      if (VerifyOops) {
        __ verify_oop(result);
      }
    }

    如下

    oop Bytecode_loadconstant::resolve_constant(TRAPS) const {
      assert(_method.not_null(), "must supply method to resolve constant");
      int index = raw_index();
      ConstantPool* constants = _method->constants();
      if (has_cache_index()) {
        return constants->resolve_cached_constant_at(index, THREAD);
      } else {
        return constants->resolve_constant_at(index, THREAD);
      }
    }
    ---------------
      oop resolve_cached_constant_at(int cache_index, TRAPS) {
        constantPoolHandle h_this(THREAD, this);
        return resolve_constant_at_impl(h_this, _no_index_sentinel, cache_index, THREAD);
      }
    ---------------
    // Called to resolve constants in the constant pool and return an oop.
    // Some constant pool entries cache their resolved oop. This is also
    // called to create oops from constants to use in arguments for invokedynamic
    oop ConstantPool::resolve_constant_at_impl(constantPoolHandle this_oop, int index, int cache_index, TRAPS) {
      oop result_oop = NULL;
      Handle throw_exception;
    
      if (cache_index == _possible_index_sentinel) {
        // It is possible that this constant is one which is cached in the objects.
        // We'll do a linear search.  This should be OK because this usage is rare.
        assert(index > 0, "valid index");
        cache_index = this_oop->cp_to_object_index(index);
      }
      assert(cache_index == _no_index_sentinel || cache_index >= 0, "");
      assert(index == _no_index_sentinel || index >= 0, "");
    
      if (cache_index >= 0) {
        result_oop = this_oop->resolved_references()->obj_at(cache_index);
        if (result_oop != NULL) {
          return result_oop;
          // That was easy...
        }
        index = this_oop->object_to_cp_index(cache_index);
      }
    
      jvalue prim_value;  // temp used only in a few cases below
    
      int tag_value = this_oop->tag_at(index).value();
    
      switch (tag_value) {
    
      case JVM_CONSTANT_UnresolvedClass:
      case JVM_CONSTANT_UnresolvedClassInError:
      case JVM_CONSTANT_Class:
        {
          assert(cache_index == _no_index_sentinel, "should not have been set");
          Klass* resolved = klass_at_impl(this_oop, index, CHECK_NULL);
          // ldc wants the java mirror.
          result_oop = resolved->java_mirror();
          break;
        }
    
      case JVM_CONSTANT_String:
        assert(cache_index != _no_index_sentinel, "should have been set");
        if (this_oop->is_pseudo_string_at(index)) {
          result_oop = this_oop->pseudo_string_at(index, cache_index);
          break;
        }
        result_oop = string_at_impl(this_oop, index, cache_index, CHECK_NULL);
        break;
    
      case JVM_CONSTANT_MethodHandleInError:
      case JVM_CONSTANT_MethodTypeInError:
        {
          Symbol* error = SystemDictionary::find_resolution_error(this_oop, index);
          guarantee(error != (Symbol*)NULL, "tag mismatch with resolution error table");
          ResourceMark rm;
          THROW_MSG_0(error, "");
          break;
        }
    
      case JVM_CONSTANT_MethodHandle:
        {
          int ref_kind                 = this_oop->method_handle_ref_kind_at(index);
          int callee_index             = this_oop->method_handle_klass_index_at(index);
          Symbol*  name =      this_oop->method_handle_name_ref_at(index);
          Symbol*  signature = this_oop->method_handle_signature_ref_at(index);
          if (PrintMiscellaneous)
            tty->print_cr("resolve JVM_CONSTANT_MethodHandle:%d [%d/%d/%d] %s.%s",
                          ref_kind, index, this_oop->method_handle_index_at(index),
                          callee_index, name->as_C_string(), signature->as_C_string());
          KlassHandle callee;
          { Klass* k = klass_at_impl(this_oop, callee_index, CHECK_NULL);
            callee = KlassHandle(THREAD, k);
          }
          KlassHandle klass(THREAD, this_oop->pool_holder());
          Handle value = SystemDictionary::link_method_handle_constant(klass, ref_kind,
                                                                       callee, name, signature,
                                                                       THREAD);
          result_oop = value();
          if (HAS_PENDING_EXCEPTION) {
            save_and_throw_exception(this_oop, index, tag_value, CHECK_NULL);
          }
          break;
        }
    
      case JVM_CONSTANT_MethodType:
        {
          Symbol*  signature = this_oop->method_type_signature_at(index);
          if (PrintMiscellaneous)
            tty->print_cr("resolve JVM_CONSTANT_MethodType [%d/%d] %s",
                          index, this_oop->method_type_index_at(index),
                          signature->as_C_string());
          KlassHandle klass(THREAD, this_oop->pool_holder());
          Handle value = SystemDictionary::find_method_handle_type(signature, klass, THREAD);
          result_oop = value();
          if (HAS_PENDING_EXCEPTION) {
            save_and_throw_exception(this_oop, index, tag_value, CHECK_NULL);
          }
          break;
        }
    
      case JVM_CONSTANT_Integer:
        assert(cache_index == _no_index_sentinel, "should not have been set");
        prim_value.i = this_oop->int_at(index);
        result_oop = java_lang_boxing_object::create(T_INT, &prim_value, CHECK_NULL);
        break;
    
      case JVM_CONSTANT_Float:
        assert(cache_index == _no_index_sentinel, "should not have been set");
        prim_value.f = this_oop->float_at(index);
        result_oop = java_lang_boxing_object::create(T_FLOAT, &prim_value, CHECK_NULL);
        break;
    
      case JVM_CONSTANT_Long:
        assert(cache_index == _no_index_sentinel, "should not have been set");
        prim_value.j = this_oop->long_at(index);
        result_oop = java_lang_boxing_object::create(T_LONG, &prim_value, CHECK_NULL);
        break;
    
      case JVM_CONSTANT_Double:
        assert(cache_index == _no_index_sentinel, "should not have been set");
        prim_value.d = this_oop->double_at(index);
        result_oop = java_lang_boxing_object::create(T_DOUBLE, &prim_value, CHECK_NULL);
        break;
    
      default:
        DEBUG_ONLY( tty->print_cr("*** %p: tag at CP[%d/%d] = %d",
                                  this_oop(), index, cache_index, tag_value) );
        assert(false, "unexpected constant tag");
        break;
      }
    
      if (cache_index >= 0) {
        // Cache the oop here also.
        Handle result_handle(THREAD, result_oop);
        MonitorLockerEx ml(this_oop->lock());  // don't know if we really need this
        oop result = this_oop->resolved_references()->obj_at(cache_index);
        // Benign race condition:  resolved_references may already be filled in while we were trying to lock.
        // The important thing here is that all threads pick up the same result.
        // It doesn't matter which racing thread wins, as long as only one
        // result is used by all threads, and all future queries.
        // That result may be either a resolved constant or a failure exception.
        if (result == NULL) {
          this_oop->resolved_references()->obj_at_put(cache_index, result_handle());
          return result_handle();
        } else {
          // Return the winning thread's result.  This can be different than
          // result_handle() for MethodHandles.
          return result;
        }
      } else {
        return result_oop;
      }
    }
    -------------------
    oop ConstantPool::string_at_impl(constantPoolHandle this_oop, int which, int obj_index, TRAPS) {
      // If the string has already been interned, this entry will be non-null
      oop str = this_oop->resolved_references()->obj_at(obj_index);
      if (str != NULL) return str;
      Symbol* sym = this_oop->unresolved_string_at(which);
      str = StringTable::intern(sym, CHECK_(NULL));
      this_oop->string_at_put(which, obj_index, str);
      assert(java_lang_String::is_instance(str), "must be string");
      return str;
    }
    -----
    oop StringTable::intern(Symbol* symbol, TRAPS) {
      if (symbol == NULL) return NULL;
      ResourceMark rm(THREAD);
      int length;
      jchar* chars = symbol->as_unicode(length);
      Handle string;
      oop result = intern(string, chars, length, CHECK_NULL);
      return result;
    }
    -----
    oop StringTable::intern(Handle string_or_null, jchar* name,
                            int len, TRAPS) {
      unsigned int hashValue = hash_string(name, len);
      int index = the_table()->hash_to_index(hashValue);
      oop found_string = the_table()->lookup(index, name, len, hashValue);
    
      // Found
      if (found_string != NULL) return found_string;
    
      debug_only(StableMemoryChecker smc(name, len * sizeof(name[0])));
      assert(!Universe::heap()->is_in_reserved(name),
             "proposed name of symbol must be stable");
    
      Handle string;
      // try to reuse the string if possible
      if (!string_or_null.is_null()) {
        string = string_or_null;
      } else {
        string = java_lang_String::create_from_unicode(name, len, CHECK_NULL);
      }
    
      // Grab the StringTable_lock before getting the_table() because it could
      // change at safepoint.
      MutexLocker ml(StringTable_lock, THREAD);
    
      // Otherwise, add to symbol to table
      return the_table()->basic_add(index, string, name, len,
                                    hashValue, CHECK_NULL);
    }
    -----
    oop StringTable::basic_add(int index_arg, Handle string, jchar* name,
                               int len, unsigned int hashValue_arg, TRAPS) {
    
      assert(java_lang_String::equals(string(), name, len),
             "string must be properly initialized");
      // Cannot hit a safepoint in this function because the "this" pointer can move.
      No_Safepoint_Verifier nsv;
    
      // Check if the symbol table has been rehashed, if so, need to recalculate
      // the hash value and index before second lookup.
      unsigned int hashValue;
      int index;
      if (use_alternate_hashcode()) {
        hashValue = hash_string(name, len);
        index = hash_to_index(hashValue);
      } else {
        hashValue = hashValue_arg;
        index = index_arg;
      }
    
      // Since look-up was done lock-free, we need to check if another
      // thread beat us in the race to insert the symbol.
    
      oop test = lookup(index, name, len, hashValue); // calls lookup(u1*, int)
      if (test != NULL) {
        // Entry already added
        return test;
      }
    
      HashtableEntry<oop, mtSymbol>* entry = new_entry(hashValue, string());
      add_entry(index, entry);
      return string();
    }

    这下下就清楚了,这是气人,你重写代码,怎么不和我说一下呢

  • 相关阅读:
    轮播图2
    点击按钮切换轮播图
    轮播图
    2016.5.5_十进制转二进制【ABAP】
    2016.4.26_longtext长文本【ABAP】
    2016.4.26_动态内表【ABAP】
    2016.4.26_下载abap代码【ABAP】
    2016.4.15_debug小技巧【ABAP】
    2016.4.1_js向controller传数据【笔记】
    2016.3.21_TABLE CONTROL【ABAP】
  • 原文地址:https://www.cnblogs.com/zytcomeon/p/14699803.html
Copyright © 2011-2022 走看看