Home | History | Annotate | Download | only in x86-atom
      1    /* Copyright (C) 2008 The Android Open Source Project
      2     *
      3     * Licensed under the Apache License, Version 2.0 (the "License");
      4     * you may not use this file except in compliance with the License.
      5     * You may obtain a copy of the License at
      6     *
      7     * http://www.apache.org/licenses/LICENSE-2.0
      8     *
      9     * Unless required by applicable law or agreed to in writing, software
     10     * distributed under the License is distributed on an "AS IS" BASIS,
     11     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12     * See the License for the specific language governing permissions and
     13     * limitations under the License.
     14     */
     15 
     16    /*
     17     * File: OP_CHECK_CAST.S
     18     *
     19     * Code: Checks to see if a cast is allowed. Uses no substitutions.
     20     *
     21     * For: check-cast
     22     *
     23     * Description: Throw if the reference in the given register cannot be
     24     *              cast to the indicated type. The type must be a reference
     25     *              type (not a primitive type).
     26     *
     27     * Format: AA|op BBBB (21c)
     28     *
     29     * Syntax: op vAA, type@BBBB
     30     */
     31 
     32     movl        rGLUE, %edx             # get MterpGlue pointer
     33     movl        offGlue_methodClassDex(%edx), %eax # %eax<- pDvmDex
     34     GET_VREG    rINST                   # rINST<- vAA
     35     movl        offDvmDex_pResClasses(%eax), %eax # %eax<- pDvmDex->pResClasses
     36     cmp         $$0, rINST              # check for null reference object
     37     je          .L${opcode}_okay        # can always cast null object
     38     FETCH       1, %ecx                 # %ecx<- BBBB
     39     movl        (%eax, %ecx, 4), %ecx   # %ecx<- resolved class
     40     cmp         $$0, %ecx               # check if classes is resolved before?
     41     je          .L${opcode}_resolve     # resolve class
     42     jmp         .L${opcode}_resolved    # continue
     43 %break
     44 
     45 .L${opcode}_resolved:
     46     cmp         %ecx, offObject_clazz(rINST) # check for same class
     47     jne         .L${opcode}_fullcheck   # not same class; do full check
     48 
     49 .L${opcode}_okay:
     50     FINISH      2                       # jump to next instruction
     51 
     52    /*
     53     *  Trivial test failed, need to perform full check.
     54     *  offObject_clazz(rINST) holds obj->clazz
     55     *  %ecx holds class resolved from BBBB
     56     *  rINST holds object
     57     */
     58 
     59 .L${opcode}_fullcheck:
     60     movl        offObject_clazz(rINST), %eax  # %eax<- obj->clazz
     61     movl        %eax, -12(%esp)         # push parameter obj->clazz
     62     movl        %ecx, -8(%esp)          # push parameter # push parameter resolved class
     63     lea         -12(%esp), %esp
     64     call        dvmInstanceofNonTrivial # call: (ClassObject* instance, ClassObject* clazz)
     65                                         # return: int
     66     lea         12(%esp), %esp
     67     cmp         $$0, %eax               # failed?
     68     jne         .L${opcode}_okay        # success
     69 
     70    /*
     71     * A cast has failed.  We need to throw a ClassCastException with the
     72     * class of the object that failed to be cast.
     73     */
     74 
     75     EXPORT_PC                           # we will throw an exception
     76     movl        $$.LstrClassCastExceptionPtr, -8(%esp) # push parameter message
     77     movl        offObject_clazz(rINST), rINST # rINST<- obj->clazz
     78     movl        offClassObject_descriptor(rINST), rINST # rINST<- obj->clazz->descriptor
     79     movl        rINST, -4(%esp)         # push parameter obj->clazz->descriptor
     80     lea         -8(%esp), %esp
     81     call        dvmThrowExceptionWithClassMessage # call: (const char* exceptionDescriptor,
     82                                                   #       const char* messageDescriptor, Object* cause)
     83                                                   # return: void
     84     lea         8(%esp), %esp
     85     jmp         common_exceptionThrown
     86 
     87    /*
     88     * Resolution required.  This is the least-likely path.
     89     *
     90     *  rINST holds object
     91     */
     92 
     93 .L${opcode}_resolve:
     94     movl        offGlue_method(%edx), %eax # %eax<- glue->method
     95     FETCH       1, %ecx                 # %ecx holds BBBB
     96     EXPORT_PC                           # in case we throw an exception
     97     movl        $$0, -8(%esp)           # push parameter false
     98     movl        offMethod_clazz(%eax), %eax # %eax<- glue->method->clazz
     99     movl        %ecx, -12(%esp)         # push parameter BBBB
    100     movl        %eax, -16(%esp)         # push parameter glue->method>clazz
    101     lea         -16(%esp), %esp
    102     call        dvmResolveClass         # resolve ClassObject pointer
    103                                         # call: (const ClassObject* referrer, u4 classIdx,
    104                                         #        bool fromUnverifiedConstant)
    105                                         # return ClassObject*
    106     lea         16(%esp), %esp
    107     cmp         $$0, %eax               # check for null pointer
    108     je          common_exceptionThrown  # handle excpetion
    109     movl        %eax, %ecx              # %ecx<- resolved class
    110     jmp         .L${opcode}_resolved
    111 
    112 .LstrClassCastExceptionPtr:
    113 .asciz      "Ljava/lang/ClassCastException;"
    114