• 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/amd64/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#include "arch/amd64/helpers_amd64.S"
24
25// Frame* CreateFrameForMethod(Method* method, Frame* prev);
26.extern CreateFrameForMethod
27// void InterpreterEntryPoint(const uint8_t* pc, Frame* frame);
28.extern InterpreterEntryPoint
29
30.extern DecrementHotnessCounter
31
32.global CompiledCodeToInterpreterBridge
33TYPE_FUNCTION(CompiledCodeToInterpreterBridge)
34CompiledCodeToInterpreterBridge:
35    CFI_STARTPROC
36    CFI_DEF_CFA(rsp, 8)
37
38    // Save return address to the TLS field
39    movq (%rsp), %rax
40    movq %rax, MANAGED_THREAD_NATIVE_PC_OFFSET(%THREAD_REG)
41
42    pushq $COMPILED_CODE_TO_INTERPRETER_BRIDGE
43    CFI_ADJUST_CFA_OFFSET(8)
44
45    // construct the frame
46    pushq %rbp
47    CFI_ADJUST_CFA_OFFSET(8)
48    CFI_REL_OFFSET(rbp, 0)
49    movq %rsp, %rbp // set frame pointer
50    CFI_DEF_CFA_REGISTER(rbp)
51
52    subq $8, %rsp
53
54    // save all the callee saved registers to the stack
55    // stack walker will read them during stack unwinding
56    pushq %r15
57    CFI_REL_OFFSET(r15, -(2 * 8))
58    pushq %r14
59    CFI_REL_OFFSET(r14, -(3 * 8))
60    pushq %r13
61    CFI_REL_OFFSET(r13, -(4 * 8))
62    pushq %r12
63    CFI_REL_OFFSET(r12, -(5 * 8))
64    pushq %rbx
65    CFI_REL_OFFSET(rbx, -(6 * 8))
66
67    subq $8, %rsp
68
69    // Before we call DecrementHotnessCounter we should set pointer to C2I frame in the TLS,
70    // because compilation may fall into safepoint, so we need to make caller's callee registers
71    // visible for the stack walker.
72    movq %rbp, MANAGED_THREAD_FRAME_OFFSET(%THREAD_REG)
73
74    PUSH_GENERAL_REGS
75    PUSH_FP_REGS
76
77    movq %THREAD_REG, %rsi
78    callq DecrementHotnessCounter@plt
79
80    cmpb $0, %al
81    je .Lnot_compiled
82
83    // Compilation successfully done, so recover caller's frame in the TLS, since C2I is not needed.
84    movq (%rbp), %r8
85    movq %r8, MANAGED_THREAD_FRAME_OFFSET(%THREAD_REG)
86
87    POP_FP_REGS
88    POP_GENERAL_REGS
89
90    movq %rbp, %rsp
91    addq $16, %rsp
92    movq (%rbp), %rbp
93    CFI_REMEMBER_STATE
94    CFI_RESTORE(rbp)
95    CFI_DEF_CFA(rsp, 8)
96
97    movq METHOD_COMPILED_ENTRY_POINT_OFFSET(%rdi), %rax
98    jmp *%rax
99    CFI_RESTORE_STATE
100    CFI_DEF_CFA(rbp, (3 * 8))
101
102.Lnot_compiled:
103
104    POP_FP_REGS
105    POP_GENERAL_REGS
106
107    // save arguments to the stack
108    PUSH_FP_REGS
109    PUSH_GENERAL_REGS
110
111    // %rsp % 16 == 0 here
112
113    movq %rdi, %rbx // save method to survive the call
114
115    // create an interpreter frame
116    movq %rbx, %rdi
117    movq %rbp, %rsi
118    callq CreateFrameForMethod@plt
119    movq %rax, %r13
120
121    // setup regs as follow
122    // %rax - SHORTY_PTR_REG, %r10d - SHORTY_REG, %r12 - iframe.vregs_ + num_vregs_,
123    // %rdx - gpr args, %rsi - float args, %rdi - stack args, %r8d - gpr arg counter,
124    // %r9d - float arg counter, %rcx, %r15 - temp, %r13 - iframe, %rbx - method,
125    // %r14 - method.shorty
126    movq METHOD_SHORTY_OFFSET(%rbx), %r14
127    movl FRAME_NUM_VREGS_OFFSET(%r13), %r12d
128    subl METHOD_NUM_ARGS_OFFSET(%rbx), %r12d
129    shlq $3, %r12
130    leaq FRAME_VREGS_OFFSET(%r13, %r12), %r12
131    leaq 8(%rsp), %rdx // skip Method*
132    leaq 48(%rsp), %rsi
133    leaq 24(%rbp), %rdi
134    movl $5, %r8d  // 5 because we skip Method* arg
135    movl $8, %r9d
136
137    movq %r14, %rax
138    INIT_SHORTY_REG
139
140    // parameter 'this' of instance methods is not encoded in the shorty
141    // in case of instance method hack SHORTY_REG by replacing the return type by REF
142    // in the another case just skip the return type
143
144    // check whether the method is an instance
145    movl METHOD_ACCESS_FLAGS_OFFSET(%rbx), %ecx
146    testl $ACCESS_STATIC, %ecx
147    jne 1f
148
149    // it is an instance method
150    // replace the return type by REF
151    andl $0xFFFFFFF0, %SHORTY_REG // clear the least significant 4  bits
152    orl $SHORTY_REFERENCE, %SHORTY_REG
153    jmp .Lloop_copy_args
154
1551:
156    SKIP_SHORTY
157
158    // fill in the iframe
159.Lloop_copy_args:
160    NEXT_SHORTY %r11d
161    cmpl $0, %r11d
162    je .Lloopend_copy_args
163
164    // store the tag
165    xorq %rcx, %rcx
166    cmpl $SHORTY_REFERENCE, %r11d
167    sete %cl
168    movl FRAME_NUM_VREGS_OFFSET(%r13), %r15d
169    movq %rcx, (%r12, %r15, 8)
170
171    subl $SHORTY_FIRST_FLOAT, %r11d
172    cmpl $(SHORTY_NUM_FLOAT_TYPES - 1), %r11d
173    jbe 1f
174
175    // it is an int value or reference
176    cmpl $0, %r8d
177    je 2f
178
179    // the arg in a gpr
180    movq (%rdx), %r15
181    addq $8, %rdx
182    subl $1, %r8d
183    jmp 3f
1841:
185    // it is a float value
186    cmpl $0, %r9d
187    je 2f
188
189    // the arg in a float reg
190    movq (%rsi), %r15
191    addq $8, %rsi
192    subl $1, %r9d
193    jmp 3f
1942:
195    // it is a stack arg
196    movq (%rdi), %r15
197    addq $8, %rdi
1983:
199    movq %r15, (%r12)
200    addq $FRAME_VREGISTER_SIZE, %r12
201    jmp .Lloop_copy_args
202.Lloopend_copy_args:
203
204    // call InterpreterEntryPoint
205    movq %rbx, %rdi
206    movq %r13, %rsi
207    callq InterpreterEntryPoint@plt
208
209    // handle the result
210    // setup regs as follow
211    // %rdi - iframe, %r14d - *method.shorty, %rax - &iframe.acc_
212    // %r12, %r13 - result
213    movq %r13, %rdi
214    leaq FRAME_ACC_OFFSET(%r13), %rax
215    movl (%r14), %r14d
216    andl $0xF, %r14d
217
218    cmpl $SHORTY_VOID, %r14d
219    jne 1f
220
221    // void method
222    callq FreeFrame@plt
223    jmp 4f
2241:
225    movq (%rax), %r12
226    movq FRAME_ACC_MIRROR_OFFSET(%rax), %r13
227    cmpl $SHORTY_REFERENCE, %r14d
228    jne 2f
229    // Result is a reference
230    callq FreeFrame@plt
231    // Clear the upper 32 bits, since the compiler may
232    // generate code that uses them
233    movl %r12d, %eax
234    movq %r13, %rdx
235    jmp 4f
2362:
237    subl $SHORTY_FIRST_FLOAT, %r14d
238    cmpl $(SHORTY_NUM_FLOAT_TYPES - 1), %r14d
239    jbe 3f
240    // result is an integer value
241    callq FreeFrame@plt
242    movq %r12, %rax
243    movq %r13, %rdx
244    jmp 4f
2453:
246    // result is a float value
247    callq FreeFrame@plt
248    movq %r12, %xmm0
2494:
250    leaq -48(%rbp), %rsp
251    popq %rbx
252    CFI_RESTORE(rbx)
253    popq %r12
254    CFI_RESTORE(r12)
255    popq %r13
256    CFI_RESTORE(r13)
257    popq %r14
258    CFI_RESTORE(r14)
259    popq %r15
260    CFI_RESTORE(r15)
261    addq $8, %rsp
262    popq %rbp
263    CFI_RESTORE(rbp)
264    CFI_DEF_CFA(rsp, (2 * 8))
265    addq $8, %rsp
266    CFI_ADJUST_CFA_OFFSET(-(1 * 8))
267    retq
268    CFI_ENDPROC
269