• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_COMPILER_INTERPRETER_STUB_INL_H
17 #define ECMASCRIPT_COMPILER_INTERPRETER_STUB_INL_H
18 
19 #include "ecmascript/compiler/interpreter_stub.h"
20 #include "ecmascript/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, &notException);
744     Bind(&isException);
745     {
746         DISPATCH_LAST(acc);
747     }
748     Bind(&notException);
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, &notException);
762     Bind(&isException);
763     {
764         DISPATCH_LAST(acc);
765     }
766     Bind(&notException);
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, &notException);
780     Bind(&isException);
781     {
782         DISPATCH_LAST(acc);
783     }
784     Bind(&notException);
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, &notException);
800     Bind(&isException);
801     {
802         DISPATCH_LAST(acc);
803     }
804     Bind(&notException);
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