• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "ecmascript/compiler/assembler_module.h"
17 
18 #include "ecmascript/compiler/assembler/aarch64/assembler_aarch64.h"
19 #include "ecmascript/compiler/assembler/x64/assembler_x64.h"
20 #include "ecmascript/compiler/call_signature.h"
21 #include "ecmascript/compiler/circuit_builder.h"
22 #include "ecmascript/compiler/circuit_builder_helper.h"
23 #include "ecmascript/compiler/trampoline/aarch64/common_call.h"
24 #include "ecmascript/compiler/trampoline/x64/common_call.h"
25 #include "ecmascript/compiler/rt_call_signature.h"
26 
27 namespace panda::ecmascript::kungfu {
Run(const CompilationConfig * cfg,Chunk * chunk)28 void AssemblerModule::Run(const CompilationConfig *cfg, Chunk* chunk)
29 {
30     SetUpForAsmStubs();
31     if (cfg->IsAmd64()) {
32         GenerateStubsX64(chunk);
33     } else if (cfg->IsAArch64()) {
34         GenerateStubsAarch64(chunk);
35     } else {
36         LOG_ECMA(FATAL) << "this branch is unreachable";
37         UNREACHABLE();
38     }
39 }
40 
GenerateStubsX64(Chunk * chunk)41 void AssemblerModule::GenerateStubsX64(Chunk* chunk)
42 {
43     x64::ExtendedAssembler assembler(chunk, this);
44     LOG_COMPILER(INFO) << "================ compiling asm stubs ================";
45     for (size_t i = 0; i < asmCallSigns_.size(); i++) {
46         auto cs = asmCallSigns_[i];
47         ASSERT(cs->HasConstructor());
48         LOG_COMPILER(INFO) << "Stub Name: " << cs->GetName();
49         AssemblerStub *stub = static_cast<AssemblerStub*>(
50             cs->GetConstructor()(nullptr));
51         stub->GenerateX64(&assembler);
52         delete stub;
53     }
54     buffer_ = assembler.GetBegin();
55     bufferSize_ = assembler.GetCurrentPosition();
56 }
57 
GenerateStubsAarch64(Chunk * chunk)58 void AssemblerModule::GenerateStubsAarch64(Chunk* chunk)
59 {
60     aarch64::ExtendedAssembler assembler(chunk, this);
61     LOG_COMPILER(INFO) << "================ compiling asm stubs ================";
62     for (size_t i = 0; i < asmCallSigns_.size(); i++) {
63         auto cs = asmCallSigns_[i];
64         ASSERT(cs->HasConstructor());
65         LOG_COMPILER(INFO) << "Stub Name: " << cs->GetName();
66         AssemblerStub *stub = static_cast<AssemblerStub*>(
67             cs->GetConstructor()(nullptr));
68         stub->GenerateAarch64(&assembler);
69         delete stub;
70     }
71     buffer_ = assembler.GetBegin();
72     bufferSize_ = assembler.GetCurrentPosition();
73 }
74 
SetUpForAsmStubs()75 void AssemblerModule::SetUpForAsmStubs()
76 {
77     RuntimeStubCSigns::GetASMCSigns(asmCallSigns_);
78     for (auto cs : asmCallSigns_) {
79         symbolTable_[cs->GetID()] = new panda::ecmascript::Label();
80     }
81 }
82 
GetArgcFromJSCallMode(JSCallMode mode)83 int AssemblerModule::GetArgcFromJSCallMode(JSCallMode mode)
84 {
85     switch (mode) {
86         case JSCallMode::CALL_ARG0:
87         case JSCallMode::CALL_THIS_ARG0:
88         case JSCallMode::DEPRECATED_CALL_ARG0:
89             return 0;
90         case JSCallMode::CALL_ARG1:
91         case JSCallMode::CALL_THIS_ARG1:
92         case JSCallMode::DEPRECATED_CALL_ARG1:
93             return 1;
94         case JSCallMode::CALL_ARG2:
95         case JSCallMode::CALL_THIS_ARG2:
96         case JSCallMode::DEPRECATED_CALL_ARG2:
97             return 2; // 2: arg2
98         case JSCallMode::CALL_ARG3:
99         case JSCallMode::CALL_THIS_ARG3:
100         case JSCallMode::DEPRECATED_CALL_ARG3:
101         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
102             return 3; // 3: arg3
103         case JSCallMode::CALL_THIS_WITH_ARGV:
104         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
105         case JSCallMode::CALL_WITH_ARGV:
106         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
107         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
108         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
109         case JSCallMode::SUPER_CALL_WITH_ARGV:
110         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
111         case JSCallMode::CALL_ENTRY:
112         case JSCallMode::CALL_FROM_AOT:
113         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
114             return -1;
115         case JSCallMode::CALL_GETTER:
116             return 0;
117         case JSCallMode::CALL_SETTER:
118             return 1;
119         default:
120             LOG_ECMA(FATAL) << "this branch is unreachable";
121             UNREACHABLE();
122     }
123 }
124 
IsCallNew(JSCallMode mode)125 bool AssemblerModule::IsCallNew(JSCallMode mode)
126 {
127     switch (mode) {
128         case JSCallMode::CALL_ARG0:
129         case JSCallMode::CALL_THIS_ARG0:
130         case JSCallMode::DEPRECATED_CALL_ARG0:
131         case JSCallMode::CALL_ARG1:
132         case JSCallMode::CALL_THIS_ARG1:
133         case JSCallMode::DEPRECATED_CALL_ARG1:
134         case JSCallMode::CALL_ARG2:
135         case JSCallMode::CALL_THIS_ARG2:
136         case JSCallMode::DEPRECATED_CALL_ARG2:
137         case JSCallMode::CALL_ARG3:
138         case JSCallMode::CALL_THIS_ARG3:
139         case JSCallMode::DEPRECATED_CALL_ARG3:
140         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
141         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
142         case JSCallMode::CALL_THIS_WITH_ARGV:
143         case JSCallMode::CALL_WITH_ARGV:
144         case JSCallMode::CALL_GETTER:
145         case JSCallMode::CALL_SETTER:
146         case JSCallMode::CALL_ENTRY:
147         case JSCallMode::CALL_FROM_AOT:
148         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
149         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
150             return false;
151         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
152         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
153         case JSCallMode::SUPER_CALL_WITH_ARGV:
154         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
155             return true;
156         default:
157             LOG_ECMA(FATAL) << "this branch is unreachable";
158             UNREACHABLE();
159     }
160     return false;
161 }
162 
JSModeHaveThisArg(JSCallMode mode)163 bool AssemblerModule::JSModeHaveThisArg(JSCallMode mode)
164 {
165     switch (mode) {
166         case JSCallMode::CALL_ARG0:
167         case JSCallMode::CALL_ARG1:
168         case JSCallMode::CALL_ARG2:
169         case JSCallMode::CALL_ARG3:
170         case JSCallMode::DEPRECATED_CALL_ARG0:
171         case JSCallMode::DEPRECATED_CALL_ARG1:
172         case JSCallMode::DEPRECATED_CALL_ARG2:
173         case JSCallMode::DEPRECATED_CALL_ARG3:
174         case JSCallMode::CALL_WITH_ARGV:
175         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
176             return false;
177         case JSCallMode::CALL_THIS_ARG0:
178         case JSCallMode::CALL_THIS_ARG1:
179         case JSCallMode::CALL_THIS_ARG2:
180         case JSCallMode::CALL_THIS_ARG3:
181         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
182         case JSCallMode::CALL_THIS_WITH_ARGV:
183         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
184         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
185         case JSCallMode::SUPER_CALL_WITH_ARGV:
186         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
187         case JSCallMode::CALL_ENTRY:
188         case JSCallMode::CALL_FROM_AOT:
189         case JSCallMode::CALL_GETTER:
190         case JSCallMode::CALL_SETTER:
191         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
192         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
193             return true;
194         default:
195             LOG_ECMA(FATAL) << "this branch is unreachable";
196             UNREACHABLE();
197     }
198 }
199 
JSModeHaveNewTargetArg(JSCallMode mode)200 bool AssemblerModule::JSModeHaveNewTargetArg(JSCallMode mode)
201 {
202     switch (mode) {
203         case JSCallMode::CALL_ARG0:
204         case JSCallMode::CALL_ARG1:
205         case JSCallMode::CALL_ARG2:
206         case JSCallMode::CALL_ARG3:
207         case JSCallMode::DEPRECATED_CALL_ARG0:
208         case JSCallMode::DEPRECATED_CALL_ARG1:
209         case JSCallMode::DEPRECATED_CALL_ARG2:
210         case JSCallMode::DEPRECATED_CALL_ARG3:
211         case JSCallMode::CALL_WITH_ARGV:
212         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
213         case JSCallMode::CALL_THIS_WITH_ARGV:
214         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
215         case JSCallMode::CALL_GETTER:
216         case JSCallMode::CALL_SETTER:
217         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
218         case JSCallMode::CALL_THIS_ARG0:
219         case JSCallMode::CALL_THIS_ARG1:
220         case JSCallMode::CALL_THIS_ARG2:
221         case JSCallMode::CALL_THIS_ARG3:
222         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
223             return false;
224         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
225         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
226         case JSCallMode::SUPER_CALL_WITH_ARGV:
227         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
228         case JSCallMode::CALL_ENTRY:
229         case JSCallMode::CALL_FROM_AOT:
230             return true;
231         default:
232             LOG_ECMA(FATAL) << "this branch is unreachable";
233             UNREACHABLE();
234     }
235 }
236 
IsJumpToCallCommonEntry(JSCallMode mode)237 bool AssemblerModule::IsJumpToCallCommonEntry(JSCallMode mode)
238 {
239     switch (mode) {
240         case JSCallMode::CALL_ARG0:
241         case JSCallMode::CALL_ARG1:
242         case JSCallMode::CALL_ARG2:
243         case JSCallMode::CALL_ARG3:
244         case JSCallMode::DEPRECATED_CALL_ARG0:
245         case JSCallMode::DEPRECATED_CALL_ARG1:
246         case JSCallMode::DEPRECATED_CALL_ARG2:
247         case JSCallMode::DEPRECATED_CALL_ARG3:
248         case JSCallMode::CALL_WITH_ARGV:
249         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
250         case JSCallMode::CALL_THIS_WITH_ARGV:
251         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
252         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
253         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
254         case JSCallMode::SUPER_CALL_WITH_ARGV:
255         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
256         case JSCallMode::CALL_THIS_ARG0:
257         case JSCallMode::CALL_THIS_ARG1:
258         case JSCallMode::CALL_THIS_ARG2:
259         case JSCallMode::CALL_THIS_ARG3:
260             return true;
261         case JSCallMode::CALL_GETTER:
262         case JSCallMode::CALL_SETTER:
263         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
264         case JSCallMode::CALL_ENTRY:
265         case JSCallMode::CALL_GENERATOR:
266         case JSCallMode::CALL_FROM_AOT:
267         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
268             return false;
269         default:
270             LOG_ECMA(FATAL) << "this branch is unreachable";
271             UNREACHABLE();
272     }
273     return false;
274 }
275 
276 #define DECLARE_JSCALL_TRAMPOLINE_X64_GENERATE(name)                                              \
277 void name##Stub::GenerateX64(Assembler *assembler)                                                \
278 {                                                                                                 \
279     x64::ExtendedAssembler *assemblerX64 = static_cast<x64::ExtendedAssembler*>(assembler);       \
280     x64::OptimizedCall::name(assemblerX64);                                                       \
281     assemblerX64->Align16();                                                                      \
282 }
283 
284 #define DECLARE_FAST_CALL_TRAMPOLINE_X64_GENERATE(name)                                           \
285 void name##Stub::GenerateX64(Assembler *assembler)                                                \
286 {                                                                                                 \
287     x64::ExtendedAssembler *assemblerX64 = static_cast<x64::ExtendedAssembler*>(assembler);       \
288     x64::OptimizedFastCall::name(assemblerX64);                                                   \
289     assemblerX64->Align16();                                                                      \
290 }
291 
292 #define DECLARE_ASM_INTERPRETER_TRAMPOLINE_X64_GENERATE(name)                                     \
293 void name##Stub::GenerateX64(Assembler *assembler)                                                \
294 {                                                                                                 \
295     x64::ExtendedAssembler *assemblerX64 = static_cast<x64::ExtendedAssembler*>(assembler);       \
296     x64::AsmInterpreterCall::name(assemblerX64);                                                  \
297     assemblerX64->Align16();                                                                      \
298 }
299 
300 
301 #define DECLARE_JSCALL_TRAMPOLINE_AARCH64_GENERATE(name)                                                \
302 void name##Stub::GenerateAarch64(Assembler *assembler)                                                  \
303 {                                                                                                       \
304     aarch64::ExtendedAssembler *assemblerAarch64 = static_cast<aarch64::ExtendedAssembler*>(assembler); \
305     aarch64::OptimizedCall::name(assemblerAarch64);                                                     \
306 }
307 
308 #define DECLARE_FAST_CALL_TRAMPOLINE_AARCH64_GENERATE(name)                                                \
309 void name##Stub::GenerateAarch64(Assembler *assembler)                                                  \
310 {                                                                                                       \
311     aarch64::ExtendedAssembler *assemblerAarch64 = static_cast<aarch64::ExtendedAssembler*>(assembler); \
312     aarch64::OptimizedFastCall::name(assemblerAarch64);                                                     \
313 }
314 
315 #define DECLARE_ASM_INTERPRETER_TRAMPOLINE_AARCH64_GENERATE(name)                                       \
316 void name##Stub::GenerateAarch64(Assembler *assembler)                                                  \
317 {                                                                                                       \
318     aarch64::ExtendedAssembler *assemblerAarch64 = static_cast<aarch64::ExtendedAssembler*>(assembler); \
319     aarch64::AsmInterpreterCall::name(assemblerAarch64);                                                \
320 }
321 
322 JS_CALL_TRAMPOLINE_LIST(DECLARE_JSCALL_TRAMPOLINE_X64_GENERATE)
323 FAST_CALL_TRAMPOLINE_LIST(DECLARE_FAST_CALL_TRAMPOLINE_X64_GENERATE)
324 ASM_INTERPRETER_TRAMPOLINE_LIST(DECLARE_ASM_INTERPRETER_TRAMPOLINE_X64_GENERATE)
325 JS_CALL_TRAMPOLINE_LIST(DECLARE_JSCALL_TRAMPOLINE_AARCH64_GENERATE)
326 FAST_CALL_TRAMPOLINE_LIST(DECLARE_FAST_CALL_TRAMPOLINE_AARCH64_GENERATE)
327 ASM_INTERPRETER_TRAMPOLINE_LIST(DECLARE_ASM_INTERPRETER_TRAMPOLINE_AARCH64_GENERATE)
328 #undef DECLARE_JSCALL_TRAMPOLINE_X64_GENERATE
329 #undef DECLARE_FAST_CALL_TRAMPOLINE_X64_GENERATE
330 #undef DECLARE_ASM_INTERPRETER_TRAMPOLINE_X64_GENERATE
331 #undef DECLARE_JSCALL_TRAMPOLINE_AARCH64_GENERATE
332 #undef DECLARE_FAST_CALL_TRAMPOLINE_AARCH64_GENERATE
333 #undef DECLARE_ASM_INTERPRETER_TRAMPOLINE_AARCH64_GENERATE
334 }  // namespace panda::ecmascript::kunfu
335