blob: b9d651cee19afb4a7604a6885527b9cc35ce3652 [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 */
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