• 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_STUBS_INL_H
17 #define ECMASCRIPT_COMPILER_BASELINE_BASELINE_STUBS_INL_H
18 
19 #include "ecmascript/compiler/baseline/baseline_stubs.h"
20 #include "ecmascript/js_function.h"
21 #include "ecmascript/js_generator_object.h"
22 #include "ecmascript/js_async_generator_object.h"
23 
24 namespace panda::ecmascript::kungfu {
25 using namespace panda::ecmascript;
26 
SetEnvToFrame(GateRef glue,GateRef frame,GateRef value)27 void BaselineStubBuilder::SetEnvToFrame(GateRef glue, GateRef frame, GateRef value)
28 {
29     Store(VariableType::INT64(), glue, frame,
30           IntPtr(AsmInterpretedFrame::GetEnvOffset(GetEnvironment()->IsArch32Bit())), value);
31 }
32 
CheckExceptionWithVar(GateRef glue,GateRef sp,GateRef res,GateRef acc)33 void BaselineStubBuilder::CheckExceptionWithVar(GateRef glue, GateRef sp, GateRef res, GateRef acc)
34 {
35     auto env = GetEnvironment();
36     Label isException(env);
37     Label notException(env);
38     Branch(TaggedIsException(res), &isException, &notException);
39     Bind(&isException);
40     {
41         DispatchLast(glue, sp, acc);
42         Return(acc);
43     }
44     Bind(&notException);
45     {
46         Return(res);
47     }
48 }
49 
CheckException(GateRef glue,GateRef sp,GateRef res)50 void BaselineStubBuilder::CheckException(GateRef glue, GateRef sp, GateRef res)
51 {
52     auto env = GetEnvironment();
53     Label isException(env);
54     Label notException(env);
55     Branch(TaggedIsException(res), &isException, &notException);
56     Bind(&isException);
57     {
58         GateRef frame = GetFrame(sp);
59         GateRef acc = GetAccFromFrame(glue, frame);
60         DispatchLast(glue, sp, acc);
61         Return();
62     }
63     Bind(&notException);
64     {
65         Return();
66     }
67 }
68 
CheckExceptionReturn(GateRef glue,GateRef sp,GateRef res)69 void BaselineStubBuilder::CheckExceptionReturn(GateRef glue, GateRef sp, GateRef res)
70 {
71     auto env = GetEnvironment();
72     Label isException(env);
73     Label notException(env);
74     Branch(TaggedIsException(res), &isException, &notException);
75     Bind(&isException);
76     {
77         GateRef frame = GetFrame(sp);
78         GateRef acc = GetAccFromFrame(glue, frame);
79         DispatchLast(glue, sp, acc);
80         Return(acc);
81     }
82     Bind(&notException);
83     {
84         Return(res);
85     }
86 }
87 
CheckExceptionWithJump(GateRef glue,GateRef sp,GateRef res,GateRef acc,Label * jump)88 void BaselineStubBuilder::CheckExceptionWithJump(GateRef glue, GateRef sp, GateRef res, GateRef acc, Label *jump)
89 {
90     auto env = GetEnvironment();
91     Label isException(env);
92     Label notException(env);
93     Branch(TaggedIsException(res), &isException, &notException);
94     Bind(&isException);
95     {
96         DispatchLast(glue, sp, acc);
97         Return();
98     }
99     Bind(&notException);
100     {
101         Jump(jump);
102     }
103 }
104 
CheckExceptionWithJumpAndReturn(GateRef glue,GateRef sp,GateRef res,GateRef acc,Label * jump)105 void BaselineStubBuilder::CheckExceptionWithJumpAndReturn(GateRef glue, GateRef sp, GateRef res, GateRef acc,
106                                                           Label *jump)
107 {
108     auto env = GetEnvironment();
109     Label isException(env);
110     Label notException(env);
111     Branch(TaggedIsException(res), &isException, &notException);
112     Bind(&isException);
113     {
114         DispatchLast(glue, sp, acc);
115         Return(acc);
116     }
117     Bind(&notException);
118     {
119         Jump(jump);
120     }
121 }
122 
CheckPendingException(GateRef glue,GateRef sp,GateRef res,GateRef acc)123 void BaselineStubBuilder::CheckPendingException(GateRef glue, GateRef sp, GateRef res, GateRef acc)
124 {
125     auto env = GetEnvironment();
126     Label isException(env);
127     Label notException(env);
128     Branch(HasPendingException(glue), &isException, &notException);
129     Bind(&isException);
130     {
131         DispatchLast(glue, sp, acc);
132         Return(acc);
133     }
134     Bind(&notException);
135     {
136         Return(res);
137     }
138 }
139 
DispatchLast(GateRef glue,GateRef sp,GateRef acc)140 void BaselineStubBuilder::DispatchLast(GateRef glue, GateRef sp, GateRef acc)
141 {
142     // Get baseline exceptionHandler index
143     GateRef baselineEHIndex = BaselineStubCSigns::BaselineExceptionHandler;
144     CallBaselineStub(glue, baselineEHIndex, { glue, sp, acc });
145 }
146 
CallBaselineStub(GateRef glue,int index,const std::initializer_list<GateRef> & args)147 GateRef BaselineStubBuilder::CallBaselineStub(GateRef glue, int index, const std::initializer_list<GateRef>& args)
148 {
149     auto env = GetEnvironment();
150     const std::string name = BaselineStubCSigns::GetName(index);
151     GateRef result = env->GetBuilder()->CallStub(glue, Circuit::NullGate(), index, args, name.c_str());
152     return result;
153 }
154 
GetFunctionFromFrame(GateRef glue,GateRef frame)155 GateRef BaselineStubBuilder::GetFunctionFromFrame(GateRef glue, GateRef frame)
156 {
157     return Load(VariableType::JS_POINTER(), glue, frame,
158                 IntPtr(AsmInterpretedFrame::GetFunctionOffset(GetEnvironment()->IsArch32Bit())));
159 }
160 
GetEnvFromFrame(GateRef glue,GateRef frame)161 GateRef BaselineStubBuilder::GetEnvFromFrame(GateRef glue, GateRef frame)
162 {
163     return Load(VariableType::JS_POINTER(), glue, frame,
164                 IntPtr(AsmInterpretedFrame::GetEnvOffset(GetEnvironment()->IsArch32Bit())));
165 }
166 
GetAccFromFrame(GateRef glue,GateRef frame)167 GateRef BaselineStubBuilder::GetAccFromFrame(GateRef glue, GateRef frame)
168 {
169     return Load(VariableType::JS_ANY(), glue, frame,
170                 IntPtr(AsmInterpretedFrame::GetAccOffset(GetEnvironment()->IsArch32Bit())));
171 }
172 
GetConstpoolFromMethod(GateRef glue,GateRef method)173 GateRef BaselineStubBuilder::GetConstpoolFromMethod(GateRef glue, GateRef method)
174 {
175     return Load(VariableType::JS_POINTER(), glue, method, IntPtr(Method::CONSTANT_POOL_OFFSET));
176 }
177 
GetProfileTypeInfoFromFunction(GateRef glue,GateRef function)178 GateRef BaselineStubBuilder::GetProfileTypeInfoFromFunction(GateRef glue, GateRef function)
179 {
180     GateRef raw = Load(VariableType::JS_POINTER(), glue, function, IntPtr(JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET));
181     return Load(VariableType::JS_POINTER(), glue, raw, IntPtr(ProfileTypeInfoCell::VALUE_OFFSET));
182 }
183 
GetHotnessCounterFromMethod(GateRef method)184 GateRef BaselineStubBuilder::GetHotnessCounterFromMethod(GateRef method)
185 {
186     GateRef x = LoadPrimitive(VariableType::INT16(), method, IntPtr(Method::LITERAL_INFO_OFFSET));
187     return GetEnvironment()->GetBuilder()->SExtInt1ToInt32(x);
188 }
189 
GetModuleFromFunction(GateRef glue,GateRef function)190 GateRef BaselineStubBuilder::GetModuleFromFunction(GateRef glue, GateRef function)
191 {
192     return Load(VariableType::JS_POINTER(), glue, function, IntPtr(JSFunction::ECMA_MODULE_OFFSET));
193 }
194 
GetHomeObjectFromFunction(GateRef glue,GateRef function)195 GateRef BaselineStubBuilder::GetHomeObjectFromFunction(GateRef glue, GateRef function)
196 {
197     return Load(VariableType::JS_POINTER(), glue, function, IntPtr(JSFunction::HOME_OBJECT_OFFSET));
198 }
199 
GetModule(GateRef glue,GateRef sp)200 GateRef BaselineStubBuilder::GetModule(GateRef glue, GateRef sp)
201 {
202     GateRef currentFunc = GetFunctionFromFrame(glue, GetFrame(sp));
203     return GetModuleFromFunction(glue, currentFunc);
204 }
205 
GetCurrentFrame(GateRef glue)206 GateRef BaselineStubBuilder::GetCurrentFrame(GateRef glue)
207 {
208     return GetLastLeaveFrame(glue);
209 }
210 
GetFrame(GateRef CurrentSp)211 GateRef BaselineStubBuilder::GetFrame(GateRef CurrentSp)
212 {
213     return PtrSub(CurrentSp, IntPtr(AsmInterpretedFrame::GetSize(GetEnvironment()->IsArch32Bit())));
214 }
215 
GetPcFromFrame(GateRef frame)216 GateRef BaselineStubBuilder::GetPcFromFrame(GateRef frame)
217 {
218     return LoadPrimitive(VariableType::NATIVE_POINTER(), frame,
219         IntPtr(AsmInterpretedFrame::GetPcOffset(GetEnvironment()->IsArch32Bit())));
220 }
221 
GetCallSizeFromFrame(GateRef frame)222 GateRef BaselineStubBuilder::GetCallSizeFromFrame(GateRef frame)
223 {
224     return LoadPrimitive(VariableType::NATIVE_POINTER(), frame,
225         IntPtr(AsmInterpretedFrame::GetCallSizeOffset(GetEnvironment()->IsArch32Bit())));
226 }
227 
GetThisFromFrame(GateRef glue,GateRef frame)228 GateRef BaselineStubBuilder::GetThisFromFrame(GateRef glue, GateRef frame)
229 {
230     return Load(VariableType::JS_POINTER(), glue, frame,
231                 IntPtr(AsmInterpretedFrame::GetThisOffset(GetEnvironment()->IsArch32Bit())));
232 }
233 
GetNewTarget(GateRef glue,GateRef sp)234 GateRef BaselineStubBuilder::GetNewTarget(GateRef glue, GateRef sp)
235 {
236     GateRef function = Load(VariableType::JS_POINTER(), glue, GetFrame(sp),
237                             IntPtr(AsmInterpretedFrame::GetFunctionOffset(GetEnvironment()->IsArch32Bit())));
238     GateRef method = GetMethodFromFunction(glue, function);
239     GateRef callField = GetCallFieldFromMethod(method);
240     // ASSERT: callField has "extra" bit.
241     GateRef numVregs =
242             TruncInt64ToInt32(Int64And(Int64LSR(callField, Int64(MethodLiteral::NumVregsBits::START_BIT)),
243                                        Int64((1LLU << MethodLiteral::NumVregsBits::SIZE) - 1)));
244     GateRef haveFunc =
245             ZExtInt1ToInt32(Int64NotEqual(Int64And(Int64LSR(callField, Int64(MethodLiteral::HaveFuncBit::START_BIT)),
246                 Int64((1LLU << MethodLiteral::HaveFuncBit::SIZE) - 1)), Int64(0)));
247     GateRef idx = ZExtInt32ToPtr(Int32Add(numVregs, haveFunc));
248     return Load(VariableType::JS_ANY(), glue, sp, PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()), idx));
249 }
250 
GetStartIdxAndNumArgs(GateRef glue,GateRef sp,GateRef restIdx)251 GateRef BaselineStubBuilder::GetStartIdxAndNumArgs(GateRef glue, GateRef sp, GateRef restIdx)
252 {
253     auto env = GetEnvironment();
254     Label subEntry(env);
255     env->SubCfgEntry(&subEntry);
256     DEFVARIABLE(numArgs, VariableType::INT32(), Int32(0));
257     GateRef state = PtrSub(sp, IntPtr(AsmInterpretedFrame::GetSize(env->IsArch32Bit())));
258     GateRef function = GetFunctionFromFrame(glue, state);
259     GateRef method = GetMethodFromJSFunctionOrProxy(glue, function);
260     GateRef callField = GetCallFieldFromMethod(method);
261     // ASSERT: callField has "extra" bit.
262     GateRef numVregs = TruncInt64ToInt32(Int64And(
263         Int64LSR(callField, Int64(MethodLiteral::NumVregsBits::START_BIT)),
264         Int64((1LLU << MethodLiteral::NumVregsBits::SIZE) - 1)));
265     GateRef haveFunc = Int64NotEqual(Int64And(Int64LSR(callField, Int64(MethodLiteral::HaveFuncBit::START_BIT)),
266         Int64((1LLU << MethodLiteral::HaveFuncBit::SIZE) - 1)), Int64(0));
267     GateRef haveNewTarget = Int64NotEqual(
268         Int64And(Int64LSR(callField, Int64(MethodLiteral::HaveNewTargetBit::START_BIT)),
269         Int64((1LLU << MethodLiteral::HaveNewTargetBit::SIZE) - 1)), Int64(0));
270     GateRef haveThis = Int64NotEqual(Int64And(Int64LSR(callField, Int64(MethodLiteral::HaveThisBit::START_BIT)),
271         Int64((1LLU << MethodLiteral::HaveThisBit::SIZE) - 1)), Int64(0));
272     GateRef copyArgs = Int32Add(Int32Add(ZExtInt1ToInt32(haveFunc), ZExtInt1ToInt32(haveNewTarget)),
273                                 ZExtInt1ToInt32(haveThis));
274     numArgs = TruncInt64ToInt32(Int64And(Int64LSR(callField, Int64(MethodLiteral::NumArgsBits::START_BIT)),
275                                          Int64((1LLU << MethodLiteral::NumArgsBits::SIZE) - 1)));
276     GateRef fp = LoadPrimitive(VariableType::NATIVE_POINTER(), state,
277         IntPtr(AsmInterpretedFrame::GetFpOffset(env->IsArch32Bit())));
278     Label actualEqualDeclared(env);
279     Label actualNotEqualDeclared(env);
280     Branch(Int32UnsignedGreaterThan(ChangeIntPtrToInt32(PtrSub(fp, sp)),
281                                     Int32Mul(Int32Add(Int32Add(numVregs, copyArgs), *numArgs),
282                                              Int32(sizeof(JSTaggedType)))),
283            &actualNotEqualDeclared, &actualEqualDeclared);
284     Bind(&actualNotEqualDeclared);
285     {
286         numArgs = GetInt32OfTInt(Load(VariableType::JS_ANY(), glue, fp,
287             IntPtr(static_cast<int64_t>(-sizeof(JSTaggedType)))));
288         Jump(&actualEqualDeclared);
289     }
290     Bind(&actualEqualDeclared);
291     GateRef startIdx = Int32Add(Int32Add(numVregs, copyArgs), restIdx);
292     Label numArgsGreater(env);
293     Label numArgsNotGreater(env);
294     Label exit(env);
295     Branch(Int32UnsignedGreaterThan(*numArgs, restIdx), &numArgsGreater, &numArgsNotGreater);
296     Bind(&numArgsGreater);
297     {
298         numArgs = Int32Sub(*numArgs, restIdx);
299         Jump(&exit);
300     }
301     Bind(&numArgsNotGreater);
302     {
303         numArgs = Int32(0);
304         Jump(&exit);
305     }
306     Bind(&exit);
307     // 32: high 32 bits = startIdx, low 32 bits = numArgs
308     GateRef ret = Int64Or(Int64LSL(ZExtInt32ToInt64(startIdx), Int64(32)), ZExtInt32ToInt64(*numArgs));
309     env->SubCfgExit();
310     return ret;
311 }
312 
SetVregValue(GateRef glue,GateRef sp,GateRef idx,GateRef val)313 void BaselineStubBuilder::SetVregValue(GateRef glue, GateRef sp, GateRef idx, GateRef val)
314 {
315     Store(VariableType::INT64(), glue, sp, PtrMul(IntPtr(sizeof(JSTaggedType)), idx), val);
316 }
317 
GetVregValue(GateRef glue,GateRef sp,GateRef idx)318 GateRef BaselineStubBuilder::GetVregValue(GateRef glue, GateRef sp, GateRef idx)
319 {
320     return Load(VariableType::JS_ANY(), glue, sp, PtrMul(IntPtr(sizeof(JSTaggedType)), idx));
321 }
322 
GetResumeModeFromGeneratorObject(GateRef obj)323 GateRef BaselineStubBuilder::GetResumeModeFromGeneratorObject(GateRef obj)
324 {
325     GateRef bitfieldOffset = IntPtr(JSGeneratorObject::BIT_FIELD_OFFSET);
326     GateRef bitfield = LoadPrimitive(VariableType::INT32(), obj, bitfieldOffset);
327     return Int32And(
328         Int32LSR(bitfield, Int32(JSGeneratorObject::ResumeModeBits::START_BIT)),
329         Int32((1LU << JSGeneratorObject::ResumeModeBits::SIZE) - 1));
330 }
331 
GetResumeModeFromAsyncGeneratorObject(GateRef obj)332 GateRef BaselineStubBuilder::GetResumeModeFromAsyncGeneratorObject(GateRef obj)
333 {
334     GateRef bitfieldOffset = IntPtr(JSAsyncGeneratorObject::BIT_FIELD_OFFSET);
335     GateRef bitfield = LoadPrimitive(VariableType::INT32(), obj, bitfieldOffset);
336     return Int32And(
337         Int32LSR(bitfield, Int32(JSAsyncGeneratorObject::ResumeModeBits::START_BIT)),
338         Int32((1LU << JSAsyncGeneratorObject::ResumeModeBits::SIZE) - 1));
339 }
340 
GetLastLeaveFrame(GateRef glue)341 GateRef BaselineStubBuilder::GetLastLeaveFrame(GateRef glue)
342 {
343     bool isArch32 = GetEnvironment()->Is32Bit();
344     GateRef spOffset = IntPtr(JSThread::GlueData::GetLeaveFrameOffset(isArch32));
345     return LoadPrimitive(VariableType::NATIVE_POINTER(), glue, spOffset);
346 }
347 }
348 
349 #endif // ECMASCRIPT_COMPILER_BASELINE_BASELINE_STUBS_INL_H
350