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 movl $$.LstrClassCastExceptionPtr, -8(%esp) # push parameter message 77 movl offObject_clazz(rINST), rINST # rINST<- obj->clazz 78 movl offClassObject_descriptor(rINST), rINST # rINST<- obj->clazz->descriptor 79 movl rINST, -4(%esp) # push parameter obj->clazz->descriptor 80 lea -8(%esp), %esp 81 call dvmThrowExceptionWithClassMessage # call: (const char* exceptionDescriptor, 82 # const char* messageDescriptor, Object* cause) 83 # return: void 84 lea 8(%esp), %esp 85 jmp common_exceptionThrown 86 87 /* 88 * Resolution required. This is the least-likely path. 89 * 90 * rINST holds object 91 */ 92 93.L${opcode}_resolve: 94 movl offGlue_method(%edx), %eax # %eax<- glue->method 95 FETCH 1, %ecx # %ecx holds BBBB 96 EXPORT_PC # in case we throw an exception 97 movl $$0, -8(%esp) # push parameter false 98 movl offMethod_clazz(%eax), %eax # %eax<- glue->method->clazz 99 movl %ecx, -12(%esp) # push parameter BBBB 100 movl %eax, -16(%esp) # push parameter glue->method>clazz 101 lea -16(%esp), %esp 102 call dvmResolveClass # resolve ClassObject pointer 103 # call: (const ClassObject* referrer, u4 classIdx, 104 # bool fromUnverifiedConstant) 105 # return ClassObject* 106 lea 16(%esp), %esp 107 cmp $$0, %eax # check for null pointer 108 je common_exceptionThrown # handle excpetion 109 movl %eax, %ecx # %ecx<- resolved class 110 jmp .L${opcode}_resolved 111 112.LstrClassCastExceptionPtr: 113.asciz "Ljava/lang/ClassCastException;" 114