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 using Label = panda::ecmascript::Label; 25 class CommonCall { 26 public: 27 static constexpr int FRAME_SLOT_SIZE = 8; 28 static constexpr int DOUBLE_SLOT_SIZE = 16; 29 static constexpr int TRIPLE_SLOT_SIZE = 24; 30 static constexpr int QUADRUPLE_SLOT_SIZE = 32; 31 static constexpr int QUINTUPLE_SLOT_SIZE = 40; 32 static constexpr int OCTUPLE_SLOT_SIZE = 64; 33 static constexpr int FRAME_SLOT_SIZE_LOG2 = 3; 34 enum BuiltinsLeaveFrameArgId : unsigned {CODE_ADDRESS = 0, ENV, ARGC, ARGV}; GetStackArgOffSetToFp(unsigned argId)35 static inline int64_t GetStackArgOffSetToFp(unsigned argId) 36 { 37 // +--------------------------+ 38 // | argv0 | calltarget , newtARGET, this, .... 39 // +--------------------------+ --- 40 // | argc | ^ 41 // |--------------------------| arguments 42 // | env | | 43 // |--------------------------| | 44 // | codeAddress | | 45 // |--------------------------| | 46 // | returnAddr | | 47 // |--------------------------| Fixed OptimizedBuiltinLeaveFrame 48 // | callsiteFp | | 49 // |--------------------------| | 50 // | frameType | v 51 // +--------------------------+ --- 52 // 16 : 16 means arguments offset to fp 53 return 16 + static_cast<int64_t>(argId) * static_cast<int64_t>(FRAME_SLOT_SIZE); 54 } 55 static void PushUndefinedWithArgc(ExtendedAssembler *assembler, Register glue, Register argc, Register temp, 56 Register fp, Label *next, Label *stackOverflow); 57 static void PushArgsWithArgv(ExtendedAssembler *assembler, Register glue, Register argc, Register argv, 58 Register op, Register fp, Label *next, Label *stackOverflow); 59 static void PushAsmInterpBridgeFrame(ExtendedAssembler *assembler); 60 static void PopAsmInterpBridgeFrame(ExtendedAssembler *assembler); 61 static void StackOverflowCheck(ExtendedAssembler *assembler, Register glue, Register currentSlot, Register numArgs, 62 Register op, Label *stackOverflow); 63 static void PushLeaveFrame(ExtendedAssembler *assembler, Register glue); 64 static void PopLeaveFrame(ExtendedAssembler *assembler); 65 }; 66 67 class OptimizedCall : public CommonCall { 68 public: 69 static void CallRuntime(ExtendedAssembler *assembler); 70 71 static void JSFunctionEntry(ExtendedAssembler *assembler); 72 73 static void OptimizedCallAndPushUndefined(ExtendedAssembler *assembler); 74 75 static void CallBuiltinTrampoline(ExtendedAssembler *assembler); 76 77 static void JSProxyCallInternalWithArgV(ExtendedAssembler *assembler); 78 79 static void JSCall(ExtendedAssembler *assembler); 80 81 static void CallOptimized(ExtendedAssembler *assembler); 82 83 static void CallRuntimeWithArgv(ExtendedAssembler *assembler); 84 85 static void JSCallWithArgV(ExtendedAssembler *assembler); 86 87 static void JSCallWithArgVAndPushUndefined(ExtendedAssembler *assembler); 88 89 static void DeoptHandlerAsm(ExtendedAssembler *assembler); 90 91 static void JSCallNew(ExtendedAssembler *assembler); 92 93 static void GenJSCall(ExtendedAssembler *assembler, bool isNew); 94 95 static void GenJSCallWithArgV(ExtendedAssembler *assembler, bool needAddExpectedArgs); 96 private: 97 static void DeoptEnterAsmInterp(ExtendedAssembler *assembler); 98 static void JSCallCheck(ExtendedAssembler *assembler, Register jsfunc, Register taggedValue, 99 Label *nonCallable, Label *notJSFunction); 100 static void ThrowNonCallableInternal(ExtendedAssembler *assembler, Register sp); 101 static void JSBoundFunctionCallInternal(ExtendedAssembler *assembler, Register glue, 102 Register actualArgC, Register jsfunc, int stubId); 103 static void JSProxyCallInternal(ExtendedAssembler *assembler, Register sp, Register jsfunc); 104 static void OptimizedCallAsmInterpreter(ExtendedAssembler *assembler); 105 static void PushMandatoryJSArgs(ExtendedAssembler *assembler, Register jsfunc, 106 Register thisObj, Register newTarget, Register currentSp); 107 static void PopJSFunctionArgs(ExtendedAssembler *assembler, Register expectedNumArgs, Register actualNumArgs); 108 static void PushJSFunctionEntryFrame(ExtendedAssembler *assembler, Register prevFp); 109 static void PopJSFunctionEntryFrame(ExtendedAssembler *assembler, Register glue); 110 static void PushOptimizedUnfoldArgVFrame(ExtendedAssembler *assembler, Register callSiteSp); 111 static void PopOptimizedUnfoldArgVFrame(ExtendedAssembler *assembler); 112 static void IncreaseStackForArguments(ExtendedAssembler *assembler, Register argC, Register fp); 113 static void PushOptimizedArgsConfigFrame(ExtendedAssembler *assembler); 114 static void PopOptimizedArgsConfigFrame(ExtendedAssembler *assembler); 115 static void PushAsmBridgeFrame(ExtendedAssembler *assembler); 116 static void PopOptimizedFrame(ExtendedAssembler *assembler); 117 static void JSCallInternal(ExtendedAssembler *assembler, Register jsfunc, bool isNew = false); 118 friend class OptimizedFastCall; 119 }; 120 121 class OptimizedFastCall : public CommonCall { 122 public: 123 static void OptimizedFastCallEntry(ExtendedAssembler *assembler); 124 125 static void OptimizedFastCallAndPushUndefined(ExtendedAssembler *assembler); 126 127 static void JSFastCallWithArgV(ExtendedAssembler *assembler); 128 129 static void JSFastCallWithArgVAndPushUndefined(ExtendedAssembler *assembler); 130 }; 131 132 class AsmInterpreterCall : public CommonCall { 133 public: 134 static void AsmInterpreterEntry(ExtendedAssembler *assembler); 135 136 static void AsmInterpEntryDispatch(ExtendedAssembler *assembler); 137 138 static void GeneratorReEnterAsmInterp(ExtendedAssembler *assembler); 139 140 static void GeneratorReEnterAsmInterpDispatch(ExtendedAssembler *assembler); 141 142 static void PushCallThisRangeAndDispatch(ExtendedAssembler *assembler); 143 144 static void PushCallRangeAndDispatch(ExtendedAssembler *assembler); 145 146 static void PushCallArgs3AndDispatch(ExtendedAssembler *assembler); 147 148 static void PushCallArgs2AndDispatch(ExtendedAssembler *assembler); 149 150 static void PushCallArg1AndDispatch(ExtendedAssembler *assembler); 151 152 static void PushCallArg0AndDispatch(ExtendedAssembler *assembler); 153 154 static void PushCallThisArg0AndDispatch(ExtendedAssembler *assembler); 155 156 static void PushCallThisArg1AndDispatch(ExtendedAssembler *assembler); 157 158 static void PushCallThisArgs2AndDispatch(ExtendedAssembler *assembler); 159 160 static void PushCallThisArgs3AndDispatch(ExtendedAssembler *assembler); 161 162 static void PushCallThisRangeAndDispatchNative(ExtendedAssembler *assembler); 163 164 static void PushCallRangeAndDispatchNative(ExtendedAssembler *assembler); 165 166 static void PushCallNewAndDispatchNative(ExtendedAssembler *assembler); 167 168 static void PushNewTargetAndDispatchNative(ExtendedAssembler *assembler); 169 170 static void PushCallNewAndDispatch(ExtendedAssembler *assembler); 171 172 static void PushSuperCallAndDispatch(ExtendedAssembler *assembler); 173 174 static void PushCallArgsAndDispatchNative(ExtendedAssembler *assembler); 175 176 static void ResumeRspAndDispatch(ExtendedAssembler *assembler); 177 178 static void ResumeRspAndReturn([[maybe_unused]] ExtendedAssembler *assembler); 179 180 static void ResumeCaughtFrameAndDispatch(ExtendedAssembler *assembler); 181 182 static void ResumeUncaughtFrameAndReturn(ExtendedAssembler *assembler); 183 184 static void ResumeRspAndRollback(ExtendedAssembler *assembler); 185 186 static void CallGetter(ExtendedAssembler *assembler); 187 188 static void CallSetter(ExtendedAssembler *assembler); 189 190 static void CallContainersArgs3(ExtendedAssembler *assembler); 191 192 static void CallReturnWithArgv([[maybe_unused]]ExtendedAssembler *assembler); 193 194 private: 195 static void PushCallThis(ExtendedAssembler *assembler, JSCallMode mode, Label *stackOverflow); 196 197 static Register GetThisRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister); 198 static Register GetNewTargetRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister); 199 200 static void PushVregs(ExtendedAssembler *assembler, Label *stackOverflow); 201 202 static void DispatchCall(ExtendedAssembler *assembler, Register pc, Register newSp, 203 Register acc = INVALID_REG); 204 205 static void CallNativeInternal(ExtendedAssembler *assembler, Register nativeCode); 206 207 static void PushBuiltinFrame(ExtendedAssembler *assembler, Register glue, 208 FrameType type, Register op, Register next); 209 210 static void ThrowStackOverflowExceptionAndReturn(ExtendedAssembler *assembler, Register glue, Register fp, 211 Register op); 212 213 static void PushFrameState(ExtendedAssembler *assembler, Register prevSp, Register fp, Register currentSlot, 214 Register callTarget, Register thisObj, Register method, Register pc, Register op); 215 216 static void JSCallCommonEntry(ExtendedAssembler *assembler, JSCallMode mode); 217 static void JSCallCommonFastPath(ExtendedAssembler *assembler, JSCallMode mode, Label *pushCallThis, 218 Label *stackOverflow); 219 static void JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMode mode, 220 Label *fastPathEntry, Label *pushCallThis, Label *stackOverflow); 221 222 static void GetNumVregsFromCallField(ExtendedAssembler *assembler, Register callField, Register numVregs); 223 224 static void GetDeclaredNumArgsFromCallField(ExtendedAssembler *assembler, Register callField, 225 Register declaredNumArgs); 226 227 static void SaveFpAndJumpSize(ExtendedAssembler *assembler, Immediate jumpSize); 228 229 static void PushAsmInterpEntryFrame(ExtendedAssembler *assembler); 230 231 static void PopAsmInterpEntryFrame(ExtendedAssembler *assembler); 232 233 static void PushGeneratorFrameState(ExtendedAssembler *assembler, Register &prevSpRegister, Register &fpRegister, 234 Register ¤tSlotRegister, Register &callTargetRegister, Register &thisRegister, Register &methodRegister, 235 Register &contextRegister, Register &pcRegister, Register &operatorRegister); 236 237 static void CallBCStub(ExtendedAssembler *assembler, Register &newSp, Register &glue, 238 Register &method, Register &pc, Register &temp); 239 240 static void CallNativeEntry(ExtendedAssembler *assembler); 241 242 static void CallNativeWithArgv(ExtendedAssembler *assembler, bool callNew, bool hasNewTarget = false); 243 friend class OptimizedCall; 244 }; 245 } // namespace panda::ecmascript::x64 246 #endif // ECMASCRIPT_COMPILER_ASSEMBLER_MODULE_X64_H 247