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
21 namespace panda::ecmascript::kungfu {
SetVregValue(GateRef glue,GateRef sp,GateRef idx,GateRef val)22 void InterpreterStub::SetVregValue(GateRef glue, GateRef sp, GateRef idx, GateRef val)
23 {
24 Store(StubMachineType::UINT64, glue, sp, IntPtrMul(GetIntPtrConstant(sizeof(JSTaggedType)), idx), val);
25 }
26
GetVregValue(GateRef sp,GateRef idx)27 GateRef InterpreterStub::GetVregValue(GateRef sp, GateRef idx)
28 {
29 return Load(StubMachineType::TAGGED, sp, IntPtrMul(GetIntPtrConstant(sizeof(JSTaggedType)), idx));
30 }
31
ReadInst8_0(GateRef pc)32 GateRef InterpreterStub::ReadInst8_0(GateRef pc)
33 {
34 return Load(StubMachineType::UINT8, pc, GetIntPtrConstant(1));
35 }
36
ReadInst8_1(GateRef pc)37 GateRef InterpreterStub::ReadInst8_1(GateRef pc)
38 {
39 return Load(StubMachineType::UINT8, pc, GetIntPtrConstant(2)); // 2 : skip 1 byte of bytecode
40 }
41
ReadInst8_2(GateRef pc)42 GateRef InterpreterStub::ReadInst8_2(GateRef pc)
43 {
44 return Load(StubMachineType::UINT8, pc, GetIntPtrConstant(3)); // 3 : skip 1 byte of bytecode
45 }
46
ReadInst8_3(GateRef pc)47 GateRef InterpreterStub::ReadInst8_3(GateRef pc)
48 {
49 return Load(StubMachineType::UINT8, pc, GetIntPtrConstant(4)); // 4 : skip 1 byte of bytecode
50 }
51
ReadInst8_4(GateRef pc)52 GateRef InterpreterStub::ReadInst8_4(GateRef pc)
53 {
54 return Load(StubMachineType::UINT8, pc, GetIntPtrConstant(5)); // 5 : skip 1 byte of bytecode
55 }
56
ReadInst8_5(GateRef pc)57 GateRef InterpreterStub::ReadInst8_5(GateRef pc)
58 {
59 return Load(StubMachineType::UINT8, pc, GetIntPtrConstant(6)); // 6 : skip 1 byte of bytecode
60 }
61
ReadInst8_6(GateRef pc)62 GateRef InterpreterStub::ReadInst8_6(GateRef pc)
63 {
64 return Load(StubMachineType::UINT8, pc, GetIntPtrConstant(7)); // 7 : skip 1 byte of bytecode
65 }
66
ReadInst8_7(GateRef pc)67 GateRef InterpreterStub::ReadInst8_7(GateRef pc)
68 {
69 return Load(StubMachineType::UINT8, pc, GetIntPtrConstant(8)); // 8 : skip 1 byte of bytecode
70 }
71
ReadInst8_8(GateRef pc)72 GateRef InterpreterStub::ReadInst8_8(GateRef pc)
73 {
74 return Load(StubMachineType::UINT8, pc, GetIntPtrConstant(9)); // 9 : skip 1 byte of bytecode
75 }
76
ReadInst4_0(GateRef pc)77 GateRef InterpreterStub::ReadInst4_0(GateRef pc)
78 {
79 return Int8And(Load(StubMachineType::UINT8, pc, GetIntPtrConstant(1)), GetInt8Constant(0xf));
80 }
81
ReadInst4_1(GateRef pc)82 GateRef InterpreterStub::ReadInst4_1(GateRef pc)
83 {
84 return Int8And(Int8LSR(Load(StubMachineType::UINT8, pc, GetIntPtrConstant(1)),
85 GetInt8Constant(4)), GetInt8Constant(0xf)); // 4 : read 4 byte of bytecode
86 }
87
ReadInst4_2(GateRef pc)88 GateRef InterpreterStub::ReadInst4_2(GateRef pc)
89 {
90 // 2 : skip 1 byte of bytecode
91 return Int8And(Load(StubMachineType::UINT8, pc, GetIntPtrConstant(2)), GetInt8Constant(0xf));
92 }
93
ReadInst4_3(GateRef pc)94 GateRef InterpreterStub::ReadInst4_3(GateRef pc)
95 {
96 // 4: read 4 byte of bytecode
97 return Int8And(
98 Int8LSR(Load(StubMachineType::UINT8, pc, GetIntPtrConstant(2)), GetInt8Constant(4)), GetInt8Constant(0xf));
99 }
100
ReadInstSigned8_0(GateRef pc)101 GateRef InterpreterStub::ReadInstSigned8_0(GateRef pc)
102 {
103 GateRef x = Load(StubMachineType::INT8, pc, GetIntPtrConstant(1));
104 return GetEnvironment()->GetCircuitBuilder().NewArithmeticGate(OpCode(OpCode::SEXT_TO_INT32), x);
105 }
106
ReadInstSigned16_0(GateRef pc)107 GateRef InterpreterStub::ReadInstSigned16_0(GateRef pc)
108 {
109 /* 2 : skip 8 bits of opcode and 8 bits of low bits */
110 GateRef currentInst = Load(StubMachineType::INT8, pc, GetIntPtrConstant(2));
111 GateRef currentInst1 = GetEnvironment()->GetCircuitBuilder().NewArithmeticGate(
112 OpCode(OpCode::SEXT_TO_INT32), currentInst);
113 GateRef currentInst2 = Int32LSL(currentInst1, GetInt32Constant(8)); // 8 : set as high 8 bits
114 return Int32Add(currentInst2, ZExtInt8ToInt32(ReadInst8_0(pc)));
115 }
116
ReadInstSigned32_0(GateRef pc)117 GateRef InterpreterStub::ReadInstSigned32_0(GateRef pc)
118 {
119 /* 4 : skip 8 bits of opcode and 24 bits of low bits */
120 GateRef x = Load(StubMachineType::INT8, pc, GetIntPtrConstant(4));
121 GateRef currentInst = GetEnvironment()->GetCircuitBuilder().NewArithmeticGate(OpCode(OpCode::SEXT_TO_INT32), x);
122 GateRef currentInst1 = Int32LSL(currentInst, GetInt32Constant(8));
123 GateRef currentInst2 = Int32Add(currentInst1, ZExtInt8ToInt32(ReadInst8_2(pc)));
124 GateRef currentInst3 = Int32LSL(currentInst2, GetInt32Constant(8));
125 GateRef currentInst4 = Int32Add(currentInst3, ZExtInt8ToInt32(ReadInst8_1(pc)));
126 GateRef currentInst5 = Int32LSL(currentInst4, GetInt32Constant(8));
127 return Int32Add(currentInst5, ZExtInt8ToInt32(ReadInst8_0(pc)));
128 }
129
ReadInst16_0(GateRef pc)130 GateRef InterpreterStub::ReadInst16_0(GateRef pc)
131 {
132 /* 2 : skip 8 bits of opcode and 8 bits of low bits */
133 GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_1(pc));
134 GateRef currentInst2 = Int16LSL(currentInst1, GetInt16Constant(8)); // 8 : set as high 8 bits
135 return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_0(pc)));
136 }
137
ReadInst16_1(GateRef pc)138 GateRef InterpreterStub::ReadInst16_1(GateRef pc)
139 {
140 /* 3 : skip 8 bits of opcode, 8 bits of prefix and 8 bits of low bits */
141 GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_2(pc));
142 GateRef currentInst2 = Int16LSL(currentInst1, GetInt16Constant(8)); // 8 : set as high 8 bits
143 /* 2: skip 8 bits of opcode and 8 bits of prefix */
144 return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_1(pc)));
145 }
146
ReadInst16_2(GateRef pc)147 GateRef InterpreterStub::ReadInst16_2(GateRef pc)
148 {
149 /* 4 : skip 8 bits of opcode, first parameter of 16 bits and 8 bits of low bits */
150 GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_3(pc));
151 GateRef currentInst2 = Int16LSL(currentInst1, GetInt16Constant(8)); // 8 : set as high 8 bits
152 /* 3: skip 8 bits of opcode and first parameter of 16 bits */
153 return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_2(pc)));
154 }
155
ReadInst16_3(GateRef pc)156 GateRef InterpreterStub::ReadInst16_3(GateRef pc)
157 {
158 /* 5 : skip 8 bits of opcode, 8 bits of prefix, first parameter of 16 bits and 8 bits of low bits */
159 GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_4(pc));
160 GateRef currentInst2 = Int16LSL(currentInst1, GetInt16Constant(8)); // 8 : set as high 8 bits
161 /* 4: skip 8 bits of opcode, 8 bits of prefix and first parameter of 16 bits */
162 return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_3(pc)));
163 }
164
ReadInst16_5(GateRef pc)165 GateRef InterpreterStub::ReadInst16_5(GateRef pc)
166 {
167 /* 7 : skip 8 bits of opcode, 8 bits of prefix, first 2 parameters of 16 bits and 8 bits of low bits */
168 GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_6(pc));
169 GateRef currentInst2 = Int16LSL(currentInst1, GetInt16Constant(8)); // 8 : set as high 8 bits
170 /* 6: skip 8 bits of opcode, 8 bits of prefix and first 2 parameters of 16 bits */
171 return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_5(pc)));
172 }
173
GetFrame(GateRef CurrentSp)174 GateRef InterpreterStub::GetFrame(GateRef CurrentSp)
175 {
176 return IntPtrSub(CurrentSp, GetIntPtrConstant(InterpretedFrame::GetSize(GetEnvironment()->IsArch32Bit())));
177 }
178
GetPcFromFrame(GateRef frame)179 GateRef InterpreterStub::GetPcFromFrame(GateRef frame)
180 {
181 return Load(StubMachineType::NATIVE_POINTER, frame, GetIntPtrConstant(0));
182 }
183
GetFunctionFromFrame(GateRef frame)184 GateRef InterpreterStub::GetFunctionFromFrame(GateRef frame)
185 {
186 return Load(StubMachineType::TAGGED_POINTER, frame,
187 GetIntPtrConstant(InterpretedFrame::GetFunctionOffset(GetEnvironment()->IsArch32Bit())));
188 }
189
GetAccFromFrame(GateRef frame)190 GateRef InterpreterStub::GetAccFromFrame(GateRef frame)
191 {
192 return Load(StubMachineType::TAGGED, frame,
193 GetIntPtrConstant(InterpretedFrame::GetAccOffset(GetEnvironment()->IsArch32Bit())));
194 }
195
GetEnvFromFrame(GateRef frame)196 GateRef InterpreterStub::GetEnvFromFrame(GateRef frame)
197 {
198 return Load(StubMachineType::TAGGED_POINTER, frame,
199 GetIntPtrConstant(InterpretedFrame::GetEnvOffset(GetEnvironment()->IsArch32Bit())));
200 }
201
GetProfileTypeInfoFromFunction(GateRef function)202 GateRef InterpreterStub::GetProfileTypeInfoFromFunction(GateRef function)
203 {
204 return Load(StubMachineType::TAGGED_POINTER, function, GetIntPtrConstant(JSFunction::PROFILE_TYPE_INFO_OFFSET));
205 }
206
GetConstpoolFromFunction(GateRef function)207 GateRef InterpreterStub::GetConstpoolFromFunction(GateRef function)
208 {
209 return Load(StubMachineType::TAGGED_POINTER, function, GetIntPtrConstant(JSFunction::CONSTANT_POOL_OFFSET));
210 }
211
SetEnvToFrame(GateRef glue,GateRef frame,GateRef value)212 void InterpreterStub::SetEnvToFrame(GateRef glue, GateRef frame, GateRef value)
213 {
214 Store(StubMachineType::UINT64, glue, frame,
215 GetIntPtrConstant(InterpretedFrame::GetEnvOffset(GetEnvironment()->IsArch32Bit())), value);
216 }
217
SetPcToFrame(GateRef glue,GateRef frame,GateRef value)218 void InterpreterStub::SetPcToFrame(GateRef glue, GateRef frame, GateRef value)
219 {
220 Store(StubMachineType::UINT64, glue, frame, GetIntPtrConstant(0), value);
221 }
222
SetAccToFrame(GateRef glue,GateRef frame,GateRef value)223 void InterpreterStub::SetAccToFrame(GateRef glue, GateRef frame, GateRef value)
224 {
225 Store(StubMachineType::UINT64, glue, frame,
226 GetIntPtrConstant(InterpretedFrame::GetAccOffset(GetEnvironment()->IsArch32Bit())), value);
227 }
228
SetFunctionToFrame(GateRef glue,GateRef frame,GateRef value)229 void InterpreterStub::SetFunctionToFrame(GateRef glue, GateRef frame, GateRef value)
230 {
231 Store(StubMachineType::UINT64, glue, frame,
232 GetIntPtrConstant(InterpretedFrame::GetFunctionOffset(GetEnvironment()->IsArch32Bit())), value);
233 }
234
GetCurrentSpFrame(GateRef glue)235 GateRef InterpreterStub::GetCurrentSpFrame(GateRef glue)
236 {
237 GateRef spOffset = GetIntPtrConstant(
238 GetEnvironment()->GetGlueOffset(JSThread::GlueID::CURRENT_FRAME));
239 return Load(StubMachineType::NATIVE_POINTER, glue, spOffset);
240 }
241
SetCurrentSpFrame(GateRef glue,GateRef value)242 void InterpreterStub::SetCurrentSpFrame(GateRef glue, GateRef value)
243 {
244 GateRef spOffset = GetIntPtrConstant(
245 GetEnvironment()->GetGlueOffset(JSThread::GlueID::CURRENT_FRAME));
246 Store(StubMachineType::NATIVE_POINTER, glue, glue, spOffset, value);
247 }
248
ReadInst32_0(GateRef pc)249 GateRef InterpreterStub::ReadInst32_0(GateRef pc)
250 {
251 GateRef currentInst = ZExtInt8ToInt32(ReadInst8_3(pc));
252 GateRef currentInst1 = Int32LSL(currentInst, GetInt32Constant(8));
253 GateRef currentInst2 = Int32Add(currentInst1, ZExtInt8ToInt32(ReadInst8_2(pc)));
254 GateRef currentInst3 = Int32LSL(currentInst2, GetInt32Constant(8));
255 GateRef currentInst4 = Int32Add(currentInst3, ZExtInt8ToInt32(ReadInst8_1(pc)));
256 GateRef currentInst5 = Int32LSL(currentInst4, GetInt32Constant(8));
257 return Int32Add(currentInst5, ZExtInt8ToInt32(ReadInst8_0(pc)));
258 }
259
ReadInst32_1(GateRef pc)260 GateRef InterpreterStub::ReadInst32_1(GateRef pc)
261 {
262 GateRef currentInst = ZExtInt8ToInt32(ReadInst8_4(pc));
263 GateRef currentInst1 = Int32LSL(currentInst, GetInt32Constant(8));
264 GateRef currentInst2 = Int32Add(currentInst1, ZExtInt8ToInt32(ReadInst8_3(pc)));
265 GateRef currentInst3 = Int32LSL(currentInst2, GetInt32Constant(8));
266 GateRef currentInst4 = Int32Add(currentInst3, ZExtInt8ToInt32(ReadInst8_2(pc)));
267 GateRef currentInst5 = Int32LSL(currentInst4, GetInt32Constant(8));
268 return Int32Add(currentInst5, ZExtInt8ToInt32(ReadInst8_1(pc)));
269 }
270
ReadInst32_2(GateRef pc)271 GateRef InterpreterStub::ReadInst32_2(GateRef pc)
272 {
273 GateRef currentInst = ZExtInt8ToInt32(ReadInst8_5(pc));
274 GateRef currentInst1 = Int32LSL(currentInst, GetInt32Constant(8));
275 GateRef currentInst2 = Int32Add(currentInst1, ZExtInt8ToInt32(ReadInst8_4(pc)));
276 GateRef currentInst3 = Int32LSL(currentInst2, GetInt32Constant(8));
277 GateRef currentInst4 = Int32Add(currentInst3, ZExtInt8ToInt32(ReadInst8_3(pc)));
278 GateRef currentInst5 = Int32LSL(currentInst4, GetInt32Constant(8));
279 return Int32Add(currentInst5, ZExtInt8ToInt32(ReadInst8_2(pc)));
280 }
281
ReadInst64_0(GateRef pc)282 GateRef InterpreterStub::ReadInst64_0(GateRef pc)
283 {
284 GateRef currentInst = ZExtInt8ToInt64(ReadInst8_7(pc));
285 GateRef currentInst1 = Int64LSL(currentInst, GetInt64Constant(8));
286 GateRef currentInst2 = Int64Add(currentInst1, ZExtInt8ToInt64(ReadInst8_6(pc)));
287 GateRef currentInst3 = Int64LSL(currentInst2, GetInt64Constant(8));
288 GateRef currentInst4 = Int64Add(currentInst3, ZExtInt8ToInt64(ReadInst8_5(pc)));
289 GateRef currentInst5 = Int64LSL(currentInst4, GetInt64Constant(8));
290 GateRef currentInst6 = Int64Add(currentInst5, ZExtInt8ToInt64(ReadInst8_4(pc)));
291 GateRef currentInst7 = Int64LSL(currentInst6, GetInt64Constant(8));
292 GateRef currentInst8 = Int64Add(currentInst7, ZExtInt8ToInt64(ReadInst8_3(pc)));
293 GateRef currentInst9 = Int64LSL(currentInst8, GetInt64Constant(8));
294 GateRef currentInst10 = Int64Add(currentInst9, ZExtInt8ToInt64(ReadInst8_2(pc)));
295 GateRef currentInst11 = Int64LSL(currentInst10, GetInt64Constant(8));
296 GateRef currentInst12 = Int64Add(currentInst11, ZExtInt8ToInt64(ReadInst8_1(pc)));
297 GateRef currentInst13 = Int64LSL(currentInst12, GetInt64Constant(8));
298 return Int64Add(currentInst13, ZExtInt8ToInt64(ReadInst8_0(pc)));
299 }
300
Dispatch(GateRef glue,GateRef pc,GateRef sp,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter,GateRef format)301 void InterpreterStub::Dispatch(GateRef glue, GateRef pc, GateRef sp, GateRef constpool, GateRef profileTypeInfo,
302 GateRef acc, GateRef hotnessCounter, GateRef format)
303 {
304 GateRef newPc = IntPtrAdd(pc, format);
305 GateRef opcode = Load(StubMachineType::UINT8, newPc);
306 GateRef opcodeOffset = IntPtrMul(
307 ChangeInt32ToIntPtr(ZExtInt8ToInt32(opcode)), GetIntPtrSize());
308 StubDescriptor *bytecodeHandler = GET_STUBDESCRIPTOR(BytecodeHandler);
309 auto depend = GetEnvironment()->GetCurrentLabel()->GetDepend();
310 GateRef result = GetEnvironment()->GetCircuitBuilder().NewBytecodeCallGate(bytecodeHandler, glue, opcodeOffset,
311 depend, {glue, newPc, sp, constpool, profileTypeInfo, acc, hotnessCounter});
312 GetEnvironment()->GetCurrentLabel()->SetDepend(result);
313 Return();
314 }
315
DispatchLast(GateRef glue,GateRef pc,GateRef sp,GateRef constpool,GateRef profileTypeInfo,GateRef acc,GateRef hotnessCounter)316 void InterpreterStub::DispatchLast(GateRef glue, GateRef pc, GateRef sp, GateRef constpool,
317 GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter)
318 {
319 GateRef opcodeOffset = IntPtrMul(
320 GetIntPtrConstant(EcmaOpcode::LAST_OPCODE), GetIntPtrSize());
321 StubDescriptor *bytecodeHandler = GET_STUBDESCRIPTOR(BytecodeHandler);
322 auto depend = GetEnvironment()->GetCurrentLabel()->GetDepend();
323 GateRef result = GetEnvironment()->GetCircuitBuilder().NewBytecodeCallGate(bytecodeHandler, glue, opcodeOffset,
324 depend, {glue, pc, sp, constpool, profileTypeInfo, acc, hotnessCounter});
325 GetEnvironment()->GetCurrentLabel()->SetDepend(result);
326 Return();
327 }
328
GetObjectFromConstPool(GateRef constpool,GateRef index)329 GateRef InterpreterStub::GetObjectFromConstPool(GateRef constpool, GateRef index)
330 {
331 return GetValueFromTaggedArray(StubMachineType::TAGGED, constpool, index);
332 }
333
FunctionIsResolved(GateRef object)334 GateRef InterpreterStub::FunctionIsResolved(GateRef object)
335 {
336 GateRef bitfield = TaggedGetInt(GetFunctionBitFieldFromJSFunction(object));
337 // decode
338 return Int32NotEqual(
339 Int32And(
340 UInt32LSR(bitfield, GetInt32Constant(JSFunction::ResolvedBits::START_BIT)),
341 GetInt32Constant((1LU << JSFunction::ResolvedBits::SIZE) - 1)),
342 GetInt32Constant(0));
343 }
344 } // namespace panda::ecmascript::kungfu
345 #endif // ECMASCRIPT_COMPILER_INTERPRETER_STUB_INL_H
346