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_BASELINE_BASELINE_STUB_BUILDER_H 17#define ECMASCRIPT_COMPILER_BASELINE_BASELINE_STUB_BUILDER_H 18 19#include "ecmascript/compiler/stub_builder.h" 20#include "ecmascript/base/config.h" 21#include "ecmascript/compiler/bc_call_signature.h" 22#include "ecmascript/compiler/profiler_operation.h" 23#include "ecmascript/compiler/rt_call_signature.h" 24#include "ecmascript/compiler/circuit_builder_helper.h" 25 26namespace panda::ecmascript::kungfu { 27 28class BaselineStubBuilder : public StubBuilder { 29public: 30 static_assert(false); 31 BaselineStubBuilder(CallSignature *callSignature, Environment *env) 32 : StubBuilder(callSignature, env) {} 33 ~BaselineStubBuilder() override = default; 34 NO_MOVE_SEMANTIC(BaselineStubBuilder); 35 NO_COPY_SEMANTIC(BaselineStubBuilder); 36 virtual void GenerateCircuit() override = 0; 37 38 inline void SetEnvToFrame(GateRef glue, GateRef frame, GateRef value) 39 { 40 Store(VariableType::INT64(), glue, frame, 41 IntPtr(AsmInterpretedFrame::GetEnvOffset(GetEnvironment()->IsArch32Bit())), value); 42 } 43 44 void CheckExceptionWithVar(GateRef acc, GateRef res) 45 { 46 auto env = GetEnvironment(); 47 Label isException(env); 48 Label notException(env); 49 Branch(TaggedIsException(res), &isException, ¬Exception); 50 Bind(&isException); 51 { 52 Return(); 53 } 54 Bind(¬Exception); 55 { 56 DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); 57 varAcc = res; 58 Return(); 59 } 60 } 61 62 void CheckException(GateRef acc, GateRef res) 63 { 64 auto env = GetEnvironment(); 65 Label isException(env); 66 Label notException(env); 67 Branch(TaggedIsException(res), &isException, ¬Exception); 68 Bind(&isException); 69 { 70 (void) acc; 71 Return(); 72 } 73 Bind(¬Exception); 74 { 75 Return(); 76 } 77 } 78 79 void CheckExceptionWithJump(GateRef acc, GateRef res, Label *jump) 80 { 81 auto env = GetEnvironment(); 82 Label isException(env); 83 Label notException(env); 84 Branch(TaggedIsException(res), &isException, ¬Exception); 85 Bind(&isException); 86 { 87 Return(acc); 88 } 89 Bind(¬Exception); 90 { 91 Jump(jump); 92 } 93 } 94 95 void CheckPendingException(GateRef glue, GateRef res, GateRef offset) 96 { 97 (void)offset; 98 auto env = GetEnvironment(); 99 Label isException(env); 100 Label notException(env); 101 Branch(HasPendingException(glue), &isException, ¬Exception); 102 Bind(&isException); 103 { 104 Return(); 105 } 106 Bind(¬Exception); 107 { 108 (void)res; 109 Return(); 110 } 111 } 112 113 template<typename... Args> 114 void DispatchBase(GateRef target, GateRef glue, Args... args) 115 { 116 GetEnvironment()->GetBuilder()->CallBCHandler(glue, target, {glue, args...}); 117 } 118 119 inline void DispatchLast(GateRef glue, GateRef sp, GateRef pc, GateRef constpool, 120 GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter) 121 { 122 GateRef target = PtrMul(IntPtr(BytecodeStubCSigns::ID_ExceptionHandler), IntPtrSize()); 123 DispatchBase(target, glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter); 124 Return(); 125 } 126 127 void Dispatch(GateRef glue, GateRef sp, GateRef pc, GateRef constpool, GateRef profileTypeInfo, 128 GateRef acc, GateRef hotnessCounter, GateRef format) 129 { 130 GateRef newPc = PtrAdd(pc, format); 131 GateRef opcode = Load(VariableType::INT8(), newPc); 132 GateRef target = PtrMul(ZExtInt32ToPtr(ZExtInt8ToInt32(opcode)), IntPtrSize()); 133 DispatchBase(target, glue, sp, newPc, constpool, profileTypeInfo, acc, hotnessCounter); 134 Return(); 135 } 136 137 inline GateRef GetFunctionFromFrame(GateRef frame) 138 { 139 return Load(VariableType::JS_POINTER(), frame, 140 IntPtr(AsmInterpretedFrame::GetFunctionOffset(GetEnvironment()->IsArch32Bit()))); 141 } 142 143 inline GateRef GetEnvFromFrame(GateRef frame) 144 { 145 return Load(VariableType::JS_POINTER(), frame, 146 IntPtr(AsmInterpretedFrame::GetEnvOffset(GetEnvironment()->IsArch32Bit()))); 147 } 148 149 inline GateRef GetAccFromFrame(GateRef frame) 150 { 151 return Load(VariableType::JS_ANY(), frame, 152 IntPtr(AsmInterpretedFrame::GetAccOffset(GetEnvironment()->IsArch32Bit()))); 153 } 154 155 inline GateRef GetConstpoolFromMethod(GateRef method) 156 { 157 return Load(VariableType::JS_POINTER(), method, IntPtr(Method::CONSTANT_POOL_OFFSET)); 158 } 159 160 GateRef GetProfileTypeInfoFromFunction(GateRef function); 161 162 inline GateRef GetHotnessCounterFromMethod(GateRef method) 163 { 164 GateRef x = Load(VariableType::INT16(), method, IntPtr(Method::LITERAL_INFO_OFFSET)); 165 return GetEnvironment()->GetBuilder()->SExtInt1ToInt32(x); 166 } 167 168 GateRef GetModuleFromFunction(GateRef function); 169 170 GateRef GetHomeObjectFromFunction(GateRef function); 171 172 inline GateRef GetModule(GateRef sp) 173 { 174 GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp)); 175 return GetModuleFromFunction(currentFunc); 176 } 177 178 inline GateRef GetCurrentFrame(GateRef glue) 179 { 180 return GetLastLeaveFrame(glue); 181 } 182 183 inline GateRef GetFrame(GateRef CurrentSp) 184 { 185 return PtrSub(CurrentSp, IntPtr(AsmInterpretedFrame::GetSize(GetEnvironment()->IsArch32Bit()))); 186 } 187 188 inline GateRef GetPcFromFrame(GateRef frame) 189 { 190 return Load(VariableType::NATIVE_POINTER(), frame, 191 IntPtr(AsmInterpretedFrame::GetPcOffset(GetEnvironment()->IsArch32Bit()))); 192 } 193 194 inline GateRef GetCallSizeFromFrame(GateRef frame) 195 { 196 return Load(VariableType::NATIVE_POINTER(), frame, 197 IntPtr(AsmInterpretedFrame::GetCallSizeOffset(GetEnvironment()->IsArch32Bit()))); 198 } 199 200 inline GateRef GetThisFromFrame(GateRef frame) 201 { 202 return Load(VariableType::JS_POINTER(), frame, 203 IntPtr(AsmInterpretedFrame::GetThisOffset(GetEnvironment()->IsArch32Bit()))); 204 } 205 206 GateRef GetNewTarget(GateRef sp) 207 { 208 GateRef function = Load(VariableType::JS_POINTER(), GetFrame(sp), 209 IntPtr(AsmInterpretedFrame::GetFunctionOffset(GetEnvironment()->IsArch32Bit()))); 210 GateRef method = GetMethodFromFunction(function); 211 GateRef callField = GetCallFieldFromMethod(method); 212 // ASSERT: callField has "extra" bit. 213 GateRef numVregs = 214 TruncInt64ToInt32(Int64And(Int64LSR(callField, Int64(MethodLiteral::NumVregsBits::START_BIT)), 215 Int64((1LLU << MethodLiteral::NumVregsBits::SIZE) - 1))); 216 GateRef haveFunc = ZExtInt1ToInt32(Int64NotEqual(Int64And(Int64LSR(callField, 217 Int64(MethodLiteral::HaveFuncBit::START_BIT)), 218 Int64((1LLU << MethodLiteral::HaveFuncBit::SIZE) - 1)), Int64(0))); 219 GateRef idx = ZExtInt32ToPtr(Int32Add(numVregs, haveFunc)); 220 return Load(VariableType::JS_ANY(), sp, PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()), idx)); 221 } 222 223 GateRef GetStartIdxAndNumArgs(GateRef sp, GateRef restIdx) 224 { 225 auto env = GetEnvironment(); 226 Label subEntry(env); 227 env->SubCfgEntry(&subEntry); 228 DEFVARIABLE(numArgs, VariableType::INT32(), Int32(0)); 229 GateRef state = PtrSub(sp, IntPtr(AsmInterpretedFrame::GetSize(env->IsArch32Bit()))); 230 GateRef function = GetFunctionFromFrame(state); 231 GateRef method = GetMethodFromJSFunctionOrProxy(function); 232 GateRef callField = GetCallFieldFromMethod(method); 233 // ASSERT: callField has "extra" bit. 234 GateRef numVregs = TruncInt64ToInt32(Int64And( 235 Int64LSR(callField, Int64(MethodLiteral::NumVregsBits::START_BIT)), 236 Int64((1LLU << MethodLiteral::NumVregsBits::SIZE) - 1))); 237 GateRef haveFunc = Int64NotEqual(Int64And(Int64LSR(callField, Int64(MethodLiteral::HaveFuncBit::START_BIT)), 238 Int64((1LLU << MethodLiteral::HaveFuncBit::SIZE) - 1)), Int64(0)); 239 GateRef haveNewTarget = Int64NotEqual( 240 Int64And(Int64LSR(callField, Int64(MethodLiteral::HaveNewTargetBit::START_BIT)), 241 Int64((1LLU << MethodLiteral::HaveNewTargetBit::SIZE) - 1)), Int64(0)); 242 GateRef haveThis = Int64NotEqual(Int64And(Int64LSR(callField, Int64(MethodLiteral::HaveThisBit::START_BIT)), 243 Int64((1LLU << MethodLiteral::HaveThisBit::SIZE) - 1)), Int64(0)); 244 GateRef copyArgs = Int32Add(Int32Add(ZExtInt1ToInt32(haveFunc), ZExtInt1ToInt32(haveNewTarget)), 245 ZExtInt1ToInt32(haveThis)); 246 numArgs = TruncInt64ToInt32(Int64And(Int64LSR(callField, Int64(MethodLiteral::NumArgsBits::START_BIT)), 247 Int64((1LLU << MethodLiteral::NumArgsBits::SIZE) - 1))); 248 GateRef fp = Load(VariableType::NATIVE_POINTER(), state, 249 IntPtr(AsmInterpretedFrame::GetFpOffset(env->IsArch32Bit()))); 250 Label actualEqualDeclared(env); 251 Label actualNotEqualDeclared(env); 252 Branch(Int32UnsignedGreaterThan(ChangeIntPtrToInt32(PtrSub(fp, sp)), 253 Int32Mul(Int32Add(Int32Add(numVregs, copyArgs), *numArgs), 254 Int32(sizeof(JSTaggedType)))), 255 &actualNotEqualDeclared, &actualEqualDeclared); 256 Bind(&actualNotEqualDeclared); 257 { 258 numArgs = GetInt32OfTInt(Load(VariableType::JS_ANY(), fp, 259 IntPtr(-static_cast<int64_t>(sizeof(JSTaggedType))))); 260 Jump(&actualEqualDeclared); 261 } 262 Bind(&actualEqualDeclared); 263 GateRef startIdx = Int32Add(Int32Add(numVregs, copyArgs), restIdx); 264 Label numArgsGreater(env); 265 Label numArgsNotGreater(env); 266 Label exit(env); 267 Branch(Int32UnsignedGreaterThan(*numArgs, restIdx), &numArgsGreater, &numArgsNotGreater); 268 Bind(&numArgsGreater); 269 { 270 numArgs = Int32Sub(*numArgs, restIdx); 271 Jump(&exit); 272 } 273 Bind(&numArgsNotGreater); 274 { 275 numArgs = Int32(0); 276 Jump(&exit); 277 } 278 Bind(&exit); 279 // 32: high 32 bits = startIdx, low 32 bits = numArgs 280 GateRef ret = Int64Or(Int64LSL(ZExtInt32ToInt64(startIdx), Int64(32)), ZExtInt32ToInt64(*numArgs)); 281 env->SubCfgExit(); 282 return ret; 283 } 284 285 inline void SetVregValue(GateRef glue, GateRef sp, GateRef idx, GateRef val) 286 { 287 Store(VariableType::INT64(), glue, sp, PtrMul(IntPtr(sizeof(JSTaggedType)), idx), val); 288 } 289 290 inline GateRef GetVregValue(GateRef sp, GateRef idx) 291 { 292 return Load(VariableType::JS_ANY(), sp, PtrMul(IntPtr(sizeof(JSTaggedType)), idx)); 293 } 294 295 GateRef GetResumeModeFromGeneratorObject(GateRef obj); 296 GateRef GetResumeModeFromAsyncGeneratorObject(GateRef obj); 297 GateRef GetLastLeaveFrame(GateRef glue); 298}; // class BaselineStubBuilder 299} // namespace panda::ecmascript::kungfu 300#endif // ECMASCRIPT_COMPILER_BASELINE_BASELINE_STUB_BUILDER_H 301