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