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, ¬Exception);
739 Bind(&isException);
740 {
741 DISPATCH_LAST(acc);
742 }
743 Bind(¬Exception);
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, ¬Exception);
757 Bind(&isException);
758 {
759 DISPATCH_LAST(acc);
760 }
761 Bind(¬Exception);
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, ¬Exception);
775 Bind(&isException);
776 {
777 DISPATCH_LAST(acc);
778 }
779 Bind(¬Exception);
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, ¬Exception);
795 Bind(&isException);
796 {
797 DISPATCH_LAST(acc);
798 }
799 Bind(¬Exception);
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