%verify "executed" %verify "null object" %verify "class cast exception thrown, with correct class name" %verify "class cast exception not thrown on same class" %verify "class cast exception not thrown on subclass" %verify "class not resolved" %verify "class already resolved" /* * Check to see if an object reference is an instance of a class. * * Most common situation is a non-null object, being compared against * an already-resolved class. */ /* instance-of vA, vB, class@CCCC */ movzbl rINST_HI,%eax # eax<- BA sarl $$4,%eax # eax<- B GET_VREG(%eax,%eax) # eax<- vB (obj) GET_GLUE(%ecx) testl %eax,%eax # object null? movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex SPILL(rPC) je .L${opcode}_store # null obj, not instance, store it movzwl 2(rPC),rPC # rPC<- CCCC movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses movl (%ecx,rPC,4),%ecx # ecx<- resolved class movl offObject_clazz(%eax),%eax # eax<- obj->clazz testl %ecx,%ecx # have we resolved this before? je .L${opcode}_resolve # not resolved, do it now .L${opcode}_resolved: # eax<- obj->clazz, ecx<- resolved class cmpl %eax,%ecx # same class (trivial success)? je .L${opcode}_trivial # yes, trivial finish jmp .L${opcode}_fullcheck # no, do full check %break /* * Trivial test failed, need to perform full check. This is common. * eax holds obj->clazz * ecx holds class resolved from BBBB * rINST_HI has BA * rPC already spilled */ .L${opcode}_fullcheck: movl %eax,OUT_ARG0(%esp) movl %ecx,OUT_ARG1(%esp) call dvmInstanceofNonTrivial # eax<- boolean result # fall through to ${opcode}_store /* * eax holds boolean result * rINST_HI holds BA */ .L${opcode}_store: UNSPILL(rPC) movzbl rINST_HI,%ecx # ecx<- BA FETCH_INST_WORD(2) andb $$0xf,%cl # ecl<- A ADVANCE_PC(2) SET_VREG(%eax,%ecx) # vA<- eax GOTO_NEXT /* * Trivial test succeeded, save and bail. * r9 holds A */ .L${opcode}_trivial: UNSPILL(rPC) movzbl rINST_HI,%ecx # ecx<- BA FETCH_INST_WORD(2) andb $$0xf,%cl # ecl<- A ADVANCE_PC(2) movl $$1,%eax SET_VREG(%eax,%ecx) # vA<- true GOTO_NEXT /* * Resolution required. This is the least-likely path. * * rPC holds BBBB * rINST_HI holds BA */ .L${opcode}_resolve: movl rPC,OUT_ARG1(%esp) # arg1<- BBBB GET_GLUE(%ecx) UNSPILL(rPC) movl offGlue_method(%ecx),%ecx movl $$1,OUT_ARG2(%esp) # arg2<- true movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz EXPORT_PC() movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz call dvmResolveClass # eax<- resolved ClassObject ptr UNSPILL(rPC) testl %eax,%eax # success? je common_exceptionThrown # no, handle exception /* Now, we need to sync up with fast path. We need eax to * hold the obj->clazz, and ecx to hold the resolved class */ movl %eax,%ecx # ecx<- resolved class movzbl rINST_HI,%eax # eax<- BA sarl $$4,%eax # eax<- B GET_VREG(%eax,%eax) # eax<- vB (obj) movl offObject_clazz(%eax),%eax # eax<- obj->clazz jmp .L${opcode}_resolved