GET_INST_OPCODE(ip)                 @ extract opcode from rINST    
  •     GOTO_OPCODE(ip)                     @ jump to next instruction    
  •     . . .    
  •     
  • #define rPC     r4    
  • #define rFP     r5    
  • #define rSELF   r6    
  • #define rINST   r7    
  • #define rIBASE  r8    
  •   非jit的情况下,先是FETCH_INST把pc的指令加载到rINST寄存器,之后GET_INST_OPCODE获得操作码 and     _reg, rINST, #255,是把rINST的低16位给ip寄存器,GOTO_OPCODE跳转到对应的地址。

      #define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6

      rIBASE 指向的curHandlerTable是跳转表的首地址,GOTO_OPCODE(ip)就将pc的地址指向该指令对应的操作码所在的跳转表地址。

    C++代码
    1. static Thread* allocThread(int interpStackSize)    
    2. #ifndef DVM_NO_ASM_INTERP    
    3.     thread->mainHandlerTable = dvmAsmInstructionStart;    
    4.     thread->altHandlerTable = dvmAsmAltInstructionStart;    
    5.     thread->interpBreak.ctl.curHandlerTable = thread->mainHandlerTable;    
    6. #endif    

      可见dvmAsmInstructionStart就是跳转表的入口,定义在dvmMterpStdRun里,

      你可以在这里找到所有的Java字节码的指令对应的解释器代码。

      比如new操作符对应的代码如下,先加载Thread.interpSave.methodClassDex,这是一个DvmDex指针,随后加载 DvmDex的pResClasses来查找类是否加载过,如果没加载过,那么跳转到 LOP_NEW_INSTANCE_resolve去加载类,如果加载过,就是类的初始化以及AllocObject的处理。LOP_NEW_INSTANCE_resolve就是调用clazz的dvmResolveClass加载。

    C++代码
    1. /* —————————— */    
    2.     .balign 64    
    3. .L_OP_NEW_INSTANCE: /* 0x22 */    
    4. /* File: armv5te/OP_NEW_INSTANCE.S */    
    5.     /*  
    6.      * Create a new instance of a class.  
    7.      */    
    8.     /* new-instance vAA, class@BBBB */    
    9.     ldr     r3, [rSELF, #offThread_methodClassDex]    @ r3<- pDvmDex    
    10.     FETCH(r1, 1)                        @ r1<- BBBB    
    11.     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses    
    12.     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class    
    13. #if defined(WITH_JIT)    
    14.     add     r10, r3, r1, lsl #2         @ r10<- &resolved_class    
    15. #endif    
    16.     EXPORT_PC()                         @ req’d for init, resolve, alloc    
    17.     cmp     r0, #0                      @ already resolved?    
    18.     beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now    
    19. .LOP_NEW_INSTANCE_resolved:   @ r0=class    
    20.     ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum    
    21.     cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?    
    22.     bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now    
    23. .LOP_NEW_INSTANCE_initialized: @ r0=class    
    24.     mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call    
    25.     bl      dvmAllocObject              @ r0<- new object    
    26.     b       .LOP_NEW_INSTANCE_finish          @ continue    
    27.     
    28.     
    29. .LOP_NEW_INSTANCE_needinit:    
    30.     mov     r9, r0                      @ save r0    
    31.     bl      dvmInitClass                @ initialize class    
    32.     cmp     r0, #0                      @ check boolean result    
    33.     mov     r0, r9                      @ restore r0    
    34.     bne     .LOP_NEW_INSTANCE_initialized     @ success, continue    
    35.     b       common_exceptionThrown      @ failed, deal with init exception    
    36.     
    37.     /*  
    38.      * Resolution required.  This is the least-likely path.  
    39.      *  
    40.      *  r1 holds BBBB  
    41.      */    
    42. .LOP_NEW_INSTANCE_resolve:    
    43.     ldr     r3, [rSELF, #offThread_method] @ r3<- self->method    
    44.     mov     r2, #0                      @ r2<- false    
    45.     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz    
    46.     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr    
    47.     cmp     r0, #0                      @ got null?    
    48.     bne     .LOP_NEW_INSTANCE_resolved        @ no, continue    
    49.     b       common_exceptionThrown      @ yes, handle exception  

    android开发学习网 » 深入理解Dalvik虚拟机- 解释器的运行机制
    peter

    peter 普通

    分享到: