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 * TODO: convert most of this into a common subroutine, shared with 15 * OP_INSTANCE_OF.S. 16 */ 17 /* instance-of/jumbo vBBBB, vCCCC, class@AAAAAAAA */ 18 FETCH(r3, 4) @ r3<- vCCCC 19 FETCH(r9, 3) @ r9<- vBBBB 20 GET_VREG(r0, r3) @ r0<- vCCCC (object) 21 ldr r2, [rSELF, #offThread_methodClassDex] @ r2<- pDvmDex 22 cmp r0, #0 @ is object null? 23 beq .L${opcode}_store @ null obj, not an instance, store r0 24 FETCH(r1, 1) @ r1<- aaaa (lo) 25 FETCH(r3, 2) @ r3<- AAAA (hi) 26 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 27 orr r3, r1, r3, lsl #16 @ r3<- AAAAaaaa 28 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 29 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 30 cmp r1, #0 @ have we resolved this before? 31 beq .L${opcode}_resolve @ not resolved, do it now 32 b .L${opcode}_resolved @ resolved, continue 33 %break 34 35 /* 36 * Class resolved, determine type of check necessary. This is common. 37 * r0 holds obj->clazz 38 * r1 holds class resolved from AAAAAAAA 39 * r9 holds BBBB 40 */ 41 .L${opcode}_resolved: 42 cmp r0, r1 @ same class (trivial success)? 43 beq .L${opcode}_trivial @ yes, trivial finish 44 @ fall through to ${opcode}_fullcheck 45 46 /* 47 * Trivial test failed, need to perform full check. This is common. 48 * r0 holds obj->clazz 49 * r1 holds class resolved from AAAAAAAA 50 * r9 holds BBBB 51 */ 52 .L${opcode}_fullcheck: 53 bl dvmInstanceofNonTrivial @ r0<- boolean result 54 @ fall through to ${opcode}_store 55 56 /* 57 * r0 holds boolean result 58 * r9 holds BBBB 59 */ 60 .L${opcode}_store: 61 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 62 SET_VREG(r0, r9) @ vBBBB<- r0 63 GET_INST_OPCODE(ip) @ extract opcode from rINST 64 GOTO_OPCODE(ip) @ jump to next instruction 65 66 /* 67 * Trivial test succeeded, save and bail. 68 * r9 holds BBBB 69 */ 70 .L${opcode}_trivial: 71 mov r0, #1 @ indicate success 72 @ could b ${opcode}_store, but copying is faster and cheaper 73 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 74 SET_VREG(r0, r9) @ vBBBB<- r0 75 GET_INST_OPCODE(ip) @ extract opcode from rINST 76 GOTO_OPCODE(ip) @ jump to next instruction 77 78 /* 79 * Resolution required. This is the least-likely path. 80 * 81 * r3 holds AAAAAAAA 82 * r9 holds BBBB 83 */ 84 85 .L${opcode}_resolve: 86 EXPORT_PC() @ resolve() could throw 87 ldr r0, [rSELF, #offThread_method] @ r0<- self->method 88 mov r1, r3 @ r1<- AAAAAAAA 89 mov r2, #1 @ r2<- true 90 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 91 bl dvmResolveClass @ r0<- resolved ClassObject ptr 92 cmp r0, #0 @ got null? 93 beq common_exceptionThrown @ yes, handle exception 94 FETCH(r3, 4) @ r3<- vCCCC 95 mov r1, r0 @ r1<- class resolved from AAAAAAAA 96 GET_VREG(r0, r3) @ r0<- vCCCC (object) 97 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 98 b .L${opcode}_resolved @ pick up where we left off 99