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