1 /* 2 * Copyright (c) 2024 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_CALL_STUB_BUILDER_H 17 #define ECMASCRIPT_COMPILER_CALL_STUB_BUILDER_H 18 19 #include <cstddef> 20 #include "ecmascript/compiler/profiler_operation.h" 21 #include "ecmascript/compiler/stub_builder.h" 22 23 namespace panda::ecmascript::kungfu { 24 25 struct CallArgs { 26 GateRef arg0; 27 GateRef arg1; 28 GateRef arg2; 29 }; 30 31 struct CallArgsWithThis { 32 GateRef arg0; 33 GateRef arg1; 34 GateRef arg2; 35 GateRef thisValue; 36 }; 37 38 struct CallArgv { 39 GateRef argc; 40 GateRef argv; 41 }; 42 43 struct CallArgvWithThis { 44 GateRef argc; 45 GateRef argv; 46 GateRef thisValue; 47 }; 48 49 struct SuperCallArgs { 50 GateRef thisFunc; 51 GateRef array; 52 GateRef argc; 53 GateRef argv; 54 GateRef thisObj; 55 GateRef newTarget; 56 }; 57 58 struct CallConstructorArgs { 59 GateRef argc; 60 GateRef argv; 61 GateRef thisObj; 62 }; 63 64 struct CallGetterArgs { 65 GateRef receiver; 66 }; 67 68 struct CallSetterArgs { 69 GateRef receiver; 70 GateRef value; 71 }; 72 73 struct CallThisArg2WithReturnArgs { 74 GateRef thisValue; 75 GateRef arg0; 76 GateRef arg1; 77 }; 78 79 struct CallThisArg3WithReturnArgs { 80 GateRef argHandle; 81 GateRef value; 82 GateRef key; 83 GateRef thisValue; 84 }; 85 86 struct CallThisArgvWithReturnArgs { 87 GateRef argc; 88 GateRef argv; 89 GateRef thisValue; 90 }; 91 92 struct JSCallArgs { JSCallArgsJSCallArgs93 JSCallArgs() {} JSCallArgsJSCallArgs94 JSCallArgs(JSCallMode m) : mode(m) {} 95 JSCallMode mode {JSCallMode::CALL_ARG0}; 96 union { 97 CallArgs callArgs; 98 CallArgsWithThis callArgsWithThis; 99 CallArgv callArgv; 100 CallArgvWithThis callArgvWithThis; 101 SuperCallArgs superCallArgs; 102 CallConstructorArgs callConstructorArgs; 103 CallGetterArgs callGetterArgs; 104 CallSetterArgs callSetterArgs; 105 CallThisArg2WithReturnArgs callThisArg2WithReturnArgs; 106 CallThisArg3WithReturnArgs callThisArg3WithReturnArgs; 107 CallThisArgvWithReturnArgs callThisArgvWithReturnArgs; 108 }; 109 }; 110 111 class CallCoStubBuilder : public StubBuilder { 112 public: CallCoStubBuilder(StubBuilder * parent,EcmaOpcode op)113 explicit CallCoStubBuilder(StubBuilder *parent, EcmaOpcode op) 114 : StubBuilder(parent) 115 { 116 this->op_ = op; 117 } 118 ~CallCoStubBuilder() override = default; 119 NO_MOVE_SEMANTIC(CallCoStubBuilder); 120 NO_COPY_SEMANTIC(CallCoStubBuilder); GenerateCircuit()121 void GenerateCircuit() override {} 122 void PrepareArgs(std::vector<GateRef> &args, std::vector<GateRef> &argsFastCall); 123 GateRef CallStubDispatch(bool useCmc); 124 std::tuple<bool, size_t, size_t> GetOpInfo(); 125 static void LowerFastCall(GateRef gate, GateRef glue, CircuitBuilder &builder, GateRef func, GateRef argc, 126 const std::vector<GateRef> &args, const std::vector<GateRef> &fastCallArgs, 127 Variable *result, Label *exit, bool isNew, bool useCmc); 128 static void FastCallSelector(CircuitBuilder &builder, GateRef glue, GateRef func, GateRef argc, Variable *result, 129 Label *exit); 130 static void LowerFastSuperCall(GateRef glue, CircuitBuilder &builder, const std::vector<GateRef> &args, 131 GateRef elementsPtr, Variable &result, Label &exit); 132 133 static GateRef LowerCallNGCRuntime(GateRef glue, CircuitBuilder &builder, GateRef gate, int index, 134 const std::vector<GateRef> &args, bool useLabel = false); 135 static void CallNGCRuntimeWithCallTimer(GateRef glue, CircuitBuilder &builder, int index, GateRef gate, 136 GateRef func, Variable &result, const std::vector<GateRef> &args); 137 138 private: 139 GateRef glue_ { Circuit::NullGate() }; 140 GateRef actualArgc_ { Circuit::NullGate() }; 141 GateRef actualArgv_ { Circuit::NullGate() }; 142 GateRef func_ { Circuit::NullGate() }; 143 GateRef newTarget_ { Circuit::NullGate() }; 144 GateRef hirGate_ { Circuit::NullGate() }; 145 EcmaOpcode op_; 146 GateRef thisObj_ { Circuit::NullGate() }; 147 }; 148 149 enum class FastCallType { 150 FAST_AOT_CALL, 151 FAST_AOT_CALL_BRIDGE, 152 AOT_CALL, 153 AOT_CALL_BRIDGE, 154 SLOW_CALL 155 }; 156 157 class CallStubBuilder : public StubBuilder { 158 public: 159 explicit CallStubBuilder(StubBuilder *parent, GateRef glue, GateRef func, GateRef actualNumArgs, GateRef jumpSize, 160 Variable *result, GateRef hotnessCounter, JSCallArgs callArgs, 161 ProfileOperation callback = ProfileOperation(), 162 bool checkIsCallable = true, GateRef hir = Circuit::NullGate()) StubBuilder(parent)163 : StubBuilder(parent) 164 { 165 this->glue_ = glue; 166 this->func_ = func; 167 this->jumpSize_ = jumpSize; 168 this->actualNumArgs_ = actualNumArgs; 169 this->result_ = result; 170 this->hotnessCounter_ = hotnessCounter; 171 this->callArgs_ = callArgs; 172 this->callback_ = callback; 173 this->checkIsCallable_ = checkIsCallable; 174 this->hir_ = hir; 175 } CallStubBuilder(Environment * env)176 explicit CallStubBuilder(Environment *env) 177 : StubBuilder(env) {} 178 ~CallStubBuilder() override = default; 179 NO_MOVE_SEMANTIC(CallStubBuilder); 180 NO_COPY_SEMANTIC(CallStubBuilder); GenerateCircuit()181 void GenerateCircuit() override {} 182 183 void JSCallDispatchForBaseline(Label *exit, Label *noNeedCheckException = nullptr); 184 GateRef JSCallDispatch(); 185 186 protected: 187 188 private: 189 GateRef glue_ {0}; 190 GateRef func_ {0}; 191 GateRef jumpSize_ {0}; 192 GateRef actualNumArgs_ {0}; 193 GateRef hotnessCounter_ {0}; 194 Variable *result_ {nullptr}; 195 JSCallArgs callArgs_; 196 ProfileOperation callback_; 197 bool checkIsCallable_ {true}; 198 GateRef hir_ {0}; 199 200 bool isFast_ {true}; 201 bool isBridge_ {false}; 202 bool isForBaseline_ {false}; 203 GateRef sp_ {0}; 204 GateRef method_ {0}; 205 GateRef numArgs_ {0}; 206 GateRef bitfield_ {0}; 207 GateRef callField_ {0}; 208 GateRef newTarget_ {0}; 209 GateRef thisValue_ {0}; 210 GateRef nativeCode_ {0}; 211 GateRef realNumArgs_ {0}; 212 GateRef isNativeMask_ {0}; 213 GateRef baselineBuiltinFp_ {0}; 214 215 void JSCallInit(Label *exit, Label *funcIsHeapObject, Label *funcIsCallable, Label *funcNotCallable); 216 void JSCallNative(Label *exit); 217 void JSCallNativeInner(Label *exit, bool isJSFunction); 218 void JSCallJSFunction(Label *exit, Label *noNeedCheckException = nullptr); 219 void JSFastAotCall(Label *exit); 220 void JSSlowAotCall(Label *exit); 221 GateRef CallConstructorBridge(const int idxForAot, const std::vector<GateRef> &argsForAot); 222 void CallBridge(GateRef code, GateRef expectedNum, Label *exit); 223 void JSCallAsmInterpreter(bool hasBaselineCode, Label *methodNotAot, Label *exit, Label *noNeedCheckException); 224 225 int PrepareIdxForNative(); 226 std::vector<GateRef> PrepareArgsForNative(); 227 std::vector<GateRef> PrepareBasicArgsForNative(); 228 std::vector<GateRef> PrepareAppendArgsForNative(); 229 230 int PrepareIdxForAot(); 231 std::vector<GateRef> PrepareArgsForAot(GateRef expectedNum); 232 std::vector<GateRef> PrepareBasicArgsForAot(); 233 std::vector<GateRef> PrepareAppendArgsForAotStep1(); 234 std::vector<GateRef> PrepareAppendArgsForAotStep2(); 235 std::vector<GateRef> PrepareAppendArgsForAotStep3(GateRef expectedNum); 236 237 int PrepareIdxForAsmInterpreterForBaselineWithBaselineCode(); 238 int PrepareIdxForAsmInterpreterForBaselineWithoutBaselineCode(); 239 int PrepareIdxForAsmInterpreterWithBaselineCode(); 240 int PrepareIdxForAsmInterpreterWithoutBaselineCode(); 241 std::vector<GateRef> PrepareArgsForAsmInterpreter(); 242 std::vector<GateRef> PrepareBasicArgsForAsmInterpreter(); 243 std::vector<GateRef> PrepareAppendArgsForAsmInterpreter(); 244 245 void CallFastBuiltin(Label* notFastBuiltins, Label *exit, GateRef hir = Circuit::NullGate()); 246 std::vector<GateRef> PrepareArgsForFastBuiltin(); 247 std::vector<GateRef> PrepareBasicArgsForFastBuiltin(); 248 std::vector<GateRef> PrepareAppendArgsForFastBuiltin(); 249 bool IsCallModeSupportPGO() const; 250 bool IsCallModeSupportCallBuiltin() const; 251 bool IsSlowAotCall() const; 252 bool IsFastAotCall() const; 253 bool IsSlowAotCallWithBridge() const; 254 bool IsFastAotCallWithBridge() const; 255 bool CheckResultValueChangedWithReturn(GateRef prevResRef) const; 256 void HandleProfileCall(); 257 void HandleProfileNativeCall(); 258 bool IsCallModeGetterSetter(); 259 }; 260 261 } // panda::ecmascript::kungfu 262 #endif // ECMASCRIPT_COMPILER_CALL_STUB_BUILDER_H 263