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 DECUPLE_SLOT_SIZE = 80; 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 PushCallNewAndDispatch(ExtendedAssembler *assembler); 169 170 static void PushCallArgsAndDispatchNative(ExtendedAssembler *assembler); 171 172 static void ResumeRspAndDispatch(ExtendedAssembler *assembler); 173 174 static void ResumeRspAndReturn([[maybe_unused]] ExtendedAssembler *assembler); 175 176 static void ResumeCaughtFrameAndDispatch(ExtendedAssembler *assembler); 177 178 static void ResumeUncaughtFrameAndReturn(ExtendedAssembler *assembler); 179 180 static void CallGetter(ExtendedAssembler *assembler); 181 182 static void CallSetter(ExtendedAssembler *assembler); 183 184 static void CallContainersArgs3(ExtendedAssembler *assembler); 185 186 static void CallReturnWithArgv([[maybe_unused]]ExtendedAssembler *assembler); 187 188 private: 189 static void PushCallThis(ExtendedAssembler *assembler, JSCallMode mode, Label *stackOverflow); 190 191 static Register GetThisRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister); 192 static Register GetNewTargetRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister); 193 194 static void PushVregs(ExtendedAssembler *assembler, Label *stackOverflow); 195 196 static void DispatchCall(ExtendedAssembler *assembler, Register pc, Register newSp, 197 Register acc = INVALID_REG); 198 199 static void CallNativeInternal(ExtendedAssembler *assembler, Register nativeCode); 200 201 static void PushBuiltinFrame(ExtendedAssembler *assembler, Register glue, 202 FrameType type, Register op, Register next); 203 204 static void ThrowStackOverflowExceptionAndReturn(ExtendedAssembler *assembler, Register glue, Register fp, 205 Register op); 206 207 static void PushFrameState(ExtendedAssembler *assembler, Register prevSp, Register fp, Register currentSlot, 208 Register callTarget, Register thisObj, Register method, Register pc, Register op); 209 210 static void JSCallCommonEntry(ExtendedAssembler *assembler, JSCallMode mode); 211 static void JSCallCommonFastPath(ExtendedAssembler *assembler, JSCallMode mode, Label *pushCallThis, 212 Label *stackOverflow); 213 static void JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMode mode, 214 Label *fastPathEntry, Label *pushCallThis, Label *stackOverflow); 215 216 static void GetNumVregsFromCallField(ExtendedAssembler *assembler, Register callField, Register numVregs); 217 218 static void GetDeclaredNumArgsFromCallField(ExtendedAssembler *assembler, Register callField, 219 Register declaredNumArgs); 220 221 static void SaveFpAndJumpSize(ExtendedAssembler *assembler, Immediate jumpSize); 222 223 static void PushAsmInterpEntryFrame(ExtendedAssembler *assembler); 224 225 static void PopAsmInterpEntryFrame(ExtendedAssembler *assembler); 226 227 static void PushGeneratorFrameState(ExtendedAssembler *assembler, Register &prevSpRegister, Register &fpRegister, 228 Register ¤tSlotRegister, Register &callTargetRegister, Register &thisRegister, Register &methodRegister, 229 Register &contextRegister, Register &pcRegister, Register &operatorRegister); 230 231 static void CallBCStub(ExtendedAssembler *assembler, Register &newSp, Register &glue, 232 Register &method, Register &pc, Register &temp); 233 234 static void CallNativeEntry(ExtendedAssembler *assembler); 235 236 static void CallNativeWithArgv(ExtendedAssembler *assembler, bool callNew); 237 friend class OptimizedCall; 238 }; 239 } // namespace panda::ecmascript::x64 240 #endif // ECMASCRIPT_COMPILER_ASSEMBLER_MODULE_X64_H 241