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