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_CHECK_CAST.S
18    *
19    * Code: Checks to see if a cast is allowed. Uses no substitutions.
20    *
21    * For: check-cast
22    *
23    * Description: Throw if the reference in the given register cannot be
24    *              cast to the indicated type. The type must be a reference
25    *              type (not a primitive type).
26    *
27    * Format: AA|op BBBB (21c)
28    *
29    * Syntax: op vAA, type@BBBB
30    */
31
32    movl        rGLUE, %edx             # get MterpGlue pointer
33    movl        offGlue_methodClassDex(%edx), %eax # %eax<- pDvmDex
34    GET_VREG    rINST                   # rINST<- vAA
35    movl        offDvmDex_pResClasses(%eax), %eax # %eax<- pDvmDex->pResClasses
36    cmp         $$0, rINST              # check for null reference object
37    je          .L${opcode}_okay        # can always cast null object
38    FETCH       1, %ecx                 # %ecx<- BBBB
39    movl        (%eax, %ecx, 4), %ecx   # %ecx<- resolved class
40    cmp         $$0, %ecx               # check if classes is resolved before?
41    je          .L${opcode}_resolve     # resolve class
42    jmp         .L${opcode}_resolved    # continue
43%break
44
45.L${opcode}_resolved:
46    cmp         %ecx, offObject_clazz(rINST) # check for same class
47    jne         .L${opcode}_fullcheck   # not same class; do full check
48
49.L${opcode}_okay:
50    FINISH      2                       # jump to next instruction
51
52   /*
53    *  Trivial test failed, need to perform full check.
54    *  offObject_clazz(rINST) holds obj->clazz
55    *  %ecx holds class resolved from BBBB
56    *  rINST holds object
57    */
58
59.L${opcode}_fullcheck:
60    movl        offObject_clazz(rINST), %eax  # %eax<- obj->clazz
61    movl        %eax, -12(%esp)         # push parameter obj->clazz
62    movl        %ecx, -8(%esp)          # push parameter # push parameter resolved class
63    lea         -12(%esp), %esp
64    call        dvmInstanceofNonTrivial # call: (ClassObject* instance, ClassObject* clazz)
65                                        # return: int
66    lea         12(%esp), %esp
67    cmp         $$0, %eax               # failed?
68    jne         .L${opcode}_okay        # success
69
70   /*
71    * A cast has failed.  We need to throw a ClassCastException with the
72    * class of the object that failed to be cast.
73    */
74
75    EXPORT_PC                           # we will throw an exception
76#error BIT ROT!!!
77    /*
78     * TODO: Code here needs to call dvmThrowClassCastException with two
79     * arguments.
80     */
81#if 0
82    /* old obsolete code that called dvmThrowExceptionWithClassMessage */
83    movl        $$.LstrClassCastExceptionPtr, -8(%esp) # push parameter message
84    movl        offObject_clazz(rINST), rINST # rINST<- obj->clazz
85    movl        offClassObject_descriptor(rINST), rINST # rINST<- obj->clazz->descriptor
86    movl        rINST, -4(%esp)         # push parameter obj->clazz->descriptor
87    lea         -8(%esp), %esp
88    call        dvmThrowExceptionWithClassMessage # call: (const char* exceptionDescriptor,
89                                                  #       const char* messageDescriptor, Object* cause)
90                                                  # return: void
91#endif
92    lea         8(%esp), %esp
93    jmp         common_exceptionThrown
94
95   /*
96    * Resolution required.  This is the least-likely path.
97    *
98    *  rINST holds object
99    */
100
101.L${opcode}_resolve:
102    movl        offGlue_method(%edx), %eax # %eax<- glue->method
103    FETCH       1, %ecx                 # %ecx holds BBBB
104    EXPORT_PC                           # in case we throw an exception
105    movl        $$0, -8(%esp)           # push parameter false
106    movl        offMethod_clazz(%eax), %eax # %eax<- glue->method->clazz
107    movl        %ecx, -12(%esp)         # push parameter BBBB
108    movl        %eax, -16(%esp)         # push parameter glue->method>clazz
109    lea         -16(%esp), %esp
110    call        dvmResolveClass         # resolve ClassObject pointer
111                                        # call: (const ClassObject* referrer, u4 classIdx,
112                                        #        bool fromUnverifiedConstant)
113                                        # return ClassObject*
114    lea         16(%esp), %esp
115    cmp         $$0, %eax               # check for null pointer
116    je          common_exceptionThrown  # handle excpetion
117    movl        %eax, %ecx              # %ecx<- resolved class
118    jmp         .L${opcode}_resolved
119