%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 a cast from one class to another is allowed. */ /* check-cast vAA, class@BBBB */ GET_GLUE(%ecx) movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- vAA (object) movzwl 2(rPC),%eax # eax<- BBBB movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex testl rINST_FULL,rINST_FULL # is oject null? movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses je .L${opcode}_okay # null obj, cast always succeeds movl (%ecx,%eax,4),%eax # eax<- resolved class movl offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz testl %eax,%eax # have we resolved this before? je .L${opcode}_resolve # no, go do it now .L${opcode}_resolved: cmpl %eax,%ecx # same class (trivial success)? jne .L${opcode}_fullcheck # no, do full check .L${opcode}_okay: FETCH_INST_WORD(2) ADVANCE_PC(2) GOTO_NEXT %break /* * Trivial test failed, need to perform full check. This is common. * ecx holds obj->clazz * eax holds class resolved from BBBB * rINST_FULL holds object */ .L${opcode}_fullcheck: movl %eax,OUT_ARG1(%esp) movl %ecx,OUT_ARG0(%esp) SPILL(rPC) call dvmInstanceofNonTrivial # eax<- boolean result UNSPILL(rPC) testl %eax,%eax # failed? jne .L${opcode}_okay # no, success # A cast has failed. We need to throw a ClassCastException with the # class of the object that failed to be cast. EXPORT_PC() movl offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz movl $$.LstrClassCastException,%eax movl offClassObject_descriptor(%ecx),%ecx movl %eax,OUT_ARG0(%esp) # arg0<- message movl %ecx,OUT_ARG1(%esp) # arg1<- obj->clazz->descriptor SPILL(rPC) call dvmThrowExceptionWithClassMessage UNSPILL(rPC) jmp common_exceptionThrown /* * Resolution required. This is the least-likely path, and we're * going to have to recreate some data. * * rINST_FULL holds object */ .L${opcode}_resolve: GET_GLUE(%ecx) EXPORT_PC() movzwl 2(rPC),%eax # eax<- BBBB movl offGlue_method(%ecx),%ecx # ecx<- glue->method movl %eax,OUT_ARG1(%esp) # arg1<- BBBB movl offMethod_clazz(%ecx),%ecx # ecx<- metho->clazz movl $$0,OUT_ARG2(%esp) # arg2<- false movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz SPILL(rPC) call dvmResolveClass # eax<- resolved ClassObject ptr UNSPILL(rPC) testl %eax,%eax # got null? je common_exceptionThrown # yes, handle exception movl offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz jmp .L${opcode}_resolved # pick up where we left off