• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * Copyright (c) 2021-2022 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/helpers_amd64.S"
18
19// Frame* CreateFrameForMethodWithActualArgsDyn(uint32_t num_actual_args, Method* method, Frame* prev);
20.extern CreateFrameForMethodWithActualArgsDyn
21// void InterpreterEntryPoint(Method* pc, Frame* frame, bool is_dynamic);
22.extern InterpreterEntryPoint
23// void FreeFrame(Frame* frame);
24.extern FreeFrame
25// bool IncrementHotnessCounter(Method* method, bool is_dynamic);
26.extern IncrementHotnessCounter
27// DecodedTaggedValue GetInitialTaggedValue(Method*)
28.extern GetInitialTaggedValue
29
30// CompiledCodeToInterpreterBridgeDyn(Method* method, uint32_t num_args, int64_t func_obj, int64_t func_tag, int64_t arg_i, int64_t tag_i, ...)
31.global CompiledCodeToInterpreterBridgeDyn
32TYPE_FUNCTION(CompiledCodeToInterpreterBridgeDyn)
33CompiledCodeToInterpreterBridgeDyn:
34    CFI_STARTPROC
35    CFI_DEF_CFA(rsp, 8)
36
37    // method:      %rdi
38    // num_args:    %rsi
39    // func_obj:    %rdx
40    // arg_0:       %r8
41    // arg_i:       8*i(%rbp)
42    // tag_i:       8*(i+1)(%rbp)
43
44    // Save return address to the TLS field
45    movq (%rsp), %rax
46    movq %rax, MANAGED_THREAD_NATIVE_PC_OFFSET(%THREAD_REG)
47
48    pushq $COMPILED_CODE_TO_INTERPRETER_BRIDGE
49    CFI_ADJUST_CFA_OFFSET(8)
50
51    // construct the frame
52    pushq %rbp
53    CFI_ADJUST_CFA_OFFSET(8)
54    CFI_REL_OFFSET(rbp, 0)
55    movq %rsp, %rbp // set frame pointer
56    CFI_DEF_CFA_REGISTER(rbp)
57
58    subq $8, %rsp
59
60    // save all the callee saved registers to the stack
61    // stack walker will read them during stack unwinding
62    pushq %r15
63    CFI_REL_OFFSET(r15, -(2 * 8))
64    pushq %r14
65    CFI_REL_OFFSET(r14, -(3 * 8))
66    pushq %r13
67    CFI_REL_OFFSET(r13, -(4 * 8))
68    pushq %r12
69    CFI_REL_OFFSET(r12, -(5 * 8))
70    pushq %rbx
71    CFI_REL_OFFSET(rbx, -(6 * 8))
72
73    subq $8, %rsp
74
75    // Before we call IncrementHotnessCounter we should set pointer to C2I frame in the TLS,
76    // because compilation may fall into safepoint, so we need to make caller's callee registers
77    // visible for the stack walker.
78    movq %rbp, MANAGED_THREAD_FRAME_OFFSET(%THREAD_REG)
79
80    PUSH_GENERAL_REGS
81
82    callq IncrementHotnessCounter@plt
83    cmpb $0, %al
84    je .Lnot_compiled
85
86    // Compilation successfully done, so recover caller's frame in the TLS, since C2I is not needed.
87    movq (%rbp), %r8
88    movq %r8, MANAGED_THREAD_FRAME_OFFSET(%THREAD_REG)
89
90    POP_GENERAL_REGS
91
92    movq %rbp, %rsp
93    addq $16, %rsp
94    movq (%rbp), %rbp
95    CFI_REMEMBER_STATE
96    CFI_RESTORE(rbp)
97    CFI_DEF_CFA(rsp, 8)
98
99    movq METHOD_COMPILED_ENTRY_POINT_OFFSET(%rdi), %rax
100    jmp *%rax
101    CFI_RESTORE_STATE
102    CFI_DEF_CFA(rbp, (3 * 8))
103
104.Lnot_compiled:
105
106    POP_GENERAL_REGS
107
108    // save arguments to the stack
109    PUSH_GENERAL_REGS
110
111    // %rsp % 16 == 0 here
112
113    // save method* before call
114    movq %rdi, %r14
115
116    // create an interpreter frame
117    movq %rsi, %rdi
118    addq $1, %rdi // count function object
119    // get num args in r15d
120    // num_args = max(num_args, method->num_args_)
121    movl METHOD_NUM_ARGS_OFFSET(%r14), %r15d
122    cmpl %r15d, %edi
123    cmovge %edi, %r15d
124    // get number of rest arguments in r13
125    movl %r15d, %r13d
126    subl %edi, %r13d
127
128    movq %r14, %rsi
129    leaq (%rbp), %rdx
130    // Frame* CreateFrameForMethodWithActualArgsDyn(uint32_t num_actual_args, Method* method, Frame* prev);
131    callq CreateFrameForMethodWithActualArgsDyn@plt
132    movq %rax, %r12 // iframe*
133
134    POP_GENERAL_REGS
135
136    // setup regs as follow
137    // %rax         - iframe.vregs_ + num_vregs_
138    // %rdi         - stack args
139    // %rsi         - num args
140    // %rdx         - func obj
141    // %r8          - arg0
142    // %rbx         - method*
143    // %r12         - iframe*
144    // %r13         - num of rest arguments
145    movl FRAME_NUM_VREGS_OFFSET(%rax), %ebx
146    subl %r15d, %ebx
147    shll $3, %ebx
148    leaq FRAME_VREGS_OFFSET(%r12,%rbx), %rax
149    movq %rdi, %rbx // method*
150    leaq 24(%rbp), %rdi
151
152    movq %rdx, (%rax)
153    addq $FRAME_VREGISTER_SIZE, %rax
154    cmpl $0, %esi
155    je .Lrest_args
156
157    movq %r8, (%rax)
158    addq $FRAME_VREGISTER_SIZE, %rax
159    subl $1, %esi
160    je .Lrest_args
161
162.Lloop:
163    movq (%rdi), %rdx
164    addq $FRAME_VREGISTER_SIZE, %rdi
165
166    movq %rdx, (%rax)
167    addq $FRAME_VREGISTER_SIZE, %rax
168
169    subl $1, %esi
170    ja .Lloop
171
172.Lrest_args:
173    // mov rax to r14 to survive the call
174    movq %rax, %r14
175    // set the first arg Method*
176    movq %rbx, %rdi
177    callq GetInitialTaggedValue@plt
178
179    // setup regs as follow
180    // rax / rdx - initial value / tag
181    // %rbx - method*
182    // %r12 - iframe
183    // %r13 - num rest args
184    // %r14 - pointer to the current arg vreg
185
1861:  // fill in the reset args
187    test %r13, %r13
188    je .Lcall_interpreter
189    movq %rax, (%r14)
190    addq $FRAME_VREGISTER_SIZE, %r14
191    subl $1, %r13d
192    jmp 1b
193
194.Lcall_interpreter:
195    // call InterpreterEntryPoint
196    movq %rbx, %rdi
197    movq %r12, %rsi
198    // void InterpreterEntryPoint(Method *method, Frame* frame);
199    callq InterpreterEntryPoint@plt
200
201    // handle the result
202    // setup regs as follow
203    // %rax         - &iframe.acc_
204    // %r12         - iframe*
205    // %r13/%r14    - result
206    leaq FRAME_ACC_OFFSET(%r12), %rax
207
208    movq (%rax), %r13
209    movq FRAME_ACC_MIRROR_OFFSET(%rax), %r14
210
211    movq %r12, %rdi
212    // void FreeFrame(Frame* frame);
213    callq FreeFrame@plt
214
215    movq %r13, %rax
216    movq %r14, %rdx
217
218    leaq -48(%rbp), %rsp
219    popq %rbx
220    CFI_RESTORE(rbx)
221    popq %r12
222    CFI_RESTORE(r12)
223    popq %r13
224    CFI_RESTORE(r13)
225    popq %r14
226    CFI_RESTORE(r14)
227    popq %r15
228    CFI_RESTORE(r15)
229    addq $8, %rsp
230    popq %rbp
231    CFI_RESTORE(rbp)
232    CFI_DEF_CFA(rsp, (2 * 8))
233    addq $8, %rsp
234    CFI_ADJUST_CFA_OFFSET(-(1 * 8))
235    retq
236    CFI_ENDPROC
237