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 a cast from one class to another is allowed. 10 */ 11 /* check-cast vAA, class@BBBB */ 12 movl rSELF,%ecx 13 GET_VREG_R rINST,rINST # rINST<- vAA (object) 14 movzwl 2(rPC),%eax # eax<- BBBB 15 movl offThread_methodClassDex(%ecx),%ecx # ecx<- pDvmDex 16 testl rINST,rINST # is oject null? 17 movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses 18 je .L${opcode}_okay # null obj, cast always succeeds 19 movl (%ecx,%eax,4),%eax # eax<- resolved class 20 movl offObject_clazz(rINST),%ecx # ecx<- obj->clazz 21 testl %eax,%eax # have we resolved this before? 22 je .L${opcode}_resolve # no, go do it now 23 .L${opcode}_resolved: 24 cmpl %eax,%ecx # same class (trivial success)? 25 jne .L${opcode}_fullcheck # no, do full check 26 .L${opcode}_okay: 27 FETCH_INST_OPCODE 2 %ecx 28 ADVANCE_PC 2 29 GOTO_NEXT_R %ecx 30 31 /* 32 * Trivial test failed, need to perform full check. This is common. 33 * ecx holds obj->clazz 34 * eax holds class resolved from BBBB 35 * rINST holds object 36 */ 37 .L${opcode}_fullcheck: 38 movl %eax,sReg0 # we'll need the desired class on failure 39 movl %eax,OUT_ARG1(%esp) 40 movl %ecx,OUT_ARG0(%esp) 41 SPILL(rIBASE) 42 call dvmInstanceofNonTrivial # eax<- boolean result 43 UNSPILL(rIBASE) 44 testl %eax,%eax # failed? 45 jne .L${opcode}_okay # no, success 46 47 # A cast has failed. We need to throw a ClassCastException. 48 EXPORT_PC 49 movl offObject_clazz(rINST),%eax 50 movl %eax,OUT_ARG0(%esp) # arg0<- obj->clazz 51 movl sReg0,%ecx 52 movl %ecx,OUT_ARG1(%esp) # arg1<- desired class 53 call dvmThrowClassCastException 54 jmp common_exceptionThrown 55 56 /* 57 * Resolution required. This is the least-likely path, and we're 58 * going to have to recreate some data. 59 * 60 * rINST holds object 61 */ 62 .L${opcode}_resolve: 63 movl rSELF,%ecx 64 EXPORT_PC 65 movzwl 2(rPC),%eax # eax<- BBBB 66 movl offThread_method(%ecx),%ecx # ecx<- self->method 67 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB 68 movl offMethod_clazz(%ecx),%ecx # ecx<- metho->clazz 69 movl $$0,OUT_ARG2(%esp) # arg2<- false 70 movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz 71 SPILL(rIBASE) 72 call dvmResolveClass # eax<- resolved ClassObject ptr 73 UNSPILL(rIBASE) 74 testl %eax,%eax # got null? 75 je common_exceptionThrown # yes, handle exception 76 movl offObject_clazz(rINST),%ecx # ecx<- obj->clazz 77 jmp .L${opcode}_resolved # pick up where we left off 78