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