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 an object reference is an instance of a class. 10 * 11 * Most common situation is a non-null object, being compared against 12 * an already-resolved class. 13 */ 14 # instance-of vA, vB, class /* CCCC */ 15 GET_OPB(a3) # a3 <- B 16 GET_OPA4(rOBJ) # rOBJ <- A+ 17 GET_VREG(a0, a3) # a0 <- vB (object) 18 LOAD_rSELF_methodClassDex(a2) # a2 <- pDvmDex 19 # is object null? 20 beqz a0, .L${opcode}_store # null obj, not an instance, store a0 21 FETCH(a3, 1) # a3 <- CCCC 22 LOAD_base_offDvmDex_pResClasses(a2, a2) # a2 <- pDvmDex->pResClasses 23 LOAD_eas2(a1, a2, a3) # a1 <- resolved class 24 LOAD_base_offObject_clazz(a0, a0) # a0 <- obj->clazz 25 # have we resolved this before? 26 beqz a1, .L${opcode}_resolve # not resolved, do it now 27 .L${opcode}_resolved: # a0=obj->clazz, a1=resolved class 28 # same class (trivial success)? 29 beq a0, a1, .L${opcode}_trivial # yes, trivial finish 30 b .L${opcode}_fullcheck # no, do full check 31 32 /* 33 * Trivial test succeeded, save and bail. 34 * rOBJ holds A 35 */ 36 .L${opcode}_trivial: 37 li a0, 1 # indicate success 38 # fall thru 39 /* 40 * a0 holds boolean result 41 * rOBJ holds A 42 */ 43 .L${opcode}_store: 44 FETCH_ADVANCE_INST(2) # advance rPC, load rINST 45 SET_VREG(a0, rOBJ) # vA <- a0 46 GET_INST_OPCODE(t0) # extract opcode from rINST 47 GOTO_OPCODE(t0) # jump to next instruction 48 49 %break 50 51 /* 52 * Trivial test failed, need to perform full check. This is common. 53 * a0 holds obj->clazz 54 * a1 holds class resolved from BBBB 55 * rOBJ holds A 56 */ 57 .L${opcode}_fullcheck: 58 JAL(dvmInstanceofNonTrivial) # v0 <- boolean result 59 move a0, v0 # fall through to ${opcode}_store 60 b .L${opcode}_store 61 62 /* 63 * Resolution required. This is the least-likely path. 64 * 65 * a3 holds BBBB 66 * rOBJ holds A 67 */ 68 .L${opcode}_resolve: 69 EXPORT_PC() # resolve() could throw 70 LOAD_rSELF_method(a0) # a0 <- self->method 71 move a1, a3 # a1 <- BBBB 72 li a2, 1 # a2 <- true 73 LOAD_base_offMethod_clazz(a0, a0) # a0 <- method->clazz 74 JAL(dvmResolveClass) # v0 <- resolved ClassObject ptr 75 # got null? 76 move a1, v0 # a1 <- class resolved from BBB 77 beqz v0, common_exceptionThrown # yes, handle exception 78 GET_OPB(a3) # a3 <- B 79 GET_VREG(a0, a3) # a0 <- vB (object) 80 LOAD_base_offObject_clazz(a0, a0) # a0 <- obj->clazz 81 b .L${opcode}_resolved # pick up where we left off 82 83