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 GET_OPA(a3) # a3 <- AA 13 FETCH(a2, 1) # a2 <- BBBB 14 GET_VREG(rOBJ, a3) # rOBJ <- object 15 LOAD_rSELF_methodClassDex(a0) # a0 <- pDvmDex 16 LOAD_base_offDvmDex_pResClasses(a0, a0) # a0 <- pDvmDex->pResClasses 17 # is object null? 18 beqz rOBJ, .L${opcode}_okay # null obj, cast always succeeds 19 LOAD_eas2(a1, a0, a2) # a1 <- resolved class 20 LOAD_base_offObject_clazz(a0, rOBJ) # a0 <- obj->clazz 21 # have we resolved this before? 22 beqz a1, .L${opcode}_resolve # not resolved, do it now 23 .L${opcode}_resolved: 24 # same class (trivial success)? 25 bne a0, a1, .L${opcode}_fullcheck # no, do full check 26 .L${opcode}_okay: 27 FETCH_ADVANCE_INST(2) # advance rPC, load rINST 28 GET_INST_OPCODE(t0) # extract opcode from rINST 29 GOTO_OPCODE(t0) # jump to next instruction 30 31 /* 32 * Trivial test failed, need to perform full check. This is common. 33 * a0 holds obj->clazz 34 * a1 holds class resolved from BBBB 35 * rOBJ holds object 36 */ 37 .L${opcode}_fullcheck: 38 move rBIX,a1 # avoid ClassObject getting clobbered 39 JAL(dvmInstanceofNonTrivial) # v0 <- boolean result 40 # failed? 41 bnez v0, .L${opcode}_okay # no, success 42 b .L${opcode}_castfailure 43 %break 44 45 .L${opcode}_castfailure: 46 # A cast has failed. We need to throw a ClassCastException with the 47 # class of the object that failed to be cast. 48 EXPORT_PC() # about to throw 49 LOAD_base_offObject_clazz(a0, rOBJ) # a0 <- obj->clazz 50 move a1,rBIX # r1<- desired class 51 JAL(dvmThrowClassCastException) 52 b common_exceptionThrown 53 54 /* 55 * Resolution required. This is the least-likely path. 56 * 57 * a2 holds BBBB 58 * rOBJ holds object 59 */ 60 .L${opcode}_resolve: 61 EXPORT_PC() # resolve() could throw 62 LOAD_rSELF_method(a3) # a3 <- self->method 63 move a1, a2 # a1 <- BBBB 64 li a2, 0 # a2 <- false 65 LOAD_base_offMethod_clazz(a0, a3) # a0 <- method->clazz 66 JAL(dvmResolveClass) # v0 <- resolved ClassObject ptr 67 # got null? 68 beqz v0, common_exceptionThrown # yes, handle exception 69 move a1, v0 # a1 <- class resolved from BBB 70 LOAD_base_offObject_clazz(a0, rOBJ) # a0 <- obj->clazz 71 b .L${opcode}_resolved # pick up where we left off 72