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