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(); 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); 128 129 private: 130 GateRef glue_ { Circuit::NullGate() }; 131 GateRef actualArgc_ { Circuit::NullGate() }; 132 GateRef actualArgv_ { Circuit::NullGate() }; 133 GateRef func_ { Circuit::NullGate() }; 134 GateRef newTarget_ { Circuit::NullGate() }; 135 GateRef hirGate_ { Circuit::NullGate() }; 136 EcmaOpcode op_; 137 GateRef thisObj_ { Circuit::NullGate() }; 138 }; 139 140 141 class CallStubBuilder : public StubBuilder { 142 public: 143 explicit CallStubBuilder(StubBuilder *parent, GateRef glue, GateRef func, GateRef actualNumArgs, GateRef jumpSize, 144 Variable *result, GateRef hotnessCounter, JSCallArgs callArgs, 145 ProfileOperation callback = ProfileOperation(), 146 bool checkIsCallable = true, GateRef hir = Circuit::NullGate()) StubBuilder(parent)147 : StubBuilder(parent) 148 { 149 this->glue_ = glue; 150 this->func_ = func; 151 this->jumpSize_ = jumpSize; 152 this->actualNumArgs_ = actualNumArgs; 153 this->result_ = result; 154 this->hotnessCounter_ = hotnessCounter; 155 this->callArgs_ = callArgs; 156 this->callback_ = callback; 157 this->checkIsCallable_ = checkIsCallable; 158 this->hir_ = hir; 159 } CallStubBuilder(Environment * env)160 explicit CallStubBuilder(Environment *env) 161 : StubBuilder(env) {} 162 ~CallStubBuilder() override = default; 163 NO_MOVE_SEMANTIC(CallStubBuilder); 164 NO_COPY_SEMANTIC(CallStubBuilder); GenerateCircuit()165 void GenerateCircuit() override {} 166 167 void JSCallDispatchForBaseline(Label *exit, Label *noNeedCheckException = nullptr); 168 GateRef JSCallDispatch(); 169 170 protected: 171 172 private: 173 GateRef glue_ {0}; 174 GateRef func_ {0}; 175 GateRef jumpSize_ {0}; 176 GateRef actualNumArgs_ {0}; 177 GateRef hotnessCounter_ {0}; 178 Variable *result_ {nullptr}; 179 JSCallArgs callArgs_; 180 ProfileOperation callback_; 181 bool checkIsCallable_ {true}; 182 GateRef hir_ {0}; 183 184 bool isFast_ {true}; 185 bool isBridge_ {false}; 186 bool isForBaseline_ {false}; 187 GateRef sp_ {0}; 188 GateRef method_ {0}; 189 GateRef numArgs_ {0}; 190 GateRef bitfield_ {0}; 191 GateRef callField_ {0}; 192 GateRef newTarget_ {0}; 193 GateRef thisValue_ {0}; 194 GateRef nativeCode_ {0}; 195 GateRef realNumArgs_ {0}; 196 GateRef isNativeMask_ {0}; 197 GateRef baselineBuiltinFp_ {0}; 198 199 void JSCallInit(Label *exit, Label *funcIsHeapObject, Label *funcIsCallable, Label *funcNotCallable); 200 void JSCallNative(Label *exit); 201 void JSCallNativeInner(Label *exit, bool isJsProxy); 202 void JSCallJSFunction(Label *exit, Label *noNeedCheckException = nullptr); 203 void JSFastAotCall(Label *exit); 204 void JSSlowAotCall(Label *exit); 205 GateRef CallConstructorBridge(const int idxForAot, const std::vector<GateRef> &argsForAot); 206 void CallBridge(GateRef code, GateRef expectedNum, Label *exit); 207 void JSCallAsmInterpreter(bool hasBaselineCode, Label *exit, Label *noNeedCheckException); 208 209 int PrepareIdxForNative(); 210 std::vector<GateRef> PrepareArgsForNative(); 211 std::vector<GateRef> PrepareBasicArgsForNative(); 212 std::vector<GateRef> PrepareAppendArgsForNative(); 213 214 int PrepareIdxForAot(); 215 std::vector<GateRef> PrepareArgsForAot(GateRef expectedNum); 216 std::vector<GateRef> PrepareBasicArgsForAot(); 217 std::vector<GateRef> PrepareAppendArgsForAotStep1(); 218 std::vector<GateRef> PrepareAppendArgsForAotStep2(); 219 std::vector<GateRef> PrepareAppendArgsForAotStep3(GateRef expectedNum); 220 221 int PrepareIdxForAsmInterpreterForBaselineWithBaselineCode(); 222 int PrepareIdxForAsmInterpreterForBaselineWithoutBaselineCode(); 223 int PrepareIdxForAsmInterpreterWithBaselineCode(); 224 int PrepareIdxForAsmInterpreterWithoutBaselineCode(); 225 std::vector<GateRef> PrepareArgsForAsmInterpreter(); 226 std::vector<GateRef> PrepareBasicArgsForAsmInterpreter(); 227 std::vector<GateRef> PrepareAppendArgsForAsmInterpreter(); 228 229 void CallFastBuiltin(Label* notFastBuiltins, Label *exit, GateRef hir = Circuit::NullGate()); 230 std::vector<GateRef> PrepareArgsForFastBuiltin(); 231 std::vector<GateRef> PrepareBasicArgsForFastBuiltin(); 232 std::vector<GateRef> PrepareAppendArgsForFastBuiltin(); 233 bool IsCallModeSupportPGO() const; 234 bool IsCallModeSupportCallBuiltin() const; 235 bool IsSlowAotCall() const; 236 bool IsFastAotCall() const; 237 bool IsSlowAotCallWithBridge() const; 238 bool IsFastAotCallWithBridge() const; 239 bool CheckResultValueChangedWithReturn(GateRef prevResRef) const; 240 void HandleProfileCall(); 241 void HandleProfileNativeCall(); 242 bool IsCallModeGetterSetter(); 243 }; 244 245 } // panda::ecmascript::kungfu 246 #endif // ECMASCRIPT_COMPILER_CALL_STUB_BUILDER_H 247