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