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