1 2 %default { "isrange":"0", "routine":"NoRange" } 3 %verify "executed" 4 %verify "unknown method" 5 %verify "null object" 6 /* 7 * Handle a virtual method call. 8 * 9 * for: invoke-virtual, invoke-virtual/range 10 */ 11 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 12 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 13 GET_GLUE(%eax) 14 movzwl 2(rPC),%ecx # ecx<- BBBB 15 movl offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex 16 EXPORT_PC() 17 movl offDvmDex_pResMethods(%eax),%eax # eax<- pDvmDex->pResMethods 18 movl (%eax,%ecx,4),%eax # eax<- resolved baseMethod 19 testl %eax,%eax # already resolved? 20 jne .L${opcode}_continue # yes, continue 21 GET_GLUE(%eax) 22 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 23 movl offGlue_method(%eax),%eax # eax<- glue->method 24 SPILL(rPC) 25 jmp .L${opcode}_more 26 %break 27 28 29 .L${opcode}_more: 30 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz 31 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 32 movl $$METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags 33 call dvmResolveMethod # eax<- call(clazz, ref, flags) 34 UNSPILL(rPC) 35 testl %eax,%eax # got null? 36 jne .L${opcode}_continue # no, continue 37 jmp common_exceptionThrown # yes, handle exception 38 39 /* At this point: 40 * eax = resolved base method 41 * ecx = scratch 42 */ 43 .L${opcode}_continue: 44 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC 45 .if (!$isrange) 46 andl $$0xf,%ecx # ecx<- D (or stays CCCC) 47 .endif 48 GET_VREG(%ecx,%ecx) # ecx<- "this" 49 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex 50 testl %ecx,%ecx # null this? 51 je common_errNullObject # go if so 52 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz 53 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable 54 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex] 55 jmp common_invokeMethod${routine} 56