blob: 71b92d321713b519614dc475d4ae6ed04adb8590 [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 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