blob: 0543a99f840eff2fa2e8e3b7418263d9534c8762 [file] [log] [blame]
%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 */
movl rSELF,%ecx
GET_VREG_R rINST,rINST # rINST<- vAA (object)
movzwl 2(rPC),%eax # eax<- BBBB
movl offThread_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
testl rINST,rINST # 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),%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_OPCODE 2 %ecx
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/*
* Trivial test failed, need to perform full check. This is common.
* ecx holds obj->clazz
* eax holds class resolved from BBBB
* rINST holds object
*/
.L${opcode}_fullcheck:
movl %eax,sReg0 # we'll need the desired class on failure
movl %eax,OUT_ARG1(%esp)
movl %ecx,OUT_ARG0(%esp)
SPILL(rIBASE)
call dvmInstanceofNonTrivial # eax<- boolean result
UNSPILL(rIBASE)
testl %eax,%eax # failed?
jne .L${opcode}_okay # no, success
# A cast has failed. We need to throw a ClassCastException.
EXPORT_PC
movl offObject_clazz(rINST),%eax
movl %eax,OUT_ARG0(%esp) # arg0<- obj->clazz
movl sReg0,%ecx
movl %ecx,OUT_ARG1(%esp) # arg1<- desired class
call dvmThrowClassCastException
jmp common_exceptionThrown
/*
* Resolution required. This is the least-likely path, and we're
* going to have to recreate some data.
*
* rINST holds object
*/
.L${opcode}_resolve:
movl rSELF,%ecx
EXPORT_PC
movzwl 2(rPC),%eax # eax<- BBBB
movl offThread_method(%ecx),%ecx # ecx<- self->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(rIBASE)
call dvmResolveClass # eax<- resolved ClassObject ptr
UNSPILL(rIBASE)
testl %eax,%eax # got null?
je common_exceptionThrown # yes, handle exception
movl offObject_clazz(rINST),%ecx # ecx<- obj->clazz
jmp .L${opcode}_resolved # pick up where we left off