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 movl rSELF,%eax 14 movzwl 2(rPC),%ecx # ecx<- BBBB 15 movl offThread_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 movl rSELF,%eax 22 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 23 movl offThread_method(%eax),%eax # eax<- self->method 24 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz 25 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 26 movl $$METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags 27 call dvmResolveMethod # eax<- call(clazz, ref, flags) 28 testl %eax,%eax # got null? 29 jne .L${opcode}_continue # no, continue 30 jmp common_exceptionThrown # yes, handle exception 31 32 /* At this point: 33 * eax = resolved base method 34 * ecx = scratch 35 */ 36 .L${opcode}_continue: 37 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC 38 .if (!$isrange) 39 andl $$0xf,%ecx # ecx<- D (or stays CCCC) 40 .endif 41 GET_VREG_R %ecx %ecx # ecx<- "this" 42 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex 43 testl %ecx,%ecx # null this? 44 je common_errNullObject # go if so 45 movl offObject_clazz(%ecx),%edx # edx<- thisPtr->clazz 46 movl offClassObject_vtable(%edx),%edx # edx<- thisPtr->clazz->vtable 47 movl (%edx,%eax,4),%eax # eax<- vtable[methodIndex] 48 jmp common_invokeMethod${routine} 49