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