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 #ifndef ECMASCRIPT_COMPILER_AARCH64_EXTENDED_ASSEMBLER_H 17 #define ECMASCRIPT_COMPILER_AARCH64_EXTENDED_ASSEMBLER_H 18 19 #include "ecmascript/compiler/assembler/aarch64/assembler_aarch64.h" 20 #include "ecmascript/compiler/assembler/aarch64/extend_assembler.h" 21 #include "ecmascript/frames.h" 22 23 namespace panda::ecmascript::aarch64 { 24 25 enum class FrameTransitionType : uint8_t { 26 BASELINE_TO_OTHER, 27 BASELINE_TO_BASELINE_CHECK, 28 OTHER_TO_BASELINE_CHECK, 29 OTHER_TO_OTHER 30 }; 31 32 using Label = panda::ecmascript::Label; 33 class CommonCall { 34 public: 35 static constexpr int FRAME_SLOT_SIZE = 8; 36 static constexpr int DOUBLE_SLOT_SIZE = 16; 37 static constexpr int TRIPLE_SLOT_SIZE = 24; 38 static constexpr int QUADRUPLE_SLOT_SIZE = 32; 39 static constexpr int QUINTUPLE_SLOT_SIZE = 40; 40 static constexpr int OCTUPLE_SLOT_SIZE = 64; 41 static constexpr int NONUPLE_SLOT_SIZE = 72; 42 static constexpr int FRAME_SLOT_SIZE_LOG2 = 3; 43 enum BuiltinsLeaveFrameArgId : unsigned {CODE_ADDRESS = 0, ENV, ARGC, ARGV}; GetStackArgOffSetToFp(unsigned argId)44 static inline int64_t GetStackArgOffSetToFp(unsigned argId) 45 { 46 // +--------------------------+ 47 // | argv0 | calltarget , newtARGET, this, .... 48 // +--------------------------+ --- 49 // | argc | ^ 50 // |--------------------------| arguments 51 // | env | | 52 // |--------------------------| | 53 // | codeAddress | | 54 // |--------------------------| | 55 // | returnAddr | | 56 // |--------------------------| Fixed OptimizedBuiltinLeaveFrame 57 // | callsiteFp | | 58 // |--------------------------| | 59 // | frameType | v 60 // +--------------------------+ --- 61 // 16 : 16 means arguments offset to fp 62 return 16 + static_cast<int64_t>(argId) * static_cast<int64_t>(FRAME_SLOT_SIZE); 63 } 64 static void PushUndefinedWithArgc(ExtendedAssembler *assembler, Register glue, Register argc, Register temp, 65 Register fp, Label *next, Label *stackOverflow); 66 static void PushArgsWithArgv(ExtendedAssembler *assembler, Register glue, Register argc, Register argv, 67 Register op, Register fp, Label *next, Label *stackOverflow); 68 static void PushArgsWithArgvInPair(ExtendedAssembler *assembler, Register argc, Register argv, Register padding, 69 Register op1, Register op2, Label *next); 70 static void PushAsmInterpBridgeFrame(ExtendedAssembler *assembler); 71 static void PopAsmInterpBridgeFrame(ExtendedAssembler *assembler); 72 static void StackOverflowCheck(ExtendedAssembler *assembler, Register glue, Register currentSlot, Register numArgs, 73 Register op, Label *stackOverflow); 74 static void PushLeaveFrame(ExtendedAssembler *assembler, Register glue); 75 static void PopLeaveFrame(ExtendedAssembler *assembler); 76 static void PushAsmBridgeFrame(ExtendedAssembler *assembler); 77 static void PopAsmBridgeFrame(ExtendedAssembler *assembler); 78 }; 79 80 class OptimizedCall : public CommonCall { 81 public: 82 static void CallRuntime(ExtendedAssembler *assembler); 83 84 static void JSFunctionEntry(ExtendedAssembler *assembler); 85 86 static void OptimizedCallAndPushArgv(ExtendedAssembler *assembler); 87 88 static void JSProxyCallInternalWithArgV(ExtendedAssembler *assembler); 89 90 static void JSCall(ExtendedAssembler *assembler); 91 92 static void CallOptimized(ExtendedAssembler *assembler); 93 94 static void CallRuntimeWithArgv(ExtendedAssembler *assembler); 95 96 static void JSCallWithArgV(ExtendedAssembler *assembler); 97 98 static void JSCallWithArgVAndPushArgv(ExtendedAssembler *assembler); 99 100 static void SuperCallWithArgV(ExtendedAssembler *assembler); 101 102 static void AOTCallToAsmInterBridge(ExtendedAssembler *assembler); 103 104 static void FastCallToAsmInterBridge(ExtendedAssembler *assembler); 105 106 static void DeoptHandlerAsm(ExtendedAssembler *assembler); 107 108 static void JSCallNew(ExtendedAssembler *assembler); 109 110 static void GenJSCall(ExtendedAssembler *assembler, bool isNew); 111 112 static void GenJSCallWithArgV(ExtendedAssembler *assembler, int id); 113 private: 114 static void DeoptEnterAsmInterp(ExtendedAssembler *assembler); 115 static void JSCallCheck(ExtendedAssembler *assembler, Register jsfunc, Register taggedValue, 116 Label *nonCallable, Label *notJSFunction); 117 static void ThrowNonCallableInternal(ExtendedAssembler *assembler, Register sp); 118 static void JSBoundFunctionCallInternal(ExtendedAssembler *assembler, Register glue, 119 Register actualArgC, Register jsfunc, int stubId); 120 static void OptimizedCallAsmInterpreter(ExtendedAssembler *assembler); 121 static void PushMandatoryJSArgs(ExtendedAssembler *assembler, Register jsfunc, 122 Register thisObj, Register newTarget, Register currentSp); 123 static void PopJSFunctionArgs(ExtendedAssembler *assembler, Register expectedNumArgs, Register actualNumArgs); 124 static void PushJSFunctionEntryFrame(ExtendedAssembler *assembler, Register prevFp); 125 static void PopJSFunctionEntryFrame(ExtendedAssembler *assembler, Register glue); 126 static void PushOptimizedUnfoldArgVFrame(ExtendedAssembler *assembler, Register callSiteSp); 127 static void PopOptimizedUnfoldArgVFrame(ExtendedAssembler *assembler); 128 static void IncreaseStackForArguments(ExtendedAssembler *assembler, Register argC, Register fp, 129 int64_t numExtraArgs = 0); 130 static void PushOptimizedArgsConfigFrame(ExtendedAssembler *assembler); 131 static void PopOptimizedArgsConfigFrame(ExtendedAssembler *assembler); 132 static void JSCallInternal(ExtendedAssembler *assembler, Register jsfunc, bool isNew = false); 133 static void CallBuiltinTrampoline(ExtendedAssembler *assembler); 134 static void CallBuiltinConstructorStub(ExtendedAssembler *assembler, Register builtinStub, Register argv, 135 Register glue, Register temp); 136 friend class OptimizedFastCall; 137 }; 138 139 class OptimizedFastCall : public CommonCall { 140 public: 141 static void OptimizedFastCallEntry(ExtendedAssembler *assembler); 142 143 static void OptimizedFastCallAndPushArgv(ExtendedAssembler *assembler); 144 145 static void JSFastCallWithArgV(ExtendedAssembler *assembler); 146 147 static void JSFastCallWithArgVAndPushArgv(ExtendedAssembler *assembler); 148 }; 149 150 class AsmInterpreterCall : public CommonCall { 151 public: 152 static void AsmInterpreterEntry(ExtendedAssembler *assembler); 153 154 static void AsmInterpEntryDispatch(ExtendedAssembler *assembler); 155 156 static void GeneratorReEnterAsmInterp(ExtendedAssembler *assembler); 157 158 static void GeneratorReEnterAsmInterpDispatch(ExtendedAssembler *assembler); 159 160 static void PushCallThisRangeAndDispatch(ExtendedAssembler *assembler); 161 162 static void PushCallRangeAndDispatch(ExtendedAssembler *assembler); 163 164 static void PushCallArgs3AndDispatch(ExtendedAssembler *assembler); 165 166 static void PushCallArgs2AndDispatch(ExtendedAssembler *assembler); 167 168 static void PushCallArg1AndDispatch(ExtendedAssembler *assembler); 169 170 static void PushCallArg0AndDispatch(ExtendedAssembler *assembler); 171 172 static void PushCallThisArg0AndDispatch(ExtendedAssembler *assembler); 173 174 static void PushCallThisArg1AndDispatch(ExtendedAssembler *assembler); 175 176 static void PushCallThisArgs2AndDispatch(ExtendedAssembler *assembler); 177 178 static void PushCallThisArgs3AndDispatch(ExtendedAssembler *assembler); 179 180 static void PushCallThisRangeAndDispatchNative(ExtendedAssembler *assembler); 181 182 static void PushCallRangeAndDispatchNative(ExtendedAssembler *assembler); 183 184 static void PushCallNewAndDispatchNative(ExtendedAssembler *assembler); 185 186 static void PushNewTargetAndDispatchNative(ExtendedAssembler *assembler); 187 188 static void PushCallNewAndDispatch(ExtendedAssembler *assembler); 189 190 static void PushSuperCallAndDispatch(ExtendedAssembler *assembler); 191 192 static void PushCallArgsAndDispatchNative(ExtendedAssembler *assembler); 193 194 static void ResumeRspAndDispatch(ExtendedAssembler *assembler); 195 196 static void ResumeRspAndReturn([[maybe_unused]] ExtendedAssembler *assembler); 197 198 static void ResumeRspAndReturnBaseline([[maybe_unused]] ExtendedAssembler *assembler); 199 200 static void ResumeCaughtFrameAndDispatch(ExtendedAssembler *assembler); 201 202 static void ResumeUncaughtFrameAndReturn(ExtendedAssembler *assembler); 203 204 static void ResumeRspAndRollback(ExtendedAssembler *assembler); 205 206 static void CallGetter(ExtendedAssembler *assembler); 207 208 static void CallSetter(ExtendedAssembler *assembler); 209 210 static void CallContainersArgs2(ExtendedAssembler *assembler); 211 212 static void CallContainersArgs3(ExtendedAssembler *assembler); 213 214 static void CallReturnWithArgv([[maybe_unused]]ExtendedAssembler *assembler); 215 216 static void ASMFastWriteBarrier(ExtendedAssembler *assembler); 217 218 static void ASMWriteBarrierWithEden(ExtendedAssembler *assembler); 219 220 static void ASMFastSharedWriteBarrier(ExtendedAssembler *assembler, Label& needCall); 221 private: 222 static void PushCallThis(ExtendedAssembler *assembler, JSCallMode mode, 223 Label *stackOverflow, FrameTransitionType type); 224 225 static Register GetThisRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister); 226 static Register GetNewTargetRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister); 227 228 static void PushVregs(ExtendedAssembler *assembler, Label *stackOverflow, FrameTransitionType type); 229 230 static void DispatchCall(ExtendedAssembler *assembler, Register pc, Register newSp, 231 Register acc = INVALID_REG); 232 233 static void CallNativeInternal(ExtendedAssembler *assembler, Register nativeCode); 234 235 static bool PushBuiltinFrame(ExtendedAssembler *assembler, Register glue, 236 FrameType type, Register op, Register next); 237 238 static void ThrowStackOverflowExceptionAndReturn(ExtendedAssembler *assembler, Register glue, Register fp, 239 Register op); 240 241 static void PushFrameState(ExtendedAssembler *assembler, Register prevSp, Register fp, Register currentSlot, 242 Register callTarget, Register thisObj, Register method, Register pc, Register op); 243 244 static void JSCallCommonEntry(ExtendedAssembler *assembler, JSCallMode mode, FrameTransitionType type); 245 246 static void JSCallCommonFastPath(ExtendedAssembler *assembler, JSCallMode mode, Label *pushCallThis, 247 Label *stackOverflow); 248 static void JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMode mode, 249 Label *fastPathEntry, Label *pushCallThis, Label *stackOverflow); 250 251 static void GetNumVregsFromCallField(ExtendedAssembler *assembler, Register callField, Register numVregs); 252 253 static void GetDeclaredNumArgsFromCallField(ExtendedAssembler *assembler, Register callField, 254 Register declaredNumArgs); 255 256 static void SaveFpAndJumpSize(ExtendedAssembler *assembler, Immediate jumpSize); 257 258 static void PushAsmInterpEntryFrame(ExtendedAssembler *assembler); 259 260 static void PopAsmInterpEntryFrame(ExtendedAssembler *assembler); 261 262 static void PushGeneratorFrameState(ExtendedAssembler *assembler, Register &prevSpRegister, Register &fpRegister, 263 Register ¤tSlotRegister, Register &callTargetRegister, Register &thisRegister, Register &methodRegister, 264 Register &contextRegister, Register &pcRegister, Register &operatorRegister); 265 266 static void CallBCStub(ExtendedAssembler *assembler, Register &newSp, Register &glue, 267 Register &callTarget, Register &method, Register &pc, Register &temp); 268 269 static void CallNativeEntry(ExtendedAssembler *assembler); 270 271 static void CallFastBuiltin(ExtendedAssembler *assembler, Label *callNativeBuiltin); 272 273 static void CallNativeWithArgv(ExtendedAssembler *assembler, bool callNew, bool hasNewTarget = false); 274 static void PreserveMostCall(ExtendedAssembler* assembler); 275 friend class OptimizedCall; 276 friend class BaselineCall; 277 }; 278 279 class BaselineCall : public CommonCall { 280 public: 281 /* other call baseline: need to check whether baseline code exists */ 282 static void CallArg0AndCheckToBaseline(ExtendedAssembler *assembler); 283 static void CallArg1AndCheckToBaseline(ExtendedAssembler *assembler); 284 static void CallArgs2AndCheckToBaseline(ExtendedAssembler *assembler); 285 static void CallArgs3AndCheckToBaseline(ExtendedAssembler *assembler); 286 static void CallThisArg0AndCheckToBaseline(ExtendedAssembler *assembler); 287 static void CallThisArg1AndCheckToBaseline(ExtendedAssembler *assembler); 288 static void CallThisArgs2AndCheckToBaseline(ExtendedAssembler *assembler); 289 static void CallThisArgs3AndCheckToBaseline(ExtendedAssembler *assembler); 290 static void CallRangeAndCheckToBaseline(ExtendedAssembler *assembler); 291 static void CallNewAndCheckToBaseline(ExtendedAssembler *assembler); 292 static void SuperCallAndCheckToBaseline(ExtendedAssembler *assembler); 293 static void CallThisRangeAndCheckToBaseline(ExtendedAssembler *assembler); 294 /* baseline call other: need to save fp and lr */ 295 static void CallArg0AndDispatchFromBaseline(ExtendedAssembler *assembler); 296 static void CallArg1AndDispatchFromBaseline(ExtendedAssembler *assembler); 297 static void CallArgs2AndDispatchFromBaseline(ExtendedAssembler *assembler); 298 static void CallArgs3AndDispatchFromBaseline(ExtendedAssembler *assembler); 299 static void CallThisArg0AndDispatchFromBaseline(ExtendedAssembler *assembler); 300 static void CallThisArg1AndDispatchFromBaseline(ExtendedAssembler *assembler); 301 static void CallThisArgs2AndDispatchFromBaseline(ExtendedAssembler *assembler); 302 static void CallThisArgs3AndDispatchFromBaseline(ExtendedAssembler *assembler); 303 static void CallRangeAndDispatchFromBaseline(ExtendedAssembler *assembler); 304 static void CallNewAndDispatchFromBaseline(ExtendedAssembler *assembler); 305 static void SuperCallAndDispatchFromBaseline(ExtendedAssembler *assembler); 306 static void CallThisRangeAndDispatchFromBaseline(ExtendedAssembler *assembler); 307 /* baseline call baseline: need to check whether baseline code exists and save fp and lr */ 308 static void CallArg0AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler); 309 static void CallArg1AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler); 310 static void CallArgs2AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler); 311 static void CallArgs3AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler); 312 static void CallThisArg0AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler); 313 static void CallThisArg1AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler); 314 static void CallThisArgs2AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler); 315 static void CallThisArgs3AndCheckToBaselineFromBaseline(ExtendedAssembler *assembler); 316 static void CallRangeAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler); 317 static void CallNewAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler); 318 static void SuperCallAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler); 319 static void CallThisRangeAndCheckToBaselineFromBaseline(ExtendedAssembler *assembler); 320 /* get baselineBuiltinFp when baselineBuiltin call the others */ 321 static void GetBaselineBuiltinFp(ExtendedAssembler *assembler); 322 }; 323 324 } // namespace panda::ecmascript::x64 325 #endif // ECMASCRIPT_COMPILER_ASSEMBLER_MODULE_X64_H 326