summaryrefslogtreecommitdiff
path: root/vm/mterp/x86-atom/OP_NEW_INSTANCE.S
blob: d65afb700914d588e6abf769ee5a0f3b1d7193f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
   /* 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_NEW_INSTANCE.S
    *
    * Code: Create a new instance of a given type. Uses no substitutions.
    *
    * For: new-instance
    *
    * Description: Construct a new instance of the indicated type,
    *              storing a reference to it in the destination.
    *              The type must refer to a non-array class.
    *
    *
    *
    * Format: AA|op BBBB (21c)
    *
    * Syntax: op vAA, type@BBBB
    *         op vAA, field@BBBB
    *         op vAA, string@BBBB
    */

    movl        rGLUE, %ecx             # %ecx<- pMterpGlue
    movl        offGlue_methodClassDex(%ecx), %ecx # %ecx<- glue->pDvmDex
    FETCH       1, %edx                 # %edx<- BBBB
    movl        offDvmDex_pResClasses(%ecx), %ecx # %ecx<- glue->pDvmDex->pResClasses
    movl        (%ecx, %edx, 4), %edx   # %edx<- vB
    EXPORT_PC                           # required for resolve
    cmp         $$0, %edx               # check for null
    je          .L${opcode}_resolve     # need to resolve

   /*
    *  %edx holds class object
    */

.L${opcode}_resolved:
    movzbl      offClassObject_status(%edx), %eax # %eax<- class status
    cmp         $$CLASS_INITIALIZED, %eax # check if class is initialized
    jne         .L${opcode}_needinit    # initialize class

   /*
    *  %edx holds class object
    */

.L${opcode}_initialized:
    testl       $$(ACC_INTERFACE|ACC_ABSTRACT), offClassObject_accessFlags(%edx)
    mov         $$ALLOC_DONT_TRACK, %eax # %eax<- flag for alloc call
    je          .L${opcode}_finish      # continue
    jmp         .L${opcode}_abstract    # handle abstract or interface

   /*
    *  %edx holds class object
    *  %eax holds flags for alloc call
    */

%break
.balign 32
.L${opcode}_finish:
    movl        %edx, -8(%esp)          # push parameter object
    movl        %eax, -4(%esp)          # push parameter flags
    lea         -8(%esp), %esp
    call        dvmAllocObject          # call: (ClassObject* clazz, int flags)
                                        # return: Object*
    cmp         $$0, %eax               # check for failure
    lea         8(%esp), %esp
    je          common_exceptionThrown  # handle exception
    SET_VREG    %eax, rINST             # vAA<- pObject
    FINISH      2                       # jump to next instruction

   /*
    * Class initialization required.
    *
    *  %edx holds class object
    */

.L${opcode}_needinit:
    movl        %edx, -4(%esp)          # push parameter object
    lea         -4(%esp), %esp
    call        dvmInitClass            # call: (ClassObject* clazz)
                                        # return: bool
    lea         4(%esp), %esp
    cmp         $$0, %eax               # check for failure
    movl        -4(%esp), %edx          # %edx<- object
    je          common_exceptionThrown  # handle exception
    testl       $$(ACC_INTERFACE|ACC_ABSTRACT), offClassObject_accessFlags(%edx)
    mov         $$ALLOC_DONT_TRACK, %eax # %eax<- flag for alloc call
    je          .L${opcode}_finish      # continue
    jmp         .L${opcode}_abstract    # handle abstract or interface

   /*
    * Resolution required.  This is the least-likely path.
    *
    *  BBBB in %eax
    */

.L${opcode}_resolve:


    movl        rGLUE, %ecx             # %ecx<- pMterpGlue
    FETCH       1, %eax                 # %eax<- BBBB
    movl        offGlue_method(%ecx), %ecx # %ecx<- glue->method
    movl        offMethod_clazz(%ecx), %ecx # %ecx<- glue->method->clazz
    movl        %ecx, -12(%esp)         # push parameter clazz
    movl        $$0, -4(%esp)           # push parameter false
    movl        %eax, -8(%esp)          # push parameter BBBB
    lea         -12(%esp), %esp
    call        dvmResolveClass         # call: (const ClassObject* referrer,
                                        #       u4 classIdx, bool fromUnverifiedConstant)
                                        # return: ClassObject*
    lea         12(%esp), %esp
    movl        %eax, %edx              # %edx<- pObject
    cmp         $$0, %edx               # check for failure
    jne         .L${opcode}_resolved    # continue
    jmp         common_exceptionThrown  # handle exception

   /*
    * We can't instantiate an abstract class or interface, so throw an
    * InstantiationError with the class descriptor as the message.
    *
    *  %edx holds class object
    */

.L${opcode}_abstract:
    movl        offClassObject_descriptor(%edx), %ecx # %ecx<- descriptor
    movl        %ecx, -4(%esp)          # push parameter descriptor
    movl        $$.LstrInstantiationErrorPtr, -8(%esp) # push parameter message
    lea         -8(%esp), %esp
    call        dvmThrowExceptionWithClassMessage # call: (const char* exceptionDescriptor,
                                                  #        const char* messageDescriptor)
                                                  # return: void
    jmp         common_exceptionThrown  # handle exception

.LstrInstantiationErrorPtr:
.asciz      "Ljava/lang/InstantiationError;"