1   /* Copyright (C) 2008 The Android Open Source Project
2    *
3    * Licensed under the Apache License, Version 2.0 (the "License");
4    * you may not use this file except in compliance with the License.
5    * You may obtain a copy of the License at
6    *
7    * http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10    * distributed under the License is distributed on an "AS IS" BASIS,
11    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12    * See the License for the specific language governing permissions and
13    * limitations under the License.
14    */
15
16   /*
17    * File: OP_INSTANCE_OF.S
18    *
19    * Code: Checks if object is instance of a class. Uses no substitutions.
20    *
21    * For: instance-of
22    *
23    * Description: Store in the given destination register 1 if the indicated
24    *              reference is an instance of the given type, or 0 if not.
25    *              The type must be a reference type (not a primitive type).
26    *
27    * Format: B|A|op CCCC (22c)
28    *
29    * Syntax: op vA, vB, type@CCCC
30    *         op vA, vB, field@CCCC
31    */
32
33    movl        rINST, %edx             # %edx<- BA
34    shr         $$4, %edx               # %edx<- B
35    GET_VREG    %edx                    # %edx<- vB
36    cmp         $$0, %edx               # check for null object
37    je          .L${opcode}_store       # null object
38    jmp         .L${opcode}_break
39%break
40
41.L${opcode}_break:
42    movl        rGLUE, %ecx             # %ecx<- pMterpGlue
43    movl        offGlue_methodClassDex(%ecx), %ecx # %ecx<- pDvmDex
44    FETCH       1, %eax                 # %eax<- CCCC
45    movl        offDvmDex_pResClasses(%ecx), %ecx # %ecx<- pDvmDex->pResClasses
46    movl        (%ecx, %eax, 4), %ecx   # %ecx<- resolved class
47    movl        offObject_clazz(%edx), %edx # %edx<- obj->clazz
48    cmp         $$0, %ecx               # check if already resovled
49    je          .L${opcode}_resolve     # not resolved before, so resolve now
50
51.L${opcode}_resolved:
52    cmp         %ecx, %edx              # check if same class
53    je          .L${opcode}_trivial     # yes, finish
54    jmp         .L${opcode}_fullcheck   # no, do full check
55
56   /*
57    * The trivial test failed, we need to perform a full check.
58    * %edx holds obj->clazz
59    * %ecx holds class resolved from BBBB
60    */
61
62.L${opcode}_fullcheck:
63    movl        %edx, -8(%esp)          # push parameter obj->clazz
64    movl        %ecx, -4(%esp)          # push parameter resolved class
65    lea         -8(%esp), %esp
66    call        dvmInstanceofNonTrivial # perform full check
67                                        # call: (ClassObject* instance, ClassObject* clazz)
68                                        # return: int
69    andl        $$15, rINST             # rINST<- A
70    FFETCH_ADV  2, %edx                 # %edx<- next instruction hi; fetch, advance
71    lea         8(%esp), %esp
72    SET_VREG    %eax, rINST             # vA<- r0
73    FGETOP_JMP  2, %edx                 # jump to next instruction; getop, jmp
74
75   /*
76    * %edx holds boolean result
77    */
78
79.L${opcode}_store:
80    FFETCH_ADV  2, %eax                 # %eax<- next instruction hi; fetch, advance
81    andl        $$15, rINST             # rINST<- A
82    SET_VREG    %edx, rINST             # vA<- r0
83    FGETOP_JMP  2, %eax                 # jump to next instruction; getop, jmp
84
85   /*
86    * Trivial test succeeded, save and bail.
87    */
88
89.L${opcode}_trivial:
90    FFETCH_ADV  2, %eax                 # %eax<- next instruction hi; fetch, advance
91    andl        $$15, rINST             # rINST<- A
92    SET_VREG    $$1, rINST              # vA<- r0
93    FGETOP_JMP  2, %eax                 # jump to next instruction; getop, jmp
94
95   /*
96    * Resolution required.  This is the least-likely path.
97    * %eax holds BBBB
98    */
99
100.L${opcode}_resolve:
101
102    movl        rGLUE, %ecx             # %ecx<- pMterpGlue
103    EXPORT_PC
104    movl        offGlue_method(%ecx), %ecx # %ecx<- glue->method
105    movl        offMethod_clazz(%ecx), %ecx # %ecx<- glue->method->clazz
106    movl        %ecx, -12(%esp)         # push parameter glue->method->clazz
107    movl        %eax, -8(%esp)          # push parameter CCCC; type index
108    movl        $$1, -4(%esp)           # push parameter true
109    lea         -12(%esp), %esp
110    call        dvmResolveClass         # call: (const ClassObject* referrer, u4 classIdx,
111                                        #        bool fromUnverifiedConstant)
112                                        # return: ClassObject*
113    lea         12(%esp), %esp
114    cmp         $$0, %eax               # check for null
115    je          common_exceptionThrown  # handle exception
116    movl        rINST, %edx             # %edx<- BA+
117    shr         $$4, %edx               # %edx<- B
118    movl        %eax, %ecx              # need class in %ecx
119    GET_VREG    %edx                    # %edx<- vB
120    movl        offObject_clazz(%edx), %edx # %edx<- obj->clazz
121    jmp         .L${opcode}_resolved    # clazz resolved, continue
122