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