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