summaryrefslogtreecommitdiff
path: root/vm/mterp/x86/OP_INVOKE_VIRTUAL.S
blob: 85fcf83cbfdad0f24e70852d4a3afddae384ce65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

%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 */
    GET_GLUE(%eax)
    movzwl    2(rPC),%ecx                 # ecx<- BBBB
    movl      offGlue_methodClassDex(%eax),%eax  # eax<- pDvmDex
    EXPORT_PC()
    movl      offDvmDex_pResMethods(%eax),%eax   # eax<- pDvmDex->pResMethods
    movl      (%eax,%ecx,4),%eax          # eax<- resolved baseMethod
    testl     %eax,%eax                   # already resolved?
    jne       .L${opcode}_continue        # yes, continue
    GET_GLUE(%eax)
    movl      %ecx,OUT_ARG1(%esp)         # arg1<- ref
    movl      offGlue_method(%eax),%eax   # eax<- glue->method
    SPILL(rPC)
    jmp       .L${opcode}_more
%break


.L${opcode}_more:
    movl      offMethod_clazz(%eax),%eax  # ecx<- method->clazz
    movl      %eax,OUT_ARG0(%esp)         # arg0<- clazz
    movl      $$METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
    call      dvmResolveMethod            # eax<- call(clazz, ref, flags)
    UNSPILL(rPC)
    testl     %eax,%eax                   # got null?
    jne       .L${opcode}_continue        # no, continue
    jmp       common_exceptionThrown      # yes, handle exception

    /* At this point:
     *   eax = resolved base method
     *   ecx = scratch
     */
.L${opcode}_continue:
    movzwl    4(rPC),%ecx               # ecx<- GFED or CCCC
    .if       (!$isrange)
    andl      $$0xf,%ecx                # ecx<- D (or stays CCCC)
    .endif
    GET_VREG(%ecx,%ecx)                 # ecx<- "this"
    movzwl    offMethod_methodIndex(%eax),%eax  # eax<- baseMethod->methodIndex
    testl     %ecx,%ecx                 # null this?
    je        common_errNullObject      # go if so
    movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
    movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
    movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
    jmp       common_invokeMethod${routine}