| %default { "routine":"NoRange" } |
| %verify "executed" |
| %verify "unknown method" |
| /* |
| * Handle a static method call. |
| * |
| * for: invoke-static, invoke-static/range |
| */ |
| # op vB, {vD, vE, vF, vG, vA}, class /* CCCC */ |
| # op {vCCCC..v(CCCC+AA-1)}, meth /* BBBB */ |
| LOAD_rSELF_methodClassDex(a3) # a3 <- pDvmDex |
| FETCH(a1, 1) # a1 <- BBBB |
| LOAD_base_offDvmDex_pResMethods(a3, a3) # a3 <- pDvmDex->pResMethods |
| li rOBJ, 0 # null "this" in delay slot |
| LOAD_eas2(a0, a3, a1) # a0 <- resolved methodToCall |
| #if defined(WITH_JIT) |
| EAS2(rBIX, a3, a1) # rBIX<- &resolved_metherToCall |
| #endif |
| EXPORT_PC() # must export for invoke |
| # already resolved? |
| bnez a0, common_invokeMethod${routine} # yes, continue on |
| b .L${opcode}_resolve |
| %break |
| |
| .L${opcode}_resolve: |
| LOAD_rSELF_method(a3) # a3 <- self->method |
| LOAD_base_offMethod_clazz(a0, a3) # a0 <- method->clazz |
| li a2, METHOD_STATIC # resolver method type |
| JAL(dvmResolveMethod) # v0 <- call(clazz, ref, flags) |
| move a0, v0 |
| #if defined(WITH_JIT) |
| /* |
| * Check to see if we're actively building a trace. If so, |
| * we need to keep this instruction out of it. |
| * rBIX: &resolved_methodToCall |
| */ |
| lhu a2, offThread_subMode(rSELF) |
| beqz v0, common_exceptionThrown # null, handle exception |
| and a2, kSubModeJitTraceBuild # trace under construction? |
| beqz a2, common_invokeMethod${routine} # no, (a0=method, rOBJ="this") |
| lw a1, 0(rBIX) # reload resolved method |
| # finished resloving? |
| bnez a1, common_invokeMethod${routine} # yes, (a0=method, rOBJ="this") |
| move rBIX, a0 # preserve method |
| move a0, rSELF |
| move a1, rPC |
| JAL(dvmJitEndTraceSelect) # (self, pc) |
| move a0, rBIX |
| b common_invokeMethod${routine} # whew, finally! |
| #else |
| # got null? |
| bnez v0, common_invokeMethod${routine} # (a0=method, rOBJ="this") |
| b common_exceptionThrown # yes, handle exception |
| #endif |