• 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/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 IncrementHotnessCounter
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 IncrementHotnessCounter 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    callq IncrementHotnessCounter@plt
78
79    cmpb $0, %al
80    je .Lnot_compiled
81
82    // Compilation successfully done, so recover caller's frame in the TLS, since C2I is not needed.
83    movq (%rbp), %r8
84    movq %r8, MANAGED_THREAD_FRAME_OFFSET(%THREAD_REG)
85
86    POP_FP_REGS
87    POP_GENERAL_REGS
88
89    movq %rbp, %rsp
90    addq $16, %rsp
91    movq (%rbp), %rbp
92    CFI_REMEMBER_STATE
93    CFI_RESTORE(rbp)
94    CFI_DEF_CFA(rsp, 8)
95
96    movq METHOD_COMPILED_ENTRY_POINT_OFFSET(%rdi), %rax
97    jmp *%rax
98    CFI_RESTORE_STATE
99    CFI_DEF_CFA(rbp, (3 * 8))
100
101.Lnot_compiled:
102
103    POP_FP_REGS
104    POP_GENERAL_REGS
105
106    // save arguments to the stack
107    PUSH_FP_REGS
108    PUSH_GENERAL_REGS
109
110    // %rsp % 16 == 0 here
111
112    movq %rdi, %rbx // save method to survive the call
113
114    // create an interpreter frame
115    movq %rbx, %rdi
116    movq %rbp, %rsi
117    callq CreateFrameForMethod@plt
118    movq %rax, %r13
119
120    // setup regs as follow
121    // %rax - SHORTY_PTR_REG, %r10d - SHORTY_REG, %r12 - iframe.vregs_ + num_vregs_,
122    // %rdx - gpr args, %rsi - float args, %rdi - stack args, %r8d - gpr arg counter,
123    // %r9d - float arg counter, %rcx, %r15 - temp, %r13 - iframe, %rbx - method,
124    // %r14 - method.shorty
125    movq METHOD_SHORTY_OFFSET(%rbx), %r14
126    movl FRAME_NUM_VREGS_OFFSET(%r13), %r12d
127    subl METHOD_NUM_ARGS_OFFSET(%rbx), %r12d
128    shlq $3, %r12
129    leaq FRAME_VREGS_OFFSET(%r13, %r12), %r12
130    leaq 8(%rsp), %rdx // skip Method*
131    leaq 48(%rsp), %rsi
132    leaq 24(%rbp), %rdi
133    movl $5, %r8d  // 5 because we skip Method* arg
134    movl $8, %r9d
135
136    movq %r14, %rax
137    INIT_SHORTY_REG
138
139    // parameter 'this' of instance methods is not encoded in the shorty
140    // in case of instance method hack SHORTY_REG by replacing the return type by REF
141    // in the another case just skip the return type
142
143    // check whether the method is an instance
144    movl METHOD_ACCESS_FLAGS_OFFSET(%rbx), %ecx
145    testl $ACCESS_STATIC, %ecx
146    jne 1f
147
148    // it is an instance method
149    // replace the return type by REF
150    andl $0xFFFFFFF0, %SHORTY_REG // clear the least significant 4  bits
151    orl $SHORTY_REFERENCE, %SHORTY_REG
152    jmp .Lloop_copy_args
153
1541:
155    SKIP_SHORTY
156
157    // fill in the iframe
158.Lloop_copy_args:
159    NEXT_SHORTY %r11d
160    cmpl $0, %r11d
161    je .Lloopend_copy_args
162
163    // store the tag
164    xorq %rcx, %rcx
165    cmpl $SHORTY_REFERENCE, %r11d
166    sete %cl
167    movl FRAME_NUM_VREGS_OFFSET(%r13), %r15d
168    movq %rcx, (%r12, %r15, 8)
169
170    subl $SHORTY_FIRST_FLOAT, %r11d
171    cmpl $(SHORTY_NUM_FLOAT_TYPES - 1), %r11d
172    jbe 1f
173
174    // it is an int value or reference
175    cmpl $0, %r8d
176    je 2f
177
178    // the arg in a gpr
179    movq (%rdx), %r15
180    addq $8, %rdx
181    subl $1, %r8d
182    jmp 3f
1831:
184    // it is a float value
185    cmpl $0, %r9d
186    je 2f
187
188    // the arg in a float reg
189    movq (%rsi), %r15
190    addq $8, %rsi
191    subl $1, %r9d
192    jmp 3f
1932:
194    // it is a stack arg
195    movq (%rdi), %r15
196    addq $8, %rdi
1973:
198    movq %r15, (%r12)
199    addq $FRAME_VREGISTER_SIZE, %r12
200    jmp .Lloop_copy_args
201.Lloopend_copy_args:
202
203    // call InterpreterEntryPoint
204    movq %rbx, %rdi
205    movq %r13, %rsi
206    callq InterpreterEntryPoint@plt
207
208    // handle the result
209    // setup regs as follow
210    // %rdi - iframe, %r14d - *method.shorty, %rax - &iframe.acc_
211    // %r12, %r13 - result
212    movq %r13, %rdi
213    leaq FRAME_ACC_OFFSET(%r13), %rax
214    movl (%r14), %r14d
215    andl $0xF, %r14d
216
217    cmpl $SHORTY_VOID, %r14d
218    jne 1f
219
220    // void method
221    callq FreeFrame@plt
222    jmp 3f
2231:
224    movq (%rax), %r12
225    movq FRAME_ACC_MIRROR_OFFSET(%rax), %r13
226    subl $SHORTY_FIRST_FLOAT, %r14d
227    cmpl $(SHORTY_NUM_FLOAT_TYPES - 1), %r14d
228    jbe 2f
229
230    // result is an integer or reference value
231    callq FreeFrame@plt
232    movq %r12, %rax
233    movq %r13, %rdx
234    jmp 3f
2352:
236    // result is a float value
237    callq FreeFrame@plt
238    movq %r12, %xmm0
2393:
240    leaq -48(%rbp), %rsp
241    popq %rbx
242    CFI_RESTORE(rbx)
243    popq %r12
244    CFI_RESTORE(r12)
245    popq %r13
246    CFI_RESTORE(r13)
247    popq %r14
248    CFI_RESTORE(r14)
249    popq %r15
250    CFI_RESTORE(r15)
251    addq $8, %rsp
252    popq %rbp
253    CFI_RESTORE(rbp)
254    CFI_DEF_CFA(rsp, (2 * 8))
255    addq $8, %rsp
256    CFI_ADJUST_CFA_OFFSET(-(1 * 8))
257    retq
258    CFI_ENDPROC
259