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