1%default { "isrange":"0", "routine":"NoRange" } 2%verify "executed" 3%verify "unknown method" 4%verify "null object" 5 /* 6 * Handle a virtual method call. 7 * 8 * for: invoke-virtual, invoke-virtual/range 9 */ 10 # op vB, {vD, vE, vF, vG, vA}, class /* CCCC */ 11 # op vAA, {vCCCC..v(CCCC+AA-1)}, meth /* BBBB */ 12 LOAD_rSELF_methodClassDex(a3) # a3 <- pDvmDex 13 FETCH(a1, 1) # a1 <- BBBB 14 LOAD_base_offDvmDex_pResMethods(a3, a3) # a3 <- pDvmDex->pResMethods 15 FETCH(rBIX, 2) # rBIX <- GFED or CCCC 16 LOAD_eas2(a0, a3, a1) # a0 <- resolved baseMethod 17 .if (!$isrange) 18 and rBIX, rBIX, 15 # rBIX <- D (or stays CCCC) 19 .endif 20 EXPORT_PC() # must export for invoke 21 # already resolved? 22 bnez a0, .L${opcode}_continue # yes, continue on 23 24 LOAD_rSELF_method(a3) # a3 <- self->method 25 LOAD_base_offMethod_clazz(a0, a3) # a0 <- method->clazz 26 li a2, METHOD_VIRTUAL # resolver method type 27 JAL(dvmResolveMethod) # v0 <- call(clazz, ref, flags) 28 move a0, v0 29 # got null? 30 bnez v0, .L${opcode}_continue # no, continue 31 b common_exceptionThrown # yes, handle exception 32%break 33 34 /* 35 * At this point: 36 * a0 = resolved base method 37 * rBIX= C or CCCC (index of first arg, which is the "this" ptr) 38 */ 39.L${opcode}_continue: 40 GET_VREG(rOBJ, rBIX) # rOBJ <- "this" ptr 41 LOADu2_offMethod_methodIndex(a2, a0) # a2 <- baseMethod->methodIndex 42 # is "this" null? 43 beqz rOBJ, common_errNullObject # null "this", throw exception 44 LOAD_base_offObject_clazz(a3, rOBJ) # a3 <- thisPtr->clazz 45 LOAD_base_offClassObject_vtable(a3, a3) # a3 <- thisPtr->clazz->vtable 46 LOAD_eas2(a0, a3, a2) # a0 <- vtable[methodIndex] 47 b common_invokeMethod${routine} # (a0=method, rOBJ="this") 48 49