• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
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#include "arch/asm_support.h"
17#include "arch/arm/shorty.S"
18#include "shorty_values.h"
19
20#define SHORTY_PTR_REG DEFAULT_SHORTY_PTR_REG
21#define SHORTY_REG DEFAULT_SHORTY_REG
22
23// Frame* CreateFrameForMethod(Method* method, Frame* prev);
24.extern CreateFrameForMethod
25// void InterpreterEntryPoint(Method *method, Frame* frame);
26.extern InterpreterEntryPoint
27// bool DecrementHotnessCounter(Method *method);
28.extern DecrementHotnessCounter
29
30.global CompiledCodeToInterpreterBridge
31.type CompiledCodeToInterpreterBridge, %function
32CompiledCodeToInterpreterBridge:
33    CFI_STARTPROC
34    CFI_DEF_CFA(sp, 0)
35
36    // store r0-r3 before the frame to make arg array continuos with stack args
37    push {r0-r3}
38    CFI_ADJUST_CFA_OFFSET(16)
39
40    // construct the frame
41    mov r1, #COMPILED_CODE_TO_INTERPRETER_BRIDGE
42    push {r1, lr}
43    CFI_ADJUST_CFA_OFFSET(8)
44    CFI_REL_OFFSET(lr, 4)
45    push {r1, fp}
46    CFI_ADJUST_CFA_OFFSET(8)
47    CFI_REL_OFFSET(fp, 4)
48    add fp, sp, #4
49    CFI_ADJUST_CFA_OFFSET(-4)
50    CFI_DEF_CFA_REGISTER(fp)
51
52    // Save return address to the TLS field
53    str lr, [THREAD_REG, #MANAGED_THREAD_NATIVE_PC_OFFSET]
54
55    // save all the callee saved registers to the stack
56    // stack walker will read them during stack unwinding
57    push {r4 - r10}
58    CFI_REL_OFFSET(r10, -(2 * 4))
59    CFI_REL_OFFSET(r9,  -(3 * 4))
60    CFI_REL_OFFSET(r8,  -(4 * 4))
61    CFI_REL_OFFSET(r7,  -(5 * 4))
62    CFI_REL_OFFSET(r6,  -(6 * 4))
63    CFI_REL_OFFSET(r5,  -(7 * 4))
64    CFI_REL_OFFSET(r4,  -(8 * 4))
65
66#ifndef PANDA_TARGET_ARM32_ABI_SOFT
67    vpush {d8 - d15}
68    CFI_REL_OFFSET(d15, -(10 * 4))
69    CFI_REL_OFFSET(d14, -(12 * 4))
70    CFI_REL_OFFSET(d13, -(14 * 4))
71    CFI_REL_OFFSET(d12, -(16 * 4))
72    CFI_REL_OFFSET(d11, -(18 * 4))
73    CFI_REL_OFFSET(d10, -(20 * 4))
74    CFI_REL_OFFSET(d9,  -(22 * 4))
75    CFI_REL_OFFSET(d8,  -(24 * 4))
76#endif
77
78    // align to 8
79    sub sp, sp, #4
80
81    // Before we call DecrementHotnessCounter we should set pointer to C2I frame in the TLS,
82    // because compilation may fall into safepoint, so we need to make caller's callee registers
83    // visible for the stack walker.
84    str fp, [THREAD_REG, #MANAGED_THREAD_FRAME_OFFSET]
85
86    push {r0 - r3}
87    mov r1, THREAD_REG
88    blx DecrementHotnessCounter
89
90    cmp r0, #0
91    beq .Lnot_compiled
92
93    pop {r0 - r3}
94
95    // Compilation finished, so recover caller's frame in the TLS.
96    sub sp, fp, #4
97    CFI_REMEMBER_STATE
98    CFI_DEF_CFA(sp, 32)
99
100    pop {r1, fp}
101    CFI_ADJUST_CFA_OFFSET(-8)
102    CFI_RESTORE(fp)
103
104    str fp, [THREAD_REG, #MANAGED_THREAD_FRAME_OFFSET]
105    pop {r1, lr}
106    CFI_ADJUST_CFA_OFFSET(-8)
107    CFI_RESTORE(lr)
108    pop {r0-r3}
109    CFI_ADJUST_CFA_OFFSET(-16)
110
111    ldr pc, [r0, #METHOD_COMPILED_ENTRY_POINT_OFFSET]
112    CFI_RESTORE_STATE
113    CFI_DEF_CFA(fp, 28)
114
115.Lnot_compiled:
116    pop {r0 - r3}
117
118    // setup regs as follow
119    // r7 - method
120    mov r7, r0 // save method to survive the call
121
122    // create an interpreter frame
123    mov r1, fp
124    blx CreateFrameForMethod
125
126    // setup regs as follow
127    // r0 - SHORTY_PTR_REG, r1 - SHORTY_REG, r2 - iframe.vregs_ + num_vregs_,
128    // r3 - args, r4, r5, r9 - temp, r6 - iframe, r7 - method, r8 - method.shorty
129    mov r6, r0
130    ldr r5, [r6, #FRAME_NUM_VREGS_OFFSET]
131    mov r9, r5, lsl #3
132    ldr r0, [r7, #METHOD_NUM_ARGS_OFFSET]
133    sub r5, r5, r0
134    ldr r8, [r7, #METHOD_SHORTY_OFFSET]
135    mov SHORTY_PTR_REG, r8
136    INIT_SHORTY_REG
137    add r2, r6, #FRAME_VREGS_OFFSET
138    add r2, r2, r5, lsl #3
139    add r3, fp, #16
140
141    // parameter 'this' of instance methods is not encoded in the shorty
142    // in case of instance method hack SHORTY_REG by replacing the return type by REF
143    // in the another case just skip the return type
144
145    // check whether the method is an instance
146    ldr r4, [r7, #METHOD_ACCESS_FLAGS_OFFSET]
147    tst r4, #ACCESS_STATIC
148    bne 1f
149    // it is an instance method
150    // replace the return type by REF
151    bic r1, r1, #0xF // clear the the least significant 4  bits
152    orr r1, r1, #SHORTY_REFERENCE
153    b .Lloop_copy_args
1541:  SKIP_SHORTY
155
156    // fill in the iframe
157.Lloop_copy_args:
158    NEXT_SHORTY r4
159    cmp r4, #0
160    beq .Lloopend_copy_args
161
162    sub r4, r4, #SHORTY_FIRST_64
163    cmp r4, #(SHORTY_NUM_64BIT_TYPES - 1)
164    bls 1f
165    // it is a 32bit value of reference
166    // store the tag
167    cmp r4, #(SHORTY_REFERENCE - SHORTY_FIRST_64)
168    movne r5, #FRAME_VREGISTER_PRIMITIVE_TAG
169    moveq r5, #FRAME_VREGISTER_OBJECT_TAG
170    str r5, [r2, r9]
171    // store the value
172    ldr r4, [r3], #4
173    str r4, [r2]
174    b 2f
1751:  // it is a 64bit value
176    // make r3 8 bytes aligned
177    add r3, r3, #7
178    bic r3, r3, #7
179    ldm r3!, {r4, r5}
180    stm r2, {r4, r5}
181    mov r4, #FRAME_VREGISTER_PRIMITIVE_TAG
182    str r4, [r2, r9]
1832:
184    add r2, r2, #FRAME_VREGISTER_SIZE
185    b .Lloop_copy_args
186.Lloopend_copy_args:
187
188    // call InterpreterEntryPoint
189    mov r0, r7
190    mov r1, r6
191    blx InterpreterEntryPoint
192
193    // handle the result
194    // setup regs as follow
195    // r0 - iframe, r1 - *method.shorty, r2 - &iframe.acc_
196    // r4, r5 - result
197    mov r0, r6
198    ldrb r1, [r8]
199    add r2, r6, #FRAME_ACC_OFFSET
200    and r1, r1, #0xF
201
202    cmp r0, #SHORTY_VOID
203    bne 1f
204    // void method
205    blx FreeFrame
206    b 3f
2071:
208    sub r1, r1, #SHORTY_FIRST_64
209    cmp r1, #(SHORTY_NUM_64BIT_TYPES - 1)
210    bls 2f
211    // result is 32 bit integer or reference
212    ldr r4, [r2]
213    blx FreeFrame
214    mov r0, r4
215    b 3f
2162:  // result is 64bit integer
217    ldm r2, {r4, r5}
218    blx FreeFrame
219    mov r0, r4
220    mov r1, r5
221
2223:
223#ifndef PANDA_TARGET_ARM32_ABI_SOFT
224    sub sp, fp, #(4 + 7 * 4 + 8 * 8)
225    vpop {d8 - d15}
226    CFI_RESTORE(d15)
227    CFI_RESTORE(d14)
228    CFI_RESTORE(d13)
229    CFI_RESTORE(d12)
230    CFI_RESTORE(d11)
231    CFI_RESTORE(d10)
232    CFI_RESTORE(d9)
233    CFI_RESTORE(d8)
234#else
235    sub sp, fp, #(4 + 7 * 4)
236#endif
237
238    pop {r4 - r10}
239    CFI_RESTORE(r10)
240    CFI_RESTORE(r9)
241    CFI_RESTORE(r8)
242    CFI_RESTORE(r7)
243    CFI_RESTORE(r6)
244    CFI_RESTORE(r5)
245    CFI_RESTORE(r4)
246
247    ldr fp, [sp, #4]
248    CFI_DEF_CFA(sp, 32)
249    CFI_RESTORE(fp)
250
251    ldr lr, [sp, #12]
252    CFI_RESTORE(lr)
253    add sp, sp, #32 // c2i + r0 - r3
254    CFI_ADJUST_CFA_OFFSET(-32)
255    bx lr
256    CFI_ENDPROC
257