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, ¬Exception);
613 Bind(&isException);
614 {
615 DISPATCH_LAST(acc);
616 }
617 Bind(¬Exception);
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, ¬Exception);
631 Bind(&isException);
632 {
633 DISPATCH_LAST(acc);
634 }
635 Bind(¬Exception);
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, ¬Exception);
649 Bind(&isException);
650 {
651 DISPATCH_LAST(acc);
652 }
653 Bind(¬Exception);
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, ¬Exception);
669 Bind(&isException);
670 {
671 DISPATCH_LAST(acc);
672 }
673 Bind(¬Exception);
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