• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 class BaselineStubBuilder : public StubBuilder {
29 public:
30     static_assert(false);
BaselineStubBuilder(CallSignature * callSignature,Environment * env)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 
SetEnvToFrame(GateRef glue,GateRef frame,GateRef value)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 
CheckExceptionWithVar(GateRef acc,GateRef res)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, &notException);
50         Bind(&isException);
51         {
52             Return();
53         }
54         Bind(&notException);
55         {
56             DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc);
57             varAcc = res;
58             Return();
59         }
60     }
61 
CheckException(GateRef acc,GateRef res)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, &notException);
68         Bind(&isException);
69         {
70             (void) acc;
71             Return();
72         }
73         Bind(&notException);
74         {
75             Return();
76         }
77     }
78 
CheckExceptionWithJump(GateRef acc,GateRef res,Label * jump)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, &notException);
85         Bind(&isException);
86         {
87             Return(acc);
88         }
89         Bind(&notException);
90         {
91             Jump(jump);
92         }
93     }
94 
CheckPendingException(GateRef glue,GateRef res,GateRef offset)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, &notException);
102         Bind(&isException);
103         {
104             Return();
105         }
106         Bind(&notException);
107         {
108             (void)res;
109             Return();
110         }
111     }
112 
113     template<typename... Args>
DispatchBase(GateRef target,GateRef glue,Args...args)114     void DispatchBase(GateRef target, GateRef glue, Args... args)
115     {
116         GetEnvironment()->GetBuilder()->CallBCHandler(glue, target, {glue, args...});
117     }
118 
DispatchLast(GateRef glue,GateRef sp,GateRef pc,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter)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 
Dispatch(GateRef glue,GateRef sp,GateRef pc,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter,GateRef format)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 
GetFunctionFromFrame(GateRef frame)137     inline GateRef GetFunctionFromFrame(GateRef frame)
138     {
139         return Load(VariableType::JS_POINTER(), frame,
140             IntPtr(AsmInterpretedFrame::GetFunctionOffset(GetEnvironment()->IsArch32Bit())));
141     }
142 
GetEnvFromFrame(GateRef frame)143     inline GateRef GetEnvFromFrame(GateRef frame)
144     {
145         return Load(VariableType::JS_POINTER(), frame,
146             IntPtr(AsmInterpretedFrame::GetEnvOffset(GetEnvironment()->IsArch32Bit())));
147     }
148 
GetAccFromFrame(GateRef frame)149     inline GateRef GetAccFromFrame(GateRef frame)
150     {
151         return Load(VariableType::JS_ANY(), frame,
152             IntPtr(AsmInterpretedFrame::GetAccOffset(GetEnvironment()->IsArch32Bit())));
153     }
154 
GetConstpoolFromMethod(GateRef method)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 
GetHotnessCounterFromMethod(GateRef method)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 
GetModule(GateRef sp)172     inline GateRef GetModule(GateRef sp)
173     {
174         GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp));
175         return GetModuleFromFunction(currentFunc);
176     }
177 
GetCurrentFrame(GateRef glue)178     inline GateRef GetCurrentFrame(GateRef glue)
179     {
180         return GetLastLeaveFrame(glue);
181     }
182 
GetFrame(GateRef CurrentSp)183     inline GateRef GetFrame(GateRef CurrentSp)
184     {
185         return PtrSub(CurrentSp, IntPtr(AsmInterpretedFrame::GetSize(GetEnvironment()->IsArch32Bit())));
186     }
187 
GetPcFromFrame(GateRef frame)188     inline GateRef GetPcFromFrame(GateRef frame)
189     {
190         return Load(VariableType::NATIVE_POINTER(), frame,
191             IntPtr(AsmInterpretedFrame::GetPcOffset(GetEnvironment()->IsArch32Bit())));
192     }
193 
GetCallSizeFromFrame(GateRef frame)194     inline GateRef GetCallSizeFromFrame(GateRef frame)
195     {
196         return Load(VariableType::NATIVE_POINTER(), frame,
197             IntPtr(AsmInterpretedFrame::GetCallSizeOffset(GetEnvironment()->IsArch32Bit())));
198     }
199 
GetThisFromFrame(GateRef frame)200     inline GateRef GetThisFromFrame(GateRef frame)
201     {
202         return Load(VariableType::JS_POINTER(), frame,
203             IntPtr(AsmInterpretedFrame::GetThisOffset(GetEnvironment()->IsArch32Bit())));
204     }
205 
GetNewTarget(GateRef sp)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 
GetStartIdxAndNumArgs(GateRef sp,GateRef restIdx)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 
SetVregValue(GateRef glue,GateRef sp,GateRef idx,GateRef val)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 
GetVregValue(GateRef sp,GateRef idx)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