summaryrefslogtreecommitdiffstats
path: root/vm/mterp/mips/OP_INVOKE_VIRTUAL.S
diff options
context:
space:
mode:
Diffstat (limited to 'vm/mterp/mips/OP_INVOKE_VIRTUAL.S')
-rw-r--r--vm/mterp/mips/OP_INVOKE_VIRTUAL.S48
1 files changed, 48 insertions, 0 deletions
diff --git a/vm/mterp/mips/OP_INVOKE_VIRTUAL.S b/vm/mterp/mips/OP_INVOKE_VIRTUAL.S
new file mode 100644
index 000000000..9f6d2c32b
--- /dev/null
+++ b/vm/mterp/mips/OP_INVOKE_VIRTUAL.S
@@ -0,0 +1,48 @@
+%default { "isrange":"0", "routine":"NoRange" }
+%verify "executed"
+%verify "unknown method"
+%verify "null object"
+ /*
+ * Handle a virtual method call.
+ *
+ * for: invoke-virtual, invoke-virtual/range
+ */
+ # op vB, {vD, vE, vF, vG, vA}, class /* CCCC */
+ # op vAA, {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
+ FETCH(rBIX, 2) # rBIX <- GFED or CCCC
+ LOAD_eas2(a0, a3, a1) # a0 <- resolved baseMethod
+ .if (!$isrange)
+ and rBIX, rBIX, 15 # rBIX <- D (or stays CCCC)
+ .endif
+ EXPORT_PC() # must export for invoke
+ # already resolved?
+ bnez a0, .L${opcode}_continue # yes, continue on
+
+ LOAD_rSELF_method(a3) # a3 <- self->method
+ LOAD_base_offMethod_clazz(a0, a3) # a0 <- method->clazz
+ li a2, METHOD_VIRTUAL # resolver method type
+ JAL(dvmResolveMethod) # v0 <- call(clazz, ref, flags)
+ move a0, v0
+ # got null?
+ bnez v0, .L${opcode}_continue # no, continue
+ b common_exceptionThrown # yes, handle exception
+%break
+
+ /*
+ * At this point:
+ * a0 = resolved base method
+ * rBIX= C or CCCC (index of first arg, which is the "this" ptr)
+ */
+.L${opcode}_continue:
+ GET_VREG(rOBJ, rBIX) # rOBJ <- "this" ptr
+ LOADu2_offMethod_methodIndex(a2, a0) # a2 <- baseMethod->methodIndex
+ # is "this" null?
+ beqz rOBJ, common_errNullObject # null "this", throw exception
+ LOAD_base_offObject_clazz(a3, rOBJ) # a3 <- thisPtr->clazz
+ LOAD_base_offClassObject_vtable(a3, a3) # a3 <- thisPtr->clazz->vtable
+ LOAD_eas2(a0, a3, a2) # a0 <- vtable[methodIndex]
+ b common_invokeMethod${routine} # (a0=method, rOBJ="this")
+