• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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_INTERPRETER_STUB_INL_H
17 #define ECMASCRIPT_COMPILER_INTERPRETER_STUB_INL_H
18 
19 #include "ecmascript/compiler/interpreter_stub.h"
20 #include "ecmascript/global_env.h"
21 #include "ecmascript/js_async_generator_object.h"
22 #include "ecmascript/js_arguments.h"
23 #include "ecmascript/js_function.h"
24 #include "ecmascript/js_generator_object.h"
25 
26 namespace panda::ecmascript::kungfu {
SetVregValue(GateRef glue,GateRef sp,GateRef idx,GateRef val)27 void InterpreterStubBuilder::SetVregValue(GateRef glue, GateRef sp, GateRef idx, GateRef val)
28 {
29     Store(VariableType::INT64(), glue, sp, PtrMul(IntPtr(sizeof(JSTaggedType)), idx), val);
30 }
31 
GetVregValue(GateRef sp,GateRef idx)32 inline GateRef InterpreterStubBuilder::GetVregValue(GateRef sp, GateRef idx)
33 {
34     return Load(VariableType::JS_ANY(), sp, PtrMul(IntPtr(sizeof(JSTaggedType)), idx));
35 }
36 
ReadInst8_0(GateRef pc)37 GateRef InterpreterStubBuilder::ReadInst8_0(GateRef pc)
38 {
39     return Load(VariableType::INT8(), pc, IntPtr(1));  // 1 : skip 1 byte of bytecode
40 }
41 
ReadInst8_1(GateRef pc)42 GateRef InterpreterStubBuilder::ReadInst8_1(GateRef pc)
43 {
44     return Load(VariableType::INT8(), pc, IntPtr(2));  // 2 : skip 1 byte of bytecode
45 }
46 
ReadInst8_2(GateRef pc)47 GateRef InterpreterStubBuilder::ReadInst8_2(GateRef pc)
48 {
49     return Load(VariableType::INT8(), pc, IntPtr(3));  // 3 : skip 1 byte of bytecode
50 }
51 
ReadInst8_3(GateRef pc)52 GateRef InterpreterStubBuilder::ReadInst8_3(GateRef pc)
53 {
54     return Load(VariableType::INT8(), pc, IntPtr(4));  // 4 : skip 1 byte of bytecode
55 }
56 
ReadInst8_4(GateRef pc)57 GateRef InterpreterStubBuilder::ReadInst8_4(GateRef pc)
58 {
59     return Load(VariableType::INT8(), pc, IntPtr(5));  // 5 : skip 1 byte of bytecode
60 }
61 
ReadInst8_5(GateRef pc)62 GateRef InterpreterStubBuilder::ReadInst8_5(GateRef pc)
63 {
64     return Load(VariableType::INT8(), pc, IntPtr(6));  // 6 : skip 1 byte of bytecode
65 }
66 
ReadInst8_6(GateRef pc)67 GateRef InterpreterStubBuilder::ReadInst8_6(GateRef pc)
68 {
69     return Load(VariableType::INT8(), pc, IntPtr(7));  // 7 : skip 1 byte of bytecode
70 }
71 
ReadInst8_7(GateRef pc)72 GateRef InterpreterStubBuilder::ReadInst8_7(GateRef pc)
73 {
74     return Load(VariableType::INT8(), pc, IntPtr(8));  // 8 : skip 1 byte of bytecode
75 }
76 
ReadInst8_8(GateRef pc)77 GateRef InterpreterStubBuilder::ReadInst8_8(GateRef pc)
78 {
79     return Load(VariableType::INT8(), pc, IntPtr(9));  // 9 : skip 1 byte of bytecode
80 }
81 
ReadInst8_9(GateRef pc)82 GateRef InterpreterStubBuilder::ReadInst8_9(GateRef pc)
83 {
84     return Load(VariableType::INT8(), pc, IntPtr(10));  // 10 : skip 1 byte of bytecode
85 }
86 
ReadInst4_0(GateRef pc)87 GateRef InterpreterStubBuilder::ReadInst4_0(GateRef pc)
88 {
89     return Int8And(Load(VariableType::INT8(), pc, IntPtr(1)), Int8(0xf));
90 }
91 
ReadInst4_1(GateRef pc)92 GateRef InterpreterStubBuilder::ReadInst4_1(GateRef pc)
93 {
94     // 1 : skip 1 byte of bytecode
95     return Int8And(
96         Int8LSR(Load(VariableType::INT8(), pc, IntPtr(1)), Int8(4)), Int8(0xf));  // 4: read 4 byte of bytecode
97 }
98 
ReadInst4_2(GateRef pc)99 GateRef InterpreterStubBuilder::ReadInst4_2(GateRef pc)
100 {
101     // 2 : skip 1 byte of bytecode
102     return Int8And(Load(VariableType::INT8(), pc, IntPtr(2)), Int8(0xf));
103 }
104 
ReadInst4_3(GateRef pc)105 GateRef InterpreterStubBuilder::ReadInst4_3(GateRef pc)
106 {
107     return Int8And(Int8LSR(Load(VariableType::INT8(), pc, IntPtr(2)), // 2 : skip 1 byte of bytecode
108         Int8(4)), Int8(0xf));  // 4 : read 4 byte of bytecode
109 }
110 
ReadInstSigned8_0(GateRef pc)111 GateRef InterpreterStubBuilder::ReadInstSigned8_0(GateRef pc)
112 {
113     GateRef x = Load(VariableType::INT8(), pc, IntPtr(1));  // 1 : skip 1 byte of bytecode
114     return GetEnvironment()->GetBuilder()->SExtInt1ToInt32(x);
115 }
116 
ReadInstSigned16_0(GateRef pc)117 GateRef InterpreterStubBuilder::ReadInstSigned16_0(GateRef pc)
118 {
119     /* 2 : skip 8 bits of opcode and 8 bits of low bits */
120     GateRef currentInst = Load(VariableType::INT8(), pc, IntPtr(2));
121     GateRef currentInst1 = GetEnvironment()->GetBuilder()->SExtInt1ToInt32(currentInst);
122     GateRef currentInst2 = Int32LSL(currentInst1, Int32(8));  // 8 : set as high 8 bits
123     return Int32Add(currentInst2, ZExtInt8ToInt32(ReadInst8_0(pc)));
124 }
125 
ReadInstSigned32_0(GateRef pc)126 GateRef InterpreterStubBuilder::ReadInstSigned32_0(GateRef pc)
127 {
128     /* 4 : skip 8 bits of opcode and 24 bits of low bits */
129     GateRef x = Load(VariableType::INT8(), pc, IntPtr(4));
130     GateRef currentInst = GetEnvironment()->GetBuilder()->SExtInt1ToInt32(x);
131     GateRef currentInst1 = Int32LSL(currentInst, Int32(8));  // 8 : set as high 8 bits
132     GateRef currentInst2 = Int32Add(currentInst1, ZExtInt8ToInt32(ReadInst8_2(pc)));
133     GateRef currentInst3 = Int32LSL(currentInst2, Int32(8));  // 8 : set as high 8 bits
134     GateRef currentInst4 = Int32Add(currentInst3, ZExtInt8ToInt32(ReadInst8_1(pc)));
135     GateRef currentInst5 = Int32LSL(currentInst4, Int32(8));  // 8 : set as high 8 bits
136     return Int32Add(currentInst5, ZExtInt8ToInt32(ReadInst8_0(pc)));
137 }
138 
ReadInst16_0(GateRef pc)139 GateRef InterpreterStubBuilder::ReadInst16_0(GateRef pc)
140 {
141     /* 2 : skip 8 bits of opcode and 8 bits of low bits */
142     GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_1(pc));
143     GateRef currentInst2 = Int16LSL(currentInst1, Int16(8));  // 8 : set as high 8 bits
144     return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_0(pc)));
145 }
146 
ReadInst16_1(GateRef pc)147 GateRef InterpreterStubBuilder::ReadInst16_1(GateRef pc)
148 {
149     /* 3 : skip 8 bits of opcode, 8 bits of prefix and 8 bits of low bits */
150     GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_2(pc));
151     GateRef currentInst2 = Int16LSL(currentInst1, Int16(8));  // 8 : set as high 8 bits
152     /* 2 : skip 8 bits of opcode and 8 bits of prefix */
153     return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_1(pc)));
154 }
155 
ReadInst16_2(GateRef pc)156 GateRef InterpreterStubBuilder::ReadInst16_2(GateRef pc)
157 {
158     /* 4 : skip 8 bits of opcode, first parameter of 16 bits and 8 bits of low bits */
159     GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_3(pc));
160     GateRef currentInst2 = Int16LSL(currentInst1, Int16(8));  // 8 : set as high 8 bits
161     /* 3 : skip 8 bits of opcode and first parameter of 16 bits */
162     return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_2(pc)));
163 }
164 
ReadInst16_3(GateRef pc)165 GateRef InterpreterStubBuilder::ReadInst16_3(GateRef pc)
166 {
167     /* 5 : skip 8 bits of opcode, 8 bits of prefix, first parameter of 16 bits and 8 bits of low bits */
168     GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_4(pc));
169     GateRef currentInst2 = Int16LSL(currentInst1, Int16(8));  // 8 : set as high 8 bits
170     /* 4 : skip 8 bits of opcode, 8 bits of prefix and first parameter of 16 bits */
171     return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_3(pc)));
172 }
173 
ReadInst16_4(GateRef pc)174 GateRef InterpreterStubBuilder::ReadInst16_4(GateRef pc)
175 {
176     /* 7 : skip 8 bits of opcode, 8 bits of prefix, first 2 parameters of 16 bits and 8 bits of low bits */
177     GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_5(pc));
178     GateRef currentInst2 = Int16LSL(currentInst1, Int16(8));  // 8 : set as high 8 bits
179     /* 6 : skip 8 bits of opcode, 8 bits of prefix and first 2 parameters of 16 bits */
180     return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_4(pc)));
181 }
182 
ReadInst16_5(GateRef pc)183 GateRef InterpreterStubBuilder::ReadInst16_5(GateRef pc)
184 {
185     /* 7 : skip 8 bits of opcode, 8 bits of prefix, first 2 parameters of 16 bits and 8 bits of low bits */
186     GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_6(pc));
187     GateRef currentInst2 = Int16LSL(currentInst1, Int16(8));  // 8 : set as high 8 bits
188     /* 6 : skip 8 bits of opcode, 8 bits of prefix and first 2 parameters of 16 bits */
189     return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_5(pc)));
190 }
191 
ReadInst16_6(GateRef pc)192 GateRef InterpreterStubBuilder::ReadInst16_6(GateRef pc)
193 {
194     /* 7 : skip 8 bits of opcode, 8 bits of prefix, first 2 parameters of 16 bits and 8 bits of low bits */
195     GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_7(pc));
196     GateRef currentInst2 = Int16LSL(currentInst1, Int16(8));  // 8 : set as high 8 bits
197     /* 6 : skip 8 bits of opcode, 8 bits of prefix and first 2 parameters of 16 bits */
198     return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_6(pc)));
199 }
200 
ReadInst16_7(GateRef pc)201 GateRef InterpreterStubBuilder::ReadInst16_7(GateRef pc)
202 {
203     /* 7 : skip 8 bits of opcode, 8 bits of prefix, first 2 parameters of 16 bits and 8 bits of low bits */
204     GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_8(pc));
205     GateRef currentInst2 = Int16LSL(currentInst1, Int16(8));  // 8 : set as high 8 bits
206     /* 6 : skip 8 bits of opcode, 8 bits of prefix and first 2 parameters of 16 bits */
207     return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_9(pc)));
208 }
209 
GetFrame(GateRef CurrentSp)210 GateRef InterpreterStubBuilder::GetFrame(GateRef CurrentSp)
211 {
212     return PtrSub(CurrentSp, IntPtr(AsmInterpretedFrame::GetSize(GetEnvironment()->IsArch32Bit())));
213 }
214 
GetPcFromFrame(GateRef frame)215 GateRef InterpreterStubBuilder::GetPcFromFrame(GateRef frame)
216 {
217     return Load(VariableType::NATIVE_POINTER(), frame,
218         IntPtr(AsmInterpretedFrame::GetPcOffset(GetEnvironment()->IsArch32Bit())));
219 }
220 
GetFunctionFromFrame(GateRef frame)221 GateRef InterpreterStubBuilder::GetFunctionFromFrame(GateRef frame)
222 {
223     return Load(VariableType::JS_POINTER(), frame,
224         IntPtr(AsmInterpretedFrame::GetFunctionOffset(GetEnvironment()->IsArch32Bit())));
225 }
226 
GetNewTarget(GateRef sp)227 GateRef InterpreterStubBuilder::GetNewTarget(GateRef sp)
228 {
229     GateRef function = Load(VariableType::JS_POINTER(), GetFrame(sp),
230         IntPtr(AsmInterpretedFrame::GetFunctionOffset(GetEnvironment()->IsArch32Bit())));
231     GateRef method = GetMethodFromFunction(function);
232     GateRef callField = GetCallFieldFromMethod(method);
233     // ASSERT: callField has "extra" bit.
234     GateRef numVregs = TruncInt64ToInt32(Int64And(Int64LSR(callField, Int64(MethodLiteral::NumVregsBits::START_BIT)),
235         Int64((1LLU << MethodLiteral::NumVregsBits::SIZE) - 1)));
236     GateRef haveFunc = ZExtInt1ToInt32(Int64NotEqual(Int64And(Int64LSR(callField,
237         Int64(MethodLiteral::HaveFuncBit::START_BIT)),
238         Int64((1LLU << MethodLiteral::HaveFuncBit::SIZE) - 1)), Int64(0)));
239     GateRef idx = ZExtInt32ToPtr(Int32Add(numVregs, haveFunc));
240     return Load(VariableType::JS_ANY(), sp, PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()), idx));
241 }
242 
GetThisFromFrame(GateRef frame)243 GateRef InterpreterStubBuilder::GetThisFromFrame(GateRef frame)
244 {
245     return Load(VariableType::JS_POINTER(), frame,
246         IntPtr(AsmInterpretedFrame::GetThisOffset(GetEnvironment()->IsArch32Bit())));
247 }
248 
GetCallSizeFromFrame(GateRef frame)249 GateRef InterpreterStubBuilder::GetCallSizeFromFrame(GateRef frame)
250 {
251     return Load(VariableType::NATIVE_POINTER(), frame,
252         IntPtr(AsmInterpretedFrame::GetCallSizeOffset(GetEnvironment()->IsArch32Bit())));
253 }
254 
GetAccFromFrame(GateRef frame)255 GateRef InterpreterStubBuilder::GetAccFromFrame(GateRef frame)
256 {
257     return Load(VariableType::JS_ANY(), frame,
258         IntPtr(AsmInterpretedFrame::GetAccOffset(GetEnvironment()->IsArch32Bit())));
259 }
260 
GetEnvFromFrame(GateRef frame)261 GateRef InterpreterStubBuilder::GetEnvFromFrame(GateRef frame)
262 {
263     return Load(VariableType::JS_POINTER(), frame,
264         IntPtr(AsmInterpretedFrame::GetEnvOffset(GetEnvironment()->IsArch32Bit())));
265 }
266 
GetEnvFromFunction(GateRef function)267 GateRef InterpreterStubBuilder::GetEnvFromFunction(GateRef function)
268 {
269     return Load(VariableType::JS_POINTER(), function, IntPtr(JSFunction::LEXICAL_ENV_OFFSET));
270 }
271 
GetProfileTypeInfoFromMethod(GateRef method)272 GateRef InterpreterStubBuilder::GetProfileTypeInfoFromMethod(GateRef method)
273 {
274     return Load(VariableType::JS_POINTER(), method, IntPtr(Method::PROFILE_TYPE_INFO_OFFSET));
275 }
276 
GetModuleFromFunction(GateRef function)277 GateRef InterpreterStubBuilder::GetModuleFromFunction(GateRef function)
278 {
279     GateRef method = GetMethodFromFunction(function);
280     return Load(VariableType::JS_POINTER(), method, IntPtr(Method::ECMA_MODULE_OFFSET));
281 }
282 
GetHomeObjectFromFunction(GateRef function)283 GateRef InterpreterStubBuilder::GetHomeObjectFromFunction(GateRef function)
284 {
285     return Load(VariableType::JS_POINTER(), function, IntPtr(JSFunction::HOME_OBJECT_OFFSET));
286 }
287 
GetConstpoolFromMethod(GateRef method)288 GateRef InterpreterStubBuilder::GetConstpoolFromMethod(GateRef method)
289 {
290     return Load(VariableType::JS_POINTER(), method, IntPtr(Method::CONSTANT_POOL_OFFSET));
291 }
292 
GetModule(GateRef sp)293 GateRef InterpreterStubBuilder::GetModule(GateRef sp)
294 {
295     GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp));
296     return GetModuleFromFunction(currentFunc);
297 }
298 
GetResumeModeFromGeneratorObject(GateRef obj)299 GateRef InterpreterStubBuilder::GetResumeModeFromGeneratorObject(GateRef obj)
300 {
301     GateRef bitfieldOffset = IntPtr(JSGeneratorObject::BIT_FIELD_OFFSET);
302     GateRef bitfield = Load(VariableType::INT32(), obj, bitfieldOffset);
303     return Int32And(
304         Int32LSR(bitfield, Int32(JSGeneratorObject::ResumeModeBits::START_BIT)),
305         Int32((1LU << JSGeneratorObject::ResumeModeBits::SIZE) - 1));
306 }
307 
GetResumeModeFromAsyncGeneratorObject(GateRef obj)308 GateRef InterpreterStubBuilder::GetResumeModeFromAsyncGeneratorObject(GateRef obj)
309 {
310     GateRef bitfieldOffset = IntPtr(JSAsyncGeneratorObject::BIT_FIELD_OFFSET);
311     GateRef bitfield = Load(VariableType::INT32(), obj, bitfieldOffset);
312     return Int32And(
313         Int32LSR(bitfield, Int32(JSAsyncGeneratorObject::ResumeModeBits::START_BIT)),
314         Int32((1LU << JSAsyncGeneratorObject::ResumeModeBits::SIZE) - 1));
315 }
316 
SetPcToFrame(GateRef glue,GateRef frame,GateRef value)317 void InterpreterStubBuilder::SetPcToFrame(GateRef glue, GateRef frame, GateRef value)
318 {
319     Store(VariableType::INT64(), glue, frame,
320         IntPtr(AsmInterpretedFrame::GetPcOffset(GetEnvironment()->IsArch32Bit())), value);
321 }
322 
SetCallSizeToFrame(GateRef glue,GateRef frame,GateRef value)323 void InterpreterStubBuilder::SetCallSizeToFrame(GateRef glue, GateRef frame, GateRef value)
324 {
325     Store(VariableType::NATIVE_POINTER(), glue, frame,
326           IntPtr(AsmInterpretedFrame::GetCallSizeOffset(GetEnvironment()->IsArch32Bit())), value);
327 }
328 
SetAccToFrame(GateRef glue,GateRef frame,GateRef value)329 void InterpreterStubBuilder::SetAccToFrame(GateRef glue, GateRef frame, GateRef value)
330 {
331     Store(VariableType::INT64(), glue, frame,
332           IntPtr(AsmInterpretedFrame::GetAccOffset(GetEnvironment()->IsArch32Bit())), value);
333 }
334 
SetEnvToFrame(GateRef glue,GateRef frame,GateRef value)335 void InterpreterStubBuilder::SetEnvToFrame(GateRef glue, GateRef frame, GateRef value)
336 {
337     Store(VariableType::INT64(), glue, frame,
338           IntPtr(AsmInterpretedFrame::GetEnvOffset(GetEnvironment()->IsArch32Bit())), value);
339 }
340 
SetFunctionToFrame(GateRef glue,GateRef frame,GateRef value)341 void InterpreterStubBuilder::SetFunctionToFrame(GateRef glue, GateRef frame, GateRef value)
342 {
343     Store(VariableType::INT64(), glue, frame,
344           IntPtr(AsmInterpretedFrame::GetFunctionOffset(GetEnvironment()->IsArch32Bit())), value);
345 }
346 
SetHomeObjectToFunction(GateRef glue,GateRef function,GateRef value)347 void InterpreterStubBuilder::SetHomeObjectToFunction(GateRef glue, GateRef function, GateRef value)
348 {
349     GateRef offset = IntPtr(JSFunction::HOME_OBJECT_OFFSET);
350     Store(VariableType::JS_ANY(), glue, function, offset, value);
351 }
352 
SetFrameState(GateRef glue,GateRef sp,GateRef function,GateRef acc,GateRef env,GateRef pc,GateRef prev,GateRef type)353 void InterpreterStubBuilder::SetFrameState(GateRef glue, GateRef sp, GateRef function, GateRef acc,
354     GateRef env, GateRef pc, GateRef prev, GateRef type)
355 {
356     GateRef state = GetFrame(sp);
357     SetFunctionToFrame(glue, state, function);
358     SetAccToFrame(glue, state, acc);
359     SetEnvToFrame(glue, state, env);
360     SetPcToFrame(glue, state, pc);
361     GateRef prevOffset = IntPtr(AsmInterpretedFrame::GetBaseOffset(GetEnvironment()->IsArch32Bit()));
362     Store(VariableType::NATIVE_POINTER(), glue, state, prevOffset, prev);
363     GateRef frameTypeOffset = PtrAdd(prevOffset, IntPtr(
364         InterpretedFrameBase::GetTypeOffset(GetEnvironment()->IsArch32Bit())));
365     Store(VariableType::INT64(), glue, state, frameTypeOffset, type);
366 }
367 
GetCurrentSpFrame(GateRef glue)368 GateRef InterpreterStubBuilder::GetCurrentSpFrame(GateRef glue)
369 {
370     bool isArch32 = GetEnvironment()->Is32Bit();
371     GateRef spOffset = IntPtr(JSThread::GlueData::GetCurrentFrameOffset(isArch32));
372     return Load(VariableType::NATIVE_POINTER(), glue, spOffset);
373 }
374 
SetCurrentSpFrame(GateRef glue,GateRef value)375 void InterpreterStubBuilder::SetCurrentSpFrame(GateRef glue, GateRef value)
376 {
377     GateRef spOffset = IntPtr(JSThread::GlueData::GetCurrentFrameOffset(GetEnvironment()->Is32Bit()));
378     Store(VariableType::NATIVE_POINTER(), glue, glue, spOffset, value);
379 }
380 
GetLastLeaveFrame(GateRef glue)381 GateRef InterpreterStubBuilder::GetLastLeaveFrame(GateRef glue)
382 {
383     bool isArch32 = GetEnvironment()->Is32Bit();
384     GateRef spOffset = IntPtr(JSThread::GlueData::GetLeaveFrameOffset(isArch32));
385     return Load(VariableType::NATIVE_POINTER(), glue, spOffset);
386 }
387 
SetLastLeaveFrame(GateRef glue,GateRef value)388 void InterpreterStubBuilder::SetLastLeaveFrame(GateRef glue, GateRef value)
389 {
390     GateRef spOffset = IntPtr(JSThread::GlueData::GetLeaveFrameOffset(GetEnvironment()->Is32Bit()));
391     Store(VariableType::NATIVE_POINTER(), glue, glue, spOffset, value);
392 }
393 
CheckStackOverflow(GateRef glue,GateRef sp)394 GateRef InterpreterStubBuilder::CheckStackOverflow(GateRef glue, GateRef sp)
395 {
396     GateRef frameBaseOffset = IntPtr(JSThread::GlueData::GetFrameBaseOffset(GetEnvironment()->IsArch32Bit()));
397     GateRef frameBase = Load(VariableType::NATIVE_POINTER(), glue, frameBaseOffset);
398     return Int64UnsignedLessThanOrEqual(sp,
399         PtrAdd(frameBase, IntPtr(JSThread::RESERVE_STACK_SIZE * sizeof(JSTaggedType))));
400 }
401 
PushArg(GateRef glue,GateRef sp,GateRef value)402 GateRef InterpreterStubBuilder::PushArg(GateRef glue, GateRef sp, GateRef value)
403 {
404     GateRef newSp = PtrSub(sp, IntPtr(sizeof(JSTaggedType)));
405     // 0 : skip 0 byte of bytecode
406     Store(VariableType::INT64(), glue, newSp, IntPtr(0), value);
407     return newSp;
408 }
409 
PushUndefined(GateRef glue,GateRef sp,GateRef num)410 GateRef InterpreterStubBuilder::PushUndefined(GateRef glue, GateRef sp, GateRef num)
411 {
412     auto env = GetEnvironment();
413     Label subEntry(env);
414     env->SubCfgEntry(&subEntry);
415     DEFVARIABLE(newSp, VariableType::NATIVE_POINTER(), sp);
416     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
417     Label pushUndefinedBegin(env);
418     Label pushUndefinedAgain(env);
419     Label pushUndefinedEnd(env);
420     Branch(Int32LessThan(*i, num), &pushUndefinedBegin, &pushUndefinedEnd);
421     LoopBegin(&pushUndefinedBegin);
422     newSp = PushArg(glue, *newSp, Undefined());
423     i = Int32Add(*i, Int32(1));  // 1 : set as high 1 bits
424     Branch(Int32LessThan(*i, num), &pushUndefinedAgain, &pushUndefinedEnd);
425     Bind(&pushUndefinedAgain);
426     LoopEnd(&pushUndefinedBegin);
427     Bind(&pushUndefinedEnd);
428     auto ret = *newSp;
429     env->SubCfgExit();
430     return ret;
431 }
432 
PushRange(GateRef glue,GateRef sp,GateRef array,GateRef startIndex,GateRef endIndex)433 GateRef InterpreterStubBuilder::PushRange(GateRef glue, GateRef sp, GateRef array, GateRef startIndex, GateRef endIndex)
434 {
435     auto env = GetEnvironment();
436     Label subEntry(env);
437     env->SubCfgEntry(&subEntry);
438     DEFVARIABLE(newSp, VariableType::NATIVE_POINTER(), sp);
439     DEFVARIABLE(i, VariableType::INT32(), endIndex);
440     Label pushArgsBegin(env);
441     Label pushArgsAgain(env);
442     Label pushArgsEnd(env);
443     Branch(Int32GreaterThanOrEqual(*i, startIndex), &pushArgsBegin, &pushArgsEnd);
444     LoopBegin(&pushArgsBegin);
445     GateRef arg = GetVregValue(array, ZExtInt32ToPtr(*i));
446     newSp = PushArg(glue, *newSp, arg);
447     i = Int32Sub(*i, Int32(1));  // 1 : set as high 1 bits
448     Branch(Int32GreaterThanOrEqual(*i, startIndex), &pushArgsAgain, &pushArgsEnd);
449     Bind(&pushArgsAgain);
450     LoopEnd(&pushArgsBegin);
451     Bind(&pushArgsEnd);
452     auto ret = *newSp;
453     env->SubCfgExit();
454     return ret;
455 }
456 
GetStartIdxAndNumArgs(GateRef sp,GateRef restIdx)457 GateRef InterpreterStubBuilder::GetStartIdxAndNumArgs(GateRef sp, GateRef restIdx)
458 {
459     auto env = GetEnvironment();
460     Label subEntry(env);
461     env->SubCfgEntry(&subEntry);
462     DEFVARIABLE(numArgs, VariableType::INT32(), Int32(0));
463     GateRef state = PtrSub(sp, IntPtr(AsmInterpretedFrame::GetSize(env->IsArch32Bit())));
464     GateRef function = GetFunctionFromFrame(state);
465     GateRef method = GetMethodFromJSFunction(function);
466     GateRef callField = GetCallFieldFromMethod(method);
467     // ASSERT: callField has "extra" bit.
468     GateRef numVregs = TruncInt64ToInt32(Int64And(Int64LSR(callField, Int64(MethodLiteral::NumVregsBits::START_BIT)),
469         Int64((1LLU << MethodLiteral::NumVregsBits::SIZE) - 1)));
470     GateRef haveFunc = Int64NotEqual(Int64And(Int64LSR(callField, Int64(MethodLiteral::HaveFuncBit::START_BIT)),
471         Int64((1LLU << MethodLiteral::HaveFuncBit::SIZE) - 1)), Int64(0));
472     GateRef haveNewTarget = Int64NotEqual(
473         Int64And(Int64LSR(callField, Int64(MethodLiteral::HaveNewTargetBit::START_BIT)),
474         Int64((1LLU << MethodLiteral::HaveNewTargetBit::SIZE) - 1)), Int64(0));
475     GateRef haveThis = Int64NotEqual(Int64And(Int64LSR(callField, Int64(MethodLiteral::HaveThisBit::START_BIT)),
476         Int64((1LLU << MethodLiteral::HaveThisBit::SIZE) - 1)), Int64(0));
477     GateRef copyArgs = Int32Add(Int32Add(ZExtInt1ToInt32(haveFunc), ZExtInt1ToInt32(haveNewTarget)),
478                                 ZExtInt1ToInt32(haveThis));
479     numArgs = TruncInt64ToInt32(Int64And(Int64LSR(callField, Int64(MethodLiteral::NumArgsBits::START_BIT)),
480                                          Int64((1LLU << MethodLiteral::NumArgsBits::SIZE) - 1)));
481     GateRef fp = Load(VariableType::NATIVE_POINTER(), state,
482                       IntPtr(AsmInterpretedFrame::GetFpOffset(env->IsArch32Bit())));
483     Label actualEqualDeclared(env);
484     Label actualNotEqualDeclared(env);
485     Branch(Int32UnsignedGreaterThan(ChangeIntPtrToInt32(PtrSub(fp, sp)),
486                                     Int32Mul(Int32Add(Int32Add(numVregs, copyArgs), *numArgs),
487                                              Int32(sizeof(JSTaggedType)))),
488            &actualNotEqualDeclared, &actualEqualDeclared);
489     Bind(&actualNotEqualDeclared);
490     {
491         numArgs = GetInt32OfTInt(Load(VariableType::JS_ANY(), fp, IntPtr(-sizeof(JSTaggedType))));
492         Jump(&actualEqualDeclared);
493     }
494     Bind(&actualEqualDeclared);
495     GateRef startIdx = Int32Add(Int32Add(numVregs, copyArgs), restIdx);
496     Label numArgsGreater(env);
497     Label numArgsNotGreater(env);
498     Label exit(env);
499     Branch(Int32UnsignedGreaterThan(*numArgs, restIdx), &numArgsGreater, &numArgsNotGreater);
500     Bind(&numArgsGreater);
501     {
502         numArgs = Int32Sub(*numArgs, restIdx);
503         Jump(&exit);
504     }
505     Bind(&numArgsNotGreater);
506     {
507         numArgs = Int32(0);
508         Jump(&exit);
509     }
510     Bind(&exit);
511     // 32: high 32 bits = startIdx, low 32 bits = numArgs
512     GateRef ret = Int64Or(Int64LSL(ZExtInt32ToInt64(startIdx), Int64(32)), ZExtInt32ToInt64(*numArgs));
513     env->SubCfgExit();
514     return ret;
515 }
516 
GetCurrentFrame(GateRef glue)517 GateRef InterpreterStubBuilder::GetCurrentFrame(GateRef glue)
518 {
519     return GetLastLeaveFrame(glue);
520 }
521 
ReadInst32_0(GateRef pc)522 GateRef InterpreterStubBuilder::ReadInst32_0(GateRef pc)
523 {
524     GateRef currentInst = ZExtInt8ToInt32(ReadInst8_3(pc));
525     GateRef currentInst1 = Int32LSL(currentInst, Int32(8));  // 8 : set as high 8 bits
526     GateRef currentInst2 = Int32Add(currentInst1, ZExtInt8ToInt32(ReadInst8_2(pc)));
527     GateRef currentInst3 = Int32LSL(currentInst2, Int32(8));  // 8 : set as high 8 bits
528     GateRef currentInst4 = Int32Add(currentInst3, ZExtInt8ToInt32(ReadInst8_1(pc)));
529     GateRef currentInst5 = Int32LSL(currentInst4, Int32(8));  // 8 : set as high 8 bits
530     return Int32Add(currentInst5, ZExtInt8ToInt32(ReadInst8_0(pc)));
531 }
532 
ReadInst32_1(GateRef pc)533 GateRef InterpreterStubBuilder::ReadInst32_1(GateRef pc)
534 {
535     GateRef currentInst = ZExtInt8ToInt32(ReadInst8_4(pc));
536     GateRef currentInst1 = Int32LSL(currentInst, Int32(8));  // 8 : set as high 8 bits
537     GateRef currentInst2 = Int32Add(currentInst1, ZExtInt8ToInt32(ReadInst8_3(pc)));
538     GateRef currentInst3 = Int32LSL(currentInst2, Int32(8));  // 8 : set as high 8 bits
539     GateRef currentInst4 = Int32Add(currentInst3, ZExtInt8ToInt32(ReadInst8_2(pc)));
540     GateRef currentInst5 = Int32LSL(currentInst4, Int32(8));  // 8 : set as high 8 bits
541     return Int32Add(currentInst5, ZExtInt8ToInt32(ReadInst8_1(pc)));
542 }
543 
ReadInst32_2(GateRef pc)544 GateRef InterpreterStubBuilder::ReadInst32_2(GateRef pc)
545 {
546     GateRef currentInst = ZExtInt8ToInt32(ReadInst8_5(pc));
547     GateRef currentInst1 = Int32LSL(currentInst, Int32(8));  // 8 : set as high 8 bits
548     GateRef currentInst2 = Int32Add(currentInst1, ZExtInt8ToInt32(ReadInst8_4(pc)));
549     GateRef currentInst3 = Int32LSL(currentInst2, Int32(8));  // 8 : set as high 8 bits
550     GateRef currentInst4 = Int32Add(currentInst3, ZExtInt8ToInt32(ReadInst8_3(pc)));
551     GateRef currentInst5 = Int32LSL(currentInst4, Int32(8));  // 8 : set as high 8 bits
552     return Int32Add(currentInst5, ZExtInt8ToInt32(ReadInst8_2(pc)));
553 }
554 
ReadInst64_0(GateRef pc)555 GateRef InterpreterStubBuilder::ReadInst64_0(GateRef pc)
556 {
557     GateRef currentInst = ZExtInt8ToInt64(ReadInst8_7(pc));
558     GateRef currentInst1 = Int64LSL(currentInst, Int64(8));  // 8 : set as high 8 bits
559     GateRef currentInst2 = Int64Add(currentInst1, ZExtInt8ToInt64(ReadInst8_6(pc)));
560     GateRef currentInst3 = Int64LSL(currentInst2, Int64(8));  // 8 : set as high 8 bits
561     GateRef currentInst4 = Int64Add(currentInst3, ZExtInt8ToInt64(ReadInst8_5(pc)));
562     GateRef currentInst5 = Int64LSL(currentInst4, Int64(8));  // 8 : set as high 8 bits
563     GateRef currentInst6 = Int64Add(currentInst5, ZExtInt8ToInt64(ReadInst8_4(pc)));
564     GateRef currentInst7 = Int64LSL(currentInst6, Int64(8));  // 8 : set as high 8 bits
565     GateRef currentInst8 = Int64Add(currentInst7, ZExtInt8ToInt64(ReadInst8_3(pc)));
566     GateRef currentInst9 = Int64LSL(currentInst8, Int64(8));  // 8 : set as high 8 bits
567     GateRef currentInst10 = Int64Add(currentInst9, ZExtInt8ToInt64(ReadInst8_2(pc)));
568     GateRef currentInst11 = Int64LSL(currentInst10, Int64(8));  // 8 : set as high 8 bits
569     GateRef currentInst12 = Int64Add(currentInst11, ZExtInt8ToInt64(ReadInst8_1(pc)));
570     GateRef currentInst13 = Int64LSL(currentInst12, Int64(8));  // 8 : set as high 8 bits
571     return Int64Add(currentInst13, ZExtInt8ToInt64(ReadInst8_0(pc)));
572 }
573 
574 template<typename... Args>
DispatchBase(GateRef target,GateRef glue,Args...args)575 void InterpreterStubBuilder::DispatchBase(GateRef target, GateRef glue, Args... args)
576 {
577     GetEnvironment()->GetBuilder()->CallBCHandler(glue, target, {glue, args...});
578 }
579 
Dispatch(GateRef glue,GateRef sp,GateRef pc,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter,GateRef format)580 void InterpreterStubBuilder::Dispatch(GateRef glue, GateRef sp, GateRef pc, GateRef constpool, GateRef profileTypeInfo,
581     GateRef acc, GateRef hotnessCounter, GateRef format)
582 {
583     GateRef newPc = PtrAdd(pc, format);
584     GateRef opcode = Load(VariableType::INT8(), newPc);
585     GateRef target = PtrMul(ZExtInt32ToPtr(ZExtInt8ToInt32(opcode)), IntPtrSize());
586     DispatchBase(target, glue, sp, newPc, constpool, profileTypeInfo, acc, hotnessCounter);
587     Return();
588 }
589 
DispatchLast(GateRef glue,GateRef sp,GateRef pc,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter)590 void InterpreterStubBuilder::DispatchLast(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
591     GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter)
592 {
593     GateRef target = PtrMul(IntPtr(BytecodeStubCSigns::ID_ExceptionHandler), IntPtrSize());
594     DispatchBase(target, glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter);
595     Return();
596 }
597 
DispatchDebugger(GateRef glue,GateRef sp,GateRef pc,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter)598 void InterpreterStubBuilder::DispatchDebugger(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
599     GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter)
600 {
601     GateRef opcode = Load(VariableType::INT8(), pc);
602     GateRef target = PtrMul(ZExtInt32ToPtr(ZExtInt8ToInt32(opcode)), IntPtrSize());
603     auto args = { glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter };
604     GetEnvironment()->GetBuilder()->CallBCDebugger(glue, target, args);
605     Return();
606 }
607 
DispatchDebuggerLast(GateRef glue,GateRef sp,GateRef pc,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter)608 void InterpreterStubBuilder::DispatchDebuggerLast(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
609     GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter)
610 {
611     GateRef target = PtrMul(IntPtr(BytecodeStubCSigns::ID_ExceptionHandler), IntPtrSize());
612     auto args = { glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter };
613     GetEnvironment()->GetBuilder()->CallBCDebugger(glue, target, args);
614     Return();
615 }
616 
GetHotnessCounterFromMethod(GateRef method)617 GateRef InterpreterStubBuilder::GetHotnessCounterFromMethod(GateRef method)
618 {
619     GateRef x = Load(VariableType::INT16(), method, IntPtr(Method::LITERAL_INFO_OFFSET));
620     return GetEnvironment()->GetBuilder()->SExtInt1ToInt32(x);
621 }
622 
DispatchWithId(GateRef glue,GateRef sp,GateRef pc,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter,GateRef index)623 void InterpreterStubBuilder::DispatchWithId(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
624     GateRef profileTypeInfo, GateRef acc,
625     GateRef hotnessCounter, GateRef index)
626 {
627     GateRef target = PtrMul(index, IntPtrSize());
628     DispatchBase(target, glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter);
629     Return();
630 }
631 
632 #define DISPATCH_LAST(acc)                                                                  \
633     DispatchLast(glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter)
634 #define DISPATCH(acc)                                                                       \
635     Dispatch(glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter, offset)
CheckException(GateRef glue,GateRef sp,GateRef pc,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter,GateRef res,GateRef offset)636 void InterpreterStubBuilder::CheckException(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
637                                             GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter,
638                                             GateRef res, GateRef offset)
639 {
640     auto env = GetEnvironment();
641     Label isException(env);
642     Label notException(env);
643     Branch(TaggedIsException(res), &isException, &notException);
644     Bind(&isException);
645     {
646         DISPATCH_LAST(acc);
647     }
648     Bind(&notException);
649     {
650         DISPATCH(acc);
651     }
652 }
653 
CheckPendingException(GateRef glue,GateRef sp,GateRef pc,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter,GateRef res,GateRef offset)654 void InterpreterStubBuilder::CheckPendingException(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
655                                                    GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter,
656                                                    GateRef res, GateRef offset)
657 {
658     auto env = GetEnvironment();
659     Label isException(env);
660     Label notException(env);
661     Branch(HasPendingException(glue), &isException, &notException);
662     Bind(&isException);
663     {
664         DISPATCH_LAST(acc);
665     }
666     Bind(&notException);
667     {
668         DISPATCH(res);
669     }
670 }
671 
CheckExceptionWithVar(GateRef glue,GateRef sp,GateRef pc,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter,GateRef res,GateRef offset)672 void InterpreterStubBuilder::CheckExceptionWithVar(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
673                                                    GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter,
674                                                    GateRef res, GateRef offset)
675 {
676     auto env = GetEnvironment();
677     Label isException(env);
678     Label notException(env);
679     Branch(TaggedIsException(res), &isException, &notException);
680     Bind(&isException);
681     {
682         DISPATCH_LAST(acc);
683     }
684     Bind(&notException);
685     {
686         DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc);
687         varAcc = res;
688         DISPATCH(*varAcc);
689     }
690 }
691 
CheckExceptionWithJump(GateRef glue,GateRef sp,GateRef pc,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter,GateRef res,Label * jump)692 void InterpreterStubBuilder::CheckExceptionWithJump(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
693                                                     GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter,
694                                                     GateRef res, Label *jump)
695 {
696     auto env = GetEnvironment();
697     Label isException(env);
698     Label notException(env);
699     Branch(TaggedIsException(res), &isException, &notException);
700     Bind(&isException);
701     {
702         DISPATCH_LAST(acc);
703     }
704     Bind(&notException);
705     {
706         Jump(jump);
707     }
708 }
709 
GetStringId(const StringIdInfo & info)710 GateRef InterpreterToolsStubBuilder::GetStringId(const StringIdInfo &info)
711 {
712     GateRef stringId;
713     switch (info.offset) {
714         case StringIdInfo::Offset::BYTE_0: {
715             if (info.length == StringIdInfo::Length::BITS_16) {
716                 stringId = ZExtInt16ToInt32(ReadInst16_0(info.pc));
717             } else {
718                 std::abort();
719             }
720             break;
721         }
722         case StringIdInfo::Offset::BYTE_1: {
723             if (info.length == StringIdInfo::Length::BITS_16) {
724                 stringId = ZExtInt16ToInt32(ReadInst16_1(info.pc));
725             } else if (info.length == StringIdInfo::Length::BITS_32) {
726                 stringId = ReadInst32_1(info.pc);
727             } else {
728                 std::abort();
729             }
730             break;
731         }
732         case StringIdInfo::Offset::BYTE_2: {
733             if (info.length == StringIdInfo::Length::BITS_16) {
734                 stringId = ZExtInt16ToInt32(ReadInst16_2(info.pc));
735             } else {
736                 std::abort();
737             }
738             break;
739         }
740         default: {
741             std::abort();
742             break;
743         }
744     }
745     return stringId;
746 }
747 #undef DISPATCH_LAST
748 #undef DISPATCH
749 } //  namespace panda::ecmascript::kungfu
750 #endif // ECMASCRIPT_COMPILER_INTERPRETER_STUB_INL_H
751