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 mov r3, rINST, lsr #8 @ r3<- AA 13 FETCH(r2, 1) @ r2<- BBBB 14 GET_VREG(r9, r3) @ r9<- object 15 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 16 cmp r9, #0 @ is object null? 17 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 18 beq .L${opcode}_okay @ null obj, cast always succeeds 19 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 20 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 21 cmp r1, #0 @ have we resolved this before? 22 beq .L${opcode}_resolve @ not resolved, do it now 23.L${opcode}_resolved: 24 cmp r0, r1 @ same class (trivial success)? 25 bne .L${opcode}_fullcheck @ no, do full check 26.L${opcode}_okay: 27 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 28 GET_INST_OPCODE(ip) @ extract opcode from rINST 29 GOTO_OPCODE(ip) @ jump to next instruction 30%break 31 32 /* 33 * Trivial test failed, need to perform full check. This is common. 34 * r0 holds obj->clazz 35 * r1 holds class resolved from BBBB 36 * r9 holds object 37 */ 38.L${opcode}_fullcheck: 39 bl dvmInstanceofNonTrivial @ r0<- boolean result 40 cmp r0, #0 @ failed? 41 bne .L${opcode}_okay @ no, success 42 43 @ A cast has failed. We need to throw a ClassCastException with the 44 @ class of the object that failed to be cast. 45 EXPORT_PC() @ about to throw 46 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 47 ldr r0, .LstrClassCastExceptionPtr 48 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 49 bl dvmThrowExceptionWithClassMessage 50 b common_exceptionThrown 51 52 /* 53 * Resolution required. This is the least-likely path. 54 * 55 * r2 holds BBBB 56 * r9 holds object 57 */ 58.L${opcode}_resolve: 59 EXPORT_PC() @ resolve() could throw 60 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 61 mov r1, r2 @ r1<- BBBB 62 mov r2, #0 @ r2<- false 63 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 64 bl dvmResolveClass @ r0<- resolved ClassObject ptr 65 cmp r0, #0 @ got null? 66 beq common_exceptionThrown @ yes, handle exception 67 mov r1, r0 @ r1<- class resolved from BBB 68 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 69 b .L${opcode}_resolved @ pick up where we left off 70 71.LstrClassCastExceptionPtr: 72 .word .LstrClassCastException 73 74