blob: bbbdb0fe3c4b721d550ad7bf3e7bc444af28a7f7 [file] [log] [blame]
/* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* File: OP_CHECK_CAST.S
*
* Code: Checks to see if a cast is allowed. Uses no substitutions.
*
* For: check-cast
*
* Description: Throw if the reference in the given register cannot be
* cast to the indicated type. The type must be a reference
* type (not a primitive type).
*
* Format: AA|op BBBB (21c)
*
* Syntax: op vAA, type@BBBB
*/
movl rGLUE, %edx # get MterpGlue pointer
movl offGlue_methodClassDex(%edx), %eax # %eax<- pDvmDex
GET_VREG rINST # rINST<- vAA
movl offDvmDex_pResClasses(%eax), %eax # %eax<- pDvmDex->pResClasses
cmp $$0, rINST # check for null reference object
je .L${opcode}_okay # can always cast null object
FETCH 1, %ecx # %ecx<- BBBB
movl (%eax, %ecx, 4), %ecx # %ecx<- resolved class
cmp $$0, %ecx # check if classes is resolved before?
je .L${opcode}_resolve # resolve class
jmp .L${opcode}_resolved # continue
%break
.L${opcode}_resolved:
cmp %ecx, offObject_clazz(rINST) # check for same class
jne .L${opcode}_fullcheck # not same class; do full check
.L${opcode}_okay:
FINISH 2 # jump to next instruction
/*
* Trivial test failed, need to perform full check.
* offObject_clazz(rINST) holds obj->clazz
* %ecx holds class resolved from BBBB
* rINST holds object
*/
.L${opcode}_fullcheck:
movl offObject_clazz(rINST), %eax # %eax<- obj->clazz
movl %eax, -12(%esp) # push parameter obj->clazz
movl %ecx, -8(%esp) # push parameter # push parameter resolved class
lea -12(%esp), %esp
call dvmInstanceofNonTrivial # call: (ClassObject* instance, ClassObject* clazz)
# return: int
lea 12(%esp), %esp
cmp $$0, %eax # failed?
jne .L${opcode}_okay # success
/*
* A cast has failed. We need to throw a ClassCastException with the
* class of the object that failed to be cast.
*/
EXPORT_PC # we will throw an exception
movl $$.LstrClassCastExceptionPtr, -8(%esp) # push parameter message
movl offObject_clazz(rINST), rINST # rINST<- obj->clazz
movl offClassObject_descriptor(rINST), rINST # rINST<- obj->clazz->descriptor
movl rINST, -4(%esp) # push parameter obj->clazz->descriptor
lea -8(%esp), %esp
call dvmThrowExceptionWithClassMessage # call: (const char* exceptionDescriptor,
# const char* messageDescriptor, Object* cause)
# return: void
lea 8(%esp), %esp
jmp common_exceptionThrown
/*
* Resolution required. This is the least-likely path.
*
* rINST holds object
*/
.L${opcode}_resolve:
movl offGlue_method(%edx), %eax # %eax<- glue->method
FETCH 1, %ecx # %ecx holds BBBB
EXPORT_PC # in case we throw an exception
movl $$0, -8(%esp) # push parameter false
movl offMethod_clazz(%eax), %eax # %eax<- glue->method->clazz
movl %ecx, -12(%esp) # push parameter BBBB
movl %eax, -16(%esp) # push parameter glue->method>clazz
lea -16(%esp), %esp
call dvmResolveClass # resolve ClassObject pointer
# call: (const ClassObject* referrer, u4 classIdx,
# bool fromUnverifiedConstant)
# return ClassObject*
lea 16(%esp), %esp
cmp $$0, %eax # check for null pointer
je common_exceptionThrown # handle excpetion
movl %eax, %ecx # %ecx<- resolved class
jmp .L${opcode}_resolved
.LstrClassCastExceptionPtr:
.asciz "Ljava/lang/ClassCastException;"