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 }
597 Jump(&profileTypeInfoEnd);
598 }
599 Bind(&profileTypeInfoEnd);
600
601 env->SubCfgExit();
602 }
603
ReadInst32_0(GateRef pc)604 GateRef InterpreterStubBuilder::ReadInst32_0(GateRef pc)
605 {
606 if (GetEnvironment()->IsAArch64() || GetEnvironment()->IsAmd64()) {
607 return Load(VariableType::INT32(), pc, IntPtr(1)); // 1 : skip 1 byte of bytecode
608 }
609 GateRef currentInst = ZExtInt8ToInt32(ReadInst8_3(pc));
610 GateRef currentInst1 = Int32LSL(currentInst, Int32(8)); // 8 : set as high 8 bits
611 GateRef currentInst2 = Int32Add(currentInst1, ZExtInt8ToInt32(ReadInst8_2(pc)));
612 GateRef currentInst3 = Int32LSL(currentInst2, Int32(8)); // 8 : set as high 8 bits
613 GateRef currentInst4 = Int32Add(currentInst3, ZExtInt8ToInt32(ReadInst8_1(pc)));
614 GateRef currentInst5 = Int32LSL(currentInst4, Int32(8)); // 8 : set as high 8 bits
615 return Int32Add(currentInst5, ZExtInt8ToInt32(ReadInst8_0(pc)));
616 }
617
ReadInst32_1(GateRef pc)618 GateRef InterpreterStubBuilder::ReadInst32_1(GateRef pc)
619 {
620 if (GetEnvironment()->IsAArch64() || GetEnvironment()->IsAmd64()) {
621 return Load(VariableType::INT32(), pc, IntPtr(2)); // 2 : skip 2 bytes of bytecode
622 }
623 GateRef currentInst = ZExtInt8ToInt32(ReadInst8_4(pc));
624 GateRef currentInst1 = Int32LSL(currentInst, Int32(8)); // 8 : set as high 8 bits
625 GateRef currentInst2 = Int32Add(currentInst1, ZExtInt8ToInt32(ReadInst8_3(pc)));
626 GateRef currentInst3 = Int32LSL(currentInst2, Int32(8)); // 8 : set as high 8 bits
627 GateRef currentInst4 = Int32Add(currentInst3, ZExtInt8ToInt32(ReadInst8_2(pc)));
628 GateRef currentInst5 = Int32LSL(currentInst4, Int32(8)); // 8 : set as high 8 bits
629 return Int32Add(currentInst5, ZExtInt8ToInt32(ReadInst8_1(pc)));
630 }
631
ReadInst32_2(GateRef pc)632 GateRef InterpreterStubBuilder::ReadInst32_2(GateRef pc)
633 {
634 if (GetEnvironment()->IsAArch64() || GetEnvironment()->IsAmd64()) {
635 return Load(VariableType::INT32(), pc, IntPtr(3)); // 3 : skip 3 bytes of bytecode
636 }
637 GateRef currentInst = ZExtInt8ToInt32(ReadInst8_5(pc));
638 GateRef currentInst1 = Int32LSL(currentInst, Int32(8)); // 8 : set as high 8 bits
639 GateRef currentInst2 = Int32Add(currentInst1, ZExtInt8ToInt32(ReadInst8_4(pc)));
640 GateRef currentInst3 = Int32LSL(currentInst2, Int32(8)); // 8 : set as high 8 bits
641 GateRef currentInst4 = Int32Add(currentInst3, ZExtInt8ToInt32(ReadInst8_3(pc)));
642 GateRef currentInst5 = Int32LSL(currentInst4, Int32(8)); // 8 : set as high 8 bits
643 return Int32Add(currentInst5, ZExtInt8ToInt32(ReadInst8_2(pc)));
644 }
645
ReadInst64_0(GateRef pc)646 GateRef InterpreterStubBuilder::ReadInst64_0(GateRef pc)
647 {
648 if (GetEnvironment()->IsAArch64() || GetEnvironment()->IsAmd64()) {
649 return Load(VariableType::INT64(), pc, IntPtr(1)); // 1 : skip 1 byte of bytecode
650 }
651 GateRef currentInst = ZExtInt8ToInt64(ReadInst8_7(pc));
652 GateRef currentInst1 = Int64LSL(currentInst, Int64(8)); // 8 : set as high 8 bits
653 GateRef currentInst2 = Int64Add(currentInst1, ZExtInt8ToInt64(ReadInst8_6(pc)));
654 GateRef currentInst3 = Int64LSL(currentInst2, Int64(8)); // 8 : set as high 8 bits
655 GateRef currentInst4 = Int64Add(currentInst3, ZExtInt8ToInt64(ReadInst8_5(pc)));
656 GateRef currentInst5 = Int64LSL(currentInst4, Int64(8)); // 8 : set as high 8 bits
657 GateRef currentInst6 = Int64Add(currentInst5, ZExtInt8ToInt64(ReadInst8_4(pc)));
658 GateRef currentInst7 = Int64LSL(currentInst6, Int64(8)); // 8 : set as high 8 bits
659 GateRef currentInst8 = Int64Add(currentInst7, ZExtInt8ToInt64(ReadInst8_3(pc)));
660 GateRef currentInst9 = Int64LSL(currentInst8, Int64(8)); // 8 : set as high 8 bits
661 GateRef currentInst10 = Int64Add(currentInst9, ZExtInt8ToInt64(ReadInst8_2(pc)));
662 GateRef currentInst11 = Int64LSL(currentInst10, Int64(8)); // 8 : set as high 8 bits
663 GateRef currentInst12 = Int64Add(currentInst11, ZExtInt8ToInt64(ReadInst8_1(pc)));
664 GateRef currentInst13 = Int64LSL(currentInst12, Int64(8)); // 8 : set as high 8 bits
665 return Int64Add(currentInst13, ZExtInt8ToInt64(ReadInst8_0(pc)));
666 }
667
668 template<typename... Args>
DispatchBase(GateRef target,GateRef glue,Args...args)669 void InterpreterStubBuilder::DispatchBase(GateRef target, GateRef glue, Args... args)
670 {
671 GetEnvironment()->GetBuilder()->CallBCHandler(glue, target, {glue, args...});
672 }
673
Dispatch(GateRef glue,GateRef sp,GateRef pc,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter,GateRef format)674 void InterpreterStubBuilder::Dispatch(GateRef glue, GateRef sp, GateRef pc, GateRef constpool, GateRef profileTypeInfo,
675 GateRef acc, GateRef hotnessCounter, GateRef format)
676 {
677 GateRef newPc = PtrAdd(pc, format);
678 GateRef opcode = Load(VariableType::INT8(), newPc);
679 GateRef target = PtrMul(ZExtInt32ToPtr(ZExtInt8ToInt32(opcode)), IntPtrSize());
680 DispatchBase(target, glue, sp, newPc, constpool, profileTypeInfo, acc, hotnessCounter);
681 Return();
682 }
683
DispatchLast(GateRef glue,GateRef sp,GateRef pc,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter)684 void InterpreterStubBuilder::DispatchLast(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
685 GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter)
686 {
687 GateRef target = PtrMul(IntPtr(BytecodeStubCSigns::ID_ExceptionHandler), IntPtrSize());
688 DispatchBase(target, glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter);
689 Return();
690 }
691
DispatchDebugger(GateRef glue,GateRef sp,GateRef pc,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter)692 void InterpreterStubBuilder::DispatchDebugger(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
693 GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter)
694 {
695 GateRef opcode = Load(VariableType::INT8(), pc);
696 GateRef target = PtrMul(ZExtInt32ToPtr(ZExtInt8ToInt32(opcode)), IntPtrSize());
697 auto args = { glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter };
698 GetEnvironment()->GetBuilder()->CallBCDebugger(glue, target, args);
699 Return();
700 }
701
DispatchDebuggerLast(GateRef glue,GateRef sp,GateRef pc,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter)702 void InterpreterStubBuilder::DispatchDebuggerLast(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
703 GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter)
704 {
705 GateRef target = PtrMul(IntPtr(BytecodeStubCSigns::ID_ExceptionHandler), IntPtrSize());
706 auto args = { glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter };
707 GetEnvironment()->GetBuilder()->CallBCDebugger(glue, target, args);
708 Return();
709 }
710
GetHotnessCounterFromMethod(GateRef method)711 GateRef InterpreterStubBuilder::GetHotnessCounterFromMethod(GateRef method)
712 {
713 GateRef x = Load(VariableType::INT16(), method, IntPtr(Method::LITERAL_INFO_OFFSET));
714 return GetEnvironment()->GetBuilder()->SExtInt1ToInt32(x);
715 }
716
DispatchWithId(GateRef glue,GateRef sp,GateRef pc,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter,GateRef index)717 void InterpreterStubBuilder::DispatchWithId(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
718 GateRef profileTypeInfo, GateRef acc,
719 GateRef hotnessCounter, GateRef index)
720 {
721 GateRef target = PtrMul(index, IntPtrSize());
722 DispatchBase(target, glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter);
723 Return();
724 }
725
726 #define DISPATCH_LAST(acc) \
727 DispatchLast(glue, sp, pc, constpool, profileTypeInfo, acc, hotnessCounter)
728 #define DISPATCH(acc) \
729 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)730 void InterpreterStubBuilder::CheckException(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
731 GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter,
732 GateRef res, GateRef offset)
733 {
734 auto env = GetEnvironment();
735 Label isException(env);
736 Label notException(env);
737 BRANCH(TaggedIsException(res), &isException, ¬Exception);
738 Bind(&isException);
739 {
740 DISPATCH_LAST(acc);
741 }
742 Bind(¬Exception);
743 {
744 DISPATCH(acc);
745 }
746 }
747
CheckPendingException(GateRef glue,GateRef sp,GateRef pc,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter,GateRef res,GateRef offset)748 void InterpreterStubBuilder::CheckPendingException(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
749 GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter,
750 GateRef res, GateRef offset)
751 {
752 auto env = GetEnvironment();
753 Label isException(env);
754 Label notException(env);
755 BRANCH(HasPendingException(glue), &isException, ¬Exception);
756 Bind(&isException);
757 {
758 DISPATCH_LAST(acc);
759 }
760 Bind(¬Exception);
761 {
762 DISPATCH(res);
763 }
764 }
765
CheckExceptionWithVar(GateRef glue,GateRef sp,GateRef pc,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter,GateRef res,GateRef offset)766 void InterpreterStubBuilder::CheckExceptionWithVar(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
767 GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter,
768 GateRef res, GateRef offset)
769 {
770 auto env = GetEnvironment();
771 Label isException(env);
772 Label notException(env);
773 BRANCH(TaggedIsException(res), &isException, ¬Exception);
774 Bind(&isException);
775 {
776 DISPATCH_LAST(acc);
777 }
778 Bind(¬Exception);
779 {
780 DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc);
781 varAcc = res;
782 DISPATCH(*varAcc);
783 }
784 }
785
CheckExceptionWithJump(GateRef glue,GateRef sp,GateRef pc,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter,GateRef res,Label * jump)786 void InterpreterStubBuilder::CheckExceptionWithJump(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
787 GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter,
788 GateRef res, Label *jump)
789 {
790 auto env = GetEnvironment();
791 Label isException(env);
792 Label notException(env);
793 BRANCH(TaggedIsException(res), &isException, ¬Exception);
794 Bind(&isException);
795 {
796 DISPATCH_LAST(acc);
797 }
798 Bind(¬Exception);
799 {
800 Jump(jump);
801 }
802 }
803
GetStringId(const StringIdInfo & info)804 GateRef InterpreterToolsStubBuilder::GetStringId(const StringIdInfo &info)
805 {
806 if (info.GetStringIdType() == StringIdInfo::StringIdType::STRING_ID) {
807 return info.GetStringId();
808 }
809 GateRef stringId;
810 switch (info.GetOffset()) {
811 case StringIdInfo::Offset::BYTE_0: {
812 if (info.GetLength() == StringIdInfo::Length::BITS_16) {
813 stringId = ZExtInt16ToInt32(ReadInst16_0(info.GetPc()));
814 } else {
815 std::abort();
816 }
817 break;
818 }
819 case StringIdInfo::Offset::BYTE_1: {
820 if (info.GetLength() == StringIdInfo::Length::BITS_16) {
821 stringId = ZExtInt16ToInt32(ReadInst16_1(info.GetPc()));
822 } else if (info.GetLength() == StringIdInfo::Length::BITS_32) {
823 stringId = ReadInst32_1(info.GetPc());
824 } else {
825 std::abort();
826 }
827 break;
828 }
829 case StringIdInfo::Offset::BYTE_2: {
830 if (info.GetLength() == StringIdInfo::Length::BITS_16) {
831 stringId = ZExtInt16ToInt32(ReadInst16_2(info.GetPc()));
832 } else {
833 std::abort();
834 }
835 break;
836 }
837 default: {
838 std::abort();
839 break;
840 }
841 }
842 return stringId;
843 }
844 #undef DISPATCH_LAST
845 #undef DISPATCH
846 } // namespace panda::ecmascript::kungfu
847 #endif // ECMASCRIPT_COMPILER_INTERPRETER_STUB_INL_H
848