Chinaunix首页 | 论坛 | 博客
  • 博客访问: 186133
  • 博文数量: 89
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 828
  • 用 户 组: 普通用户
  • 注册时间: 2013-10-08 10:44
文章分类
文章存档

2014年(9)

2013年(80)

我的朋友

分类: Java

2013-11-15 16:16:47

Hotspot主要有两种解释器,而下面我们主要讨论的是 Template Intepreter也叫asm interprete解释器, 文章下面的介绍基本都是基于template解释器


我们举一个invokespecial的例子,下面是templateTable方法解释invokespecial的代码


[cpp] view plaincopy
void TemplateTable::invokespecial(int byte_no) {  
  transition(vtos, vtos);  
  assert(byte_no == f1_byte, "use this argument");  
  prepare_invoke(rbx, noreg, byte_no);  
  // do the call  
  __ verify_oop(rbx);  
  __ profile_call(rax);  
  __ jump_from_interpreted(rbx, rax);  
}  
函数prepare_invoke
函数prepare_invoke的层级调用关系


TemplateTable::prepare_invoke


         -> TemplateTable::load_invoke_cp_cache_entry


                   -> TemplateTable::resolve_cache_and_index
在函数中resolve_cache_and_index可以看到


1. 首先先检查constantpoolcache,是否将方法指针保存到到线程的constantpoolcache里,如果有在方法里会使用jcc跳转到Label resolved去,而Lable resolved 在方法第一次运行结束后bind到函数的末尾。


2. 如果cache里没有那么会尝试用interpreterRuntime:resolve_invoke去找到正确的method, 并保存到constant pool cache 里


[cpp] view plaincopy
case Bytecodes::_invokevirtual:  
case Bytecodes::_invokespecial:  
case Bytecodes::_invokestatic:  
case Bytecodes::_invokeinterface:  
  entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke);  
  break;  


而函数
interpreterRuntime:resolve_invoke
         -->LinkResolver::resolve_invoke
                -->LinkResolver::resolve_special_call
                       -->LinkResolver::linktime_resolve_special_method
                               -->LinkResolver::resolve_method
不论什么调用方式,最后都会调用LinkResolver::resolve_method 找到真实的调用方法,通过runtime_resolve_special_method把method指针作为methodhandle存放到CallInfo 中传回InterperterRuntime::resolve_invoke中,同时在CallInfo::set_common当设置-Xcomp情况下,决定是否需要编译方法。


我们可以看到方法prepare_invoke,已经找到了methodoop指针并且存放到寄存器rbx中


函数jump_from_interpreted
[cpp] view plaincopy
void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) {  
  prepare_to_jump_from_interpreted();  
  
  if (JvmtiExport::can_post_interpreter_events()) {  
    Label run_compiled_code;  
    // JVMTI events, such as single-stepping, are implemented partly by avoiding running  
    // compiled code in threads for which the event is enabled.  Check here for  
    // interp_only_mode if these events CAN be enabled.  
    get_thread(temp);  
    // interp_only is an int, on little endian it is sufficient to test the byte only  
    // Is a cmpl faster (ce  
    cmpb(Address(temp, JavaThread::interp_only_mode_offset()), 0);  
    jcc(Assembler::zero, run_compiled_code);  
    jmp(Address(method, methodOopDesc::interpreter_entry_offset()));  
    bind(run_compiled_code);  
  }  
  
  jmp(Address(method, methodOopDesc::from_interpreted_offset()));  
  
}  
我们看到跳转到了methodoop中的_from_interpreted_entry,也就是在前面的博客里(java JNI (四) 初始化JNI方法)说的generate_native_entry 中




在这篇博客并没有太多的涉及到native方法的调用,而是asm解释器在解释一个方法的时候如何link到所对应method,并且找到处理method的entry。
阅读(772) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~