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, [rSELF, #offThread_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 desired class resolved from BBBB 36 * r9 holds object 37 */ 38 .L${opcode}_fullcheck: 39 mov r10, r1 @ avoid ClassObject getting clobbered 40 bl dvmInstanceofNonTrivial @ r0<- boolean result 41 cmp r0, #0 @ failed? 42 bne .L${opcode}_okay @ no, success 43 44 @ A cast has failed. We need to throw a ClassCastException. 45 EXPORT_PC() @ about to throw 46 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz (actual class) 47 mov r1, r10 @ r1<- desired class 48 bl dvmThrowClassCastException 49 b common_exceptionThrown 50 51 /* 52 * Resolution required. This is the least-likely path. 53 * 54 * r2 holds BBBB 55 * r9 holds object 56 */ 57 .L${opcode}_resolve: 58 EXPORT_PC() @ resolve() could throw 59 ldr r3, [rSELF, #offThread_method] @ r3<- self->method 60 mov r1, r2 @ r1<- BBBB 61 mov r2, #0 @ r2<- false 62 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 63 bl dvmResolveClass @ r0<- resolved ClassObject ptr 64 cmp r0, #0 @ got null? 65 beq common_exceptionThrown @ yes, handle exception 66 mov r1, r0 @ r1<- class resolved from BBB 67 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 68 b .L${opcode}_resolved @ pick up where we left off 69