1%verify "executed"
2%verify "null object"
3%verify "class cast exception thrown, with correct class name"
4%verify "class cast exception not thrown on same class"
5%verify "class cast exception not thrown on subclass"
6%verify "class not resolved"
7%verify "class already resolved"
8    /*
9     * Check to see if an object reference is an instance of a class.
10     *
11     * Most common situation is a non-null object, being compared against
12     * an already-resolved class.
13     */
14    /* instance-of vA, vB, class@CCCC */
15    movl    rINST,%eax                  # eax<- BA
16    sarl    $$4,%eax                    # eax<- B
17    GET_VREG_R %eax %eax                # eax<- vB (obj)
18    movl    rSELF,%ecx
19    testl   %eax,%eax                   # object null?
20    movl    offThread_methodClassDex(%ecx),%ecx  # ecx<- pDvmDex
21    SPILL(rIBASE)                       # preserve rIBASE
22    je      .L${opcode}_store           # null obj, not instance, store it
23    movzwl  2(rPC),rIBASE               # rIBASE<- CCCC
24    movl    offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses
25    movl    (%ecx,rIBASE,4),%ecx        # ecx<- resolved class
26    movl    offObject_clazz(%eax),%eax  # eax<- obj->clazz
27    testl   %ecx,%ecx                   # have we resolved this before?
28    je      .L${opcode}_resolve         # not resolved, do it now
29.L${opcode}_resolved:  # eax<- obj->clazz, ecx<- resolved class
30    cmpl    %eax,%ecx                   # same class (trivial success)?
31    je      .L${opcode}_trivial         # yes, trivial finish
32    /*
33     * Trivial test failed, need to perform full check.  This is common.
34     *  eax holds obj->clazz
35     *  ecx holds class resolved from BBBB
36     *  rINST has BA
37     */
38    movl    %eax,OUT_ARG0(%esp)
39    movl    %ecx,OUT_ARG1(%esp)
40    call    dvmInstanceofNonTrivial     # eax<- boolean result
41    # fall through to ${opcode}_store
42
43    /*
44     * eax holds boolean result
45     * rINST holds BA
46     */
47.L${opcode}_store:
48    FETCH_INST_OPCODE 2 %ecx
49    UNSPILL(rIBASE)
50    andb    $$0xf,rINSTbl               # <- A
51    ADVANCE_PC 2
52    SET_VREG %eax rINST                 # vA<- eax
53    GOTO_NEXT_R %ecx
54
55    /*
56     * Trivial test succeeded, save and bail.
57     *  r9 holds A
58     */
59.L${opcode}_trivial:
60    FETCH_INST_OPCODE 2 %ecx
61    UNSPILL(rIBASE)
62    andb    $$0xf,rINSTbl               # <- A
63    ADVANCE_PC 2
64    movl    $$1,%eax
65    SET_VREG %eax rINST                 # vA<- true
66    GOTO_NEXT_R %ecx
67
68    /*
69     * Resolution required.  This is the least-likely path.
70     *
71     *  rIBASE holds BBBB
72     *  rINST holds BA
73     */
74.L${opcode}_resolve:
75    movl    rIBASE,OUT_ARG1(%esp)         # arg1<- BBBB
76    movl    rSELF,%ecx
77    movl    offThread_method(%ecx),%ecx
78    movl    $$1,OUT_ARG2(%esp)          # arg2<- true
79    movl    offMethod_clazz(%ecx),%ecx  # ecx<- method->clazz
80    EXPORT_PC
81    movl    %ecx,OUT_ARG0(%esp)         # arg0<- method->clazz
82    call    dvmResolveClass             # eax<- resolved ClassObject ptr
83    testl   %eax,%eax                   # success?
84    je      common_exceptionThrown      # no, handle exception
85/* Now, we need to sync up with fast path.  We need eax to
86 * hold the obj->clazz, and ecx to hold the resolved class
87 */
88    movl    %eax,%ecx                   # ecx<- resolved class
89    movl    rINST,%eax                  # eax<- BA
90    sarl    $$4,%eax                    # eax<- B
91    GET_VREG_R %eax %eax                # eax<- vB (obj)
92    movl    offObject_clazz(%eax),%eax  # eax<- obj->clazz
93    jmp     .L${opcode}_resolved
94