1 /**
2 * Copyright (c) 2021-2024 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 #include <gtest/gtest.h>
17
18 #include <string>
19 #include <vector>
20
21 #include "libpandafile/bytecode_emitter.h"
22 #include "libpandafile/bytecode_instruction.h"
23 #include "libpandabase/utils/utils.h"
24 #include "libpandafile/file_items.h"
25 #include "libpandafile/value.h"
26 #include "runtime/bridge/bridge.h"
27 #include "runtime/entrypoints/entrypoints.h"
28 #include "runtime/include/method.h"
29 #include "runtime/include/runtime.h"
30 #include "runtime/include/thread.h"
31 #include "runtime/interpreter/frame.h"
32 #include "runtime/tests/test_utils.h"
33
34 using TypeId = ark::panda_file::Type::TypeId;
35 using Opcode = ark::BytecodeInstruction::Opcode;
36
37 // NOLINTBEGIN(readability-magic-numbers,modernize-avoid-c-arrays)
38
39 namespace ark::test {
40
41 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects)
42 static std::string g_gCallResult;
43
44 class InterpreterToCompiledCodeBridgeTest : public testing::Test {
45 public:
InterpreterToCompiledCodeBridgeTest()46 InterpreterToCompiledCodeBridgeTest()
47 {
48 RuntimeOptions options;
49 options.SetShouldLoadBootPandaFiles(false);
50 options.SetShouldInitializeIntrinsics(false);
51 options.SetGcType("epsilon");
52 Runtime::Create(options);
53
54 thread_ = MTManagedThread::GetCurrent();
55 thread_->ManagedCodeBegin();
56 g_gCallResult = "";
57 }
58
~InterpreterToCompiledCodeBridgeTest()59 ~InterpreterToCompiledCodeBridgeTest() override
60 {
61 thread_->ManagedCodeEnd();
62 Runtime::Destroy();
63 }
64
65 NO_COPY_SEMANTIC(InterpreterToCompiledCodeBridgeTest);
66 NO_MOVE_SEMANTIC(InterpreterToCompiledCodeBridgeTest);
67
MakeShorty(const std::initializer_list<TypeId> & shorty)68 uint16_t *MakeShorty(const std::initializer_list<TypeId> &shorty)
69 {
70 constexpr size_t ELEM_SIZE = 4;
71 constexpr size_t ELEM_COUNT = std::numeric_limits<uint16_t>::digits / ELEM_SIZE;
72
73 uint16_t val = 0;
74 uint32_t count = 0;
75 for (const TypeId &typeId : shorty) {
76 if (count == ELEM_COUNT) {
77 shorty_.push_back(val);
78 val = 0;
79 count = 0;
80 }
81 // NOLINTNEXTLINE(hicpp-signed-bitwise)
82 val |= static_cast<uint8_t>(typeId) << ELEM_SIZE * count;
83 ++count;
84 }
85 if (count == ELEM_COUNT) {
86 shorty_.push_back(val);
87 val = 0;
88 }
89 shorty_.push_back(val);
90 return shorty_.data();
91 }
92
93 protected:
94 // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes)
95 MTManagedThread *thread_ {};
96
97 private:
98 std::vector<uint16_t> shorty_;
99 };
100
101 // Test interpreter -> compiled code bridge
102
103 template <typename Arg>
ArgsToString(const Arg & arg)104 std::string ArgsToString(const Arg &arg)
105 {
106 std::ostringstream out;
107 if constexpr (std::is_integral_v<Arg>) {
108 out << std::hex << "0x" << arg;
109 } else {
110 out << arg;
111 }
112 return out.str();
113 }
114
115 template <typename Arg, typename... Args>
ArgsToString(const Arg & a0,Args...args)116 std::string ArgsToString(const Arg &a0, Args... args)
117 {
118 std::ostringstream out;
119 out << ArgsToString(a0) << ", " << ArgsToString(args...);
120 return out.str();
121 }
122
123 template <typename... Args>
PrintFunc(const char * ret,const char * name,Args...args)124 std::string PrintFunc(const char *ret, const char *name, Args... args)
125 {
126 std::ostringstream out;
127 out << ret << " " << name << "(" << ArgsToString(args...) << ")";
128 return out.str();
129 }
130
VoidNoArg(Method * method)131 static void VoidNoArg(Method *method)
132 {
133 g_gCallResult = PrintFunc("void", __FUNCTION__, method);
134 }
135
136 template <bool IS_DYNAMIC = false>
CreateFrame(size_t nregs,Method * method,Frame * prev)137 static Frame *CreateFrame(size_t nregs, Method *method, Frame *prev)
138 {
139 return ark::CreateFrameWithSize(Frame::GetActualSize<IS_DYNAMIC>(nregs), nregs, method, prev);
140 }
141
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeVoidNoArg)142 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeVoidNoArg)
143 {
144 uint16_t *shorty = MakeShorty({TypeId::VOID});
145 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
146 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(VoidNoArg));
147 Frame *frame = CreateFrame(0, nullptr, nullptr);
148
149 uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
150 g_gCallResult = "";
151 InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
152 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidNoArg", &callee));
153
154 uint8_t insn2[] = {static_cast<uint8_t>(Opcode::CALL_ACC_SHORT_V4_IMM4_ID16), 0x00, 0, 0, 0, 0};
155 g_gCallResult = "";
156 InterpreterToCompiledCodeBridge(insn2, frame, &callee, thread_);
157 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidNoArg", &callee));
158
159 g_gCallResult = "";
160 InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
161 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidNoArg", &callee));
162
163 FreeFrame(frame);
164 }
165
InstanceVoidNoArg(Method * method,ObjectHeader * thisHeader)166 static void InstanceVoidNoArg(Method *method, ObjectHeader *thisHeader)
167 {
168 g_gCallResult = PrintFunc("void", __FUNCTION__, method, thisHeader);
169 }
170
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeInstanceVoidNoArg)171 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeInstanceVoidNoArg)
172 {
173 uint16_t *shorty = MakeShorty({TypeId::VOID});
174 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), 0, 1, shorty);
175 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(InstanceVoidNoArg));
176 Frame *frame = CreateFrame(1, nullptr, nullptr);
177 auto frameHandler = StaticFrameHandler(frame);
178
179 ObjectHeader *obj1 = ark::mem::AllocateNullifiedPayloadString(5U);
180 frameHandler.GetAccAsVReg().SetReference(obj1);
181 ObjectHeader *obj2 = ark::mem::AllocateNullifiedPayloadString(4U);
182 frameHandler.GetVReg(0).SetReference(obj2);
183
184 uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
185 g_gCallResult = "";
186 InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
187 ASSERT_EQ(g_gCallResult, PrintFunc("void", "InstanceVoidNoArg", &callee, obj2));
188
189 uint8_t insn2[] = {static_cast<uint8_t>(Opcode::CALL_ACC_SHORT_V4_IMM4_ID16), 0x00, 0, 0, 0, 0};
190 g_gCallResult = "";
191 InterpreterToCompiledCodeBridge(insn2, frame, &callee, thread_);
192 ASSERT_EQ(g_gCallResult, PrintFunc("void", "InstanceVoidNoArg", &callee, obj1));
193
194 g_gCallResult = "";
195 int64_t args[] = {static_cast<int64_t>(ToUintPtr(obj2))};
196 InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
197 ASSERT_EQ(g_gCallResult, PrintFunc("void", "InstanceVoidNoArg", &callee, obj2));
198
199 FreeFrame(frame);
200 }
201
ByteNoArg(Method * method)202 static uint8_t ByteNoArg(Method *method)
203 {
204 g_gCallResult = PrintFunc("uint8_t", __FUNCTION__, method);
205 return static_cast<uint8_t>(5U);
206 }
207
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeByteNoArg)208 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeByteNoArg)
209 {
210 uint16_t *shorty = MakeShorty({TypeId::U8});
211 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
212 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(ByteNoArg));
213 Frame *frame = CreateFrame(0, nullptr, nullptr);
214 uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
215
216 g_gCallResult = "";
217 InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
218 EXPECT_EQ(g_gCallResult, PrintFunc("uint8_t", "ByteNoArg", &callee));
219 EXPECT_EQ(frame->GetAcc().Get(), static_cast<uint8_t>(5U));
220 EXPECT_EQ(frame->GetAcc().GetTag(), 0);
221
222 uint8_t insnAcc[] = {static_cast<uint8_t>(Opcode::CALL_ACC_SHORT_V4_IMM4_ID16), 0x00, 0, 0, 0, 0};
223 g_gCallResult = "";
224 InterpreterToCompiledCodeBridge(insnAcc, frame, &callee, thread_);
225 EXPECT_EQ(g_gCallResult, PrintFunc("uint8_t", "ByteNoArg", &callee));
226 EXPECT_EQ(frame->GetAcc().Get(), static_cast<uint8_t>(5U));
227 EXPECT_EQ(frame->GetAcc().GetTag(), 0);
228
229 g_gCallResult = "";
230 uint64_t res = InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
231 EXPECT_EQ(static_cast<int32_t>(res), static_cast<uint8_t>(5U));
232 EXPECT_EQ(g_gCallResult, PrintFunc("uint8_t", "ByteNoArg", &callee));
233
234 FreeFrame(frame);
235 }
236
SignedByteNoArg(Method * method)237 static int8_t SignedByteNoArg(Method *method)
238 {
239 g_gCallResult = PrintFunc("int8_t", __FUNCTION__, method);
240 return static_cast<int8_t>(-5_I);
241 }
242
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeSignedByteNoArg)243 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeSignedByteNoArg)
244 {
245 uint16_t *shorty = MakeShorty({TypeId::I8});
246 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
247 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(SignedByteNoArg));
248 Frame *frame = CreateFrame(0, nullptr, nullptr);
249 uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
250
251 g_gCallResult = "";
252 InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
253 EXPECT_EQ(g_gCallResult, PrintFunc("int8_t", "SignedByteNoArg", &callee));
254 EXPECT_EQ(frame->GetAcc().Get(), static_cast<int8_t>(-5_I));
255 EXPECT_EQ(frame->GetAcc().GetTag(), 0);
256
257 uint8_t insnAcc[] = {static_cast<uint8_t>(Opcode::CALL_ACC_SHORT_V4_IMM4_ID16), 0x00, 0, 0, 0, 0};
258 g_gCallResult = "";
259 InterpreterToCompiledCodeBridge(insnAcc, frame, &callee, thread_);
260 EXPECT_EQ(g_gCallResult, PrintFunc("int8_t", "SignedByteNoArg", &callee));
261 EXPECT_EQ(frame->GetAcc().Get(), static_cast<int8_t>(-5_I));
262 EXPECT_EQ(frame->GetAcc().GetTag(), 0);
263
264 g_gCallResult = "";
265 uint64_t res = InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
266 EXPECT_EQ(static_cast<int32_t>(res), static_cast<int8_t>(-5_I));
267 EXPECT_EQ(g_gCallResult, PrintFunc("int8_t", "SignedByteNoArg", &callee));
268
269 FreeFrame(frame);
270 }
271
BoolNoArg(Method * method)272 static bool BoolNoArg(Method *method)
273 {
274 g_gCallResult = PrintFunc("bool", __FUNCTION__, method);
275 return true;
276 }
277
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeBoolNoArg)278 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeBoolNoArg)
279 {
280 uint16_t *shorty = MakeShorty({TypeId::U1});
281 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
282 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(BoolNoArg));
283 Frame *frame = CreateFrame(0, nullptr, nullptr);
284 uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
285
286 g_gCallResult = "";
287 InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
288 EXPECT_EQ(g_gCallResult, PrintFunc("bool", "BoolNoArg", &callee));
289 EXPECT_EQ(frame->GetAcc().Get(), true);
290 EXPECT_EQ(frame->GetAcc().GetTag(), 0);
291
292 g_gCallResult = "";
293 uint64_t res = InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
294 EXPECT_EQ(static_cast<int32_t>(res), true);
295 EXPECT_EQ(g_gCallResult, PrintFunc("bool", "BoolNoArg", &callee));
296
297 FreeFrame(frame);
298 }
299
ShortNoArg(Method * method)300 static uint16_t ShortNoArg(Method *method)
301 {
302 g_gCallResult = PrintFunc("uint16_t", __FUNCTION__, method);
303 return static_cast<uint16_t>(5U);
304 }
305
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeShortNoArg)306 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeShortNoArg)
307 {
308 uint16_t *shorty = MakeShorty({TypeId::U16});
309 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
310 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(ShortNoArg));
311 Frame *frame = CreateFrame(0, nullptr, nullptr);
312 uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
313
314 g_gCallResult = "";
315 InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
316 EXPECT_EQ(g_gCallResult, PrintFunc("uint16_t", "ShortNoArg", &callee));
317 EXPECT_EQ(frame->GetAcc().Get(), static_cast<uint16_t>(5U));
318 EXPECT_EQ(frame->GetAcc().GetTag(), 0);
319
320 g_gCallResult = "";
321 uint64_t res = InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
322 EXPECT_EQ(static_cast<int32_t>(res), static_cast<uint16_t>(5U));
323 EXPECT_EQ(g_gCallResult, PrintFunc("uint16_t", "ShortNoArg", &callee));
324
325 FreeFrame(frame);
326 }
327
SignedShortNoArg(Method * method)328 static int16_t SignedShortNoArg(Method *method)
329 {
330 g_gCallResult = PrintFunc("int16_t", __FUNCTION__, method);
331 return static_cast<int16_t>(-5_I);
332 }
333
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeSignedShortNoArg)334 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeSignedShortNoArg)
335 {
336 uint16_t *shorty = MakeShorty({TypeId::I16});
337 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
338 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(SignedShortNoArg));
339 Frame *frame = CreateFrame(0, nullptr, nullptr);
340 uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
341
342 g_gCallResult = "";
343 InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
344 EXPECT_EQ(g_gCallResult, PrintFunc("int16_t", "SignedShortNoArg", &callee));
345 EXPECT_EQ(frame->GetAcc().Get(), static_cast<int16_t>(-5_I));
346 EXPECT_EQ(frame->GetAcc().GetTag(), 0);
347
348 g_gCallResult = "";
349 uint64_t res = InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
350 EXPECT_EQ(static_cast<int32_t>(res), static_cast<int16_t>(-5_I));
351 EXPECT_EQ(g_gCallResult, PrintFunc("int16_t", "SignedShortNoArg", &callee));
352
353 FreeFrame(frame);
354 }
355
IntNoArg(Method * method)356 static int32_t IntNoArg(Method *method)
357 {
358 g_gCallResult = PrintFunc("int32_t", __FUNCTION__, method);
359 return 5_I;
360 }
361
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeIntNoArg)362 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeIntNoArg)
363 {
364 uint16_t *shorty = MakeShorty({TypeId::I32});
365 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
366 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(IntNoArg));
367 Frame *frame = CreateFrame(0, nullptr, nullptr);
368 uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
369
370 g_gCallResult = "";
371 InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
372 ASSERT_EQ(g_gCallResult, PrintFunc("int32_t", "IntNoArg", &callee));
373 ASSERT_EQ(frame->GetAcc().Get(), 5_I);
374 EXPECT_EQ(frame->GetAcc().GetTag(), 0);
375
376 g_gCallResult = "";
377 uint64_t res = InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
378 ASSERT_EQ(res, 5_I);
379 ASSERT_EQ(g_gCallResult, PrintFunc("int32_t", "IntNoArg", &callee));
380
381 FreeFrame(frame);
382 }
383
LongNoArg(Method * method)384 static int64_t LongNoArg(Method *method)
385 {
386 g_gCallResult = PrintFunc("int64_t", __FUNCTION__, method);
387 return 8L;
388 }
389
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeLongNoArg)390 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeLongNoArg)
391 {
392 uint16_t *shorty = MakeShorty({TypeId::I64});
393 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
394 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(LongNoArg));
395 Frame *frame = CreateFrame(0, nullptr, nullptr);
396 uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
397
398 g_gCallResult = "";
399 InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
400 ASSERT_EQ(g_gCallResult, PrintFunc("int64_t", "LongNoArg", &callee));
401 ASSERT_EQ(frame->GetAcc().Get(), 8L);
402 EXPECT_EQ(frame->GetAcc().GetTag(), 0);
403
404 g_gCallResult = "";
405 uint64_t res = InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
406 ASSERT_EQ(res, 8L);
407 ASSERT_EQ(g_gCallResult, PrintFunc("int64_t", "LongNoArg", &callee));
408
409 FreeFrame(frame);
410 }
411
DoubleNoArg(Method * method)412 static double DoubleNoArg(Method *method)
413 {
414 g_gCallResult = PrintFunc("double", __FUNCTION__, method);
415 return 3.0F;
416 }
417
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeDoubleNoArg)418 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeDoubleNoArg)
419 {
420 uint16_t *shorty = MakeShorty({TypeId::F64});
421 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
422 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(DoubleNoArg));
423 Frame *frame = CreateFrame(0, nullptr, nullptr);
424 uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
425
426 g_gCallResult = "";
427 InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
428 ASSERT_EQ(g_gCallResult, PrintFunc("double", "DoubleNoArg", &callee));
429 ASSERT_EQ(frame->GetAcc().GetDouble(), 3.0_D);
430 EXPECT_EQ(frame->GetAcc().GetTag(), 0);
431
432 g_gCallResult = "";
433 uint64_t res = InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
434 ASSERT_EQ(bit_cast<double>(res), 3.0_D);
435 ASSERT_EQ(g_gCallResult, PrintFunc("double", "DoubleNoArg", &callee));
436
437 FreeFrame(frame);
438 }
439
ObjNoArg(Method * method)440 static ObjectHeader *ObjNoArg(Method *method)
441 {
442 g_gCallResult = PrintFunc("Object", __FUNCTION__, method);
443 return nullptr;
444 }
445
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeObjNoArg)446 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeObjNoArg)
447 {
448 uint16_t *shorty = MakeShorty({TypeId::REFERENCE});
449 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
450 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(ObjNoArg));
451 Frame *frame = CreateFrame(0, nullptr, nullptr);
452 uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
453
454 g_gCallResult = "";
455 InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
456 ASSERT_EQ(g_gCallResult, PrintFunc("Object", "ObjNoArg", &callee));
457 ASSERT_EQ(frame->GetAcc().GetReference(), nullptr);
458 EXPECT_EQ(frame->GetAcc().GetTag(), 1);
459
460 g_gCallResult = "";
461 uint64_t res = InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
462 ASSERT_EQ(reinterpret_cast<ObjectHeader *>(res), nullptr);
463 ASSERT_EQ(g_gCallResult, PrintFunc("Object", "ObjNoArg", &callee));
464
465 FreeFrame(frame);
466 }
467
VoidInt(Method * method,int32_t a0)468 static void VoidInt(Method *method, int32_t a0)
469 {
470 g_gCallResult = PrintFunc("void", __FUNCTION__, method, a0);
471 }
472
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeInt)473 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeInt)
474 {
475 uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32});
476 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
477 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(VoidInt));
478 Frame *frame = CreateFrame(2U, nullptr, nullptr);
479 frame->GetVReg(1).Set(5U);
480
481 uint8_t callShortInsn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x01, 0, 0, 0, 0};
482 g_gCallResult = "";
483 InterpreterToCompiledCodeBridge(callShortInsn, frame, &callee, thread_);
484 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidInt", &callee, 5_I));
485
486 uint8_t callRangeInsn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x01, 0, 0, 0, 0};
487 g_gCallResult = "";
488 InterpreterToCompiledCodeBridge(callRangeInsn, frame, &callee, thread_);
489 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidInt", &callee, 5_I));
490
491 g_gCallResult = "";
492 int64_t arg = 5L;
493 InvokeCompiledCodeWithArgArray(&arg, frame, &callee, thread_);
494 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidInt", &callee, 5_I));
495
496 frame->GetVReg(1).Set(0);
497 frame->GetAcc().SetValue(5L);
498 uint8_t callAccInsn[] = {static_cast<uint8_t>(Opcode::CALL_ACC_SHORT_V4_IMM4_ID16), 0x00, 0, 0};
499 g_gCallResult = "";
500 InterpreterToCompiledCodeBridge(callAccInsn, frame, &callee, thread_);
501 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidInt", &callee, 5_I));
502
503 FreeFrame(frame);
504 }
505
InstanceVoidInt(Method * method,ObjectHeader * thisHeader,int32_t a0)506 static void InstanceVoidInt(Method *method, ObjectHeader *thisHeader, int32_t a0)
507 {
508 g_gCallResult = PrintFunc("void", __FUNCTION__, method, thisHeader, a0);
509 }
510
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeInstanceInt)511 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeInstanceInt)
512 {
513 uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32});
514 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), 0, 0, shorty);
515 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(InstanceVoidInt));
516 Frame *frame = CreateFrame(2U, nullptr, nullptr);
517 auto frameHandler = StaticFrameHandler(frame);
518 ObjectHeader *obj = ark::mem::AllocateNullifiedPayloadString(1);
519 frameHandler.GetVReg(0).SetReference(obj);
520 frameHandler.GetVReg(1).Set(5U);
521
522 uint8_t callShortInsn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x10, 0, 0, 0, 0};
523 g_gCallResult = "";
524 InterpreterToCompiledCodeBridge(callShortInsn, frame, &callee, thread_);
525 ASSERT_EQ(g_gCallResult, PrintFunc("void", "InstanceVoidInt", &callee, obj, 5L));
526
527 uint8_t callRangeInsn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
528 g_gCallResult = "";
529 InterpreterToCompiledCodeBridge(callRangeInsn, frame, &callee, thread_);
530 ASSERT_EQ(g_gCallResult, PrintFunc("void", "InstanceVoidInt", &callee, obj, 5L));
531
532 g_gCallResult = "";
533 int64_t args[] = {static_cast<int64_t>(ToUintPtr(obj)), 5L};
534 InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
535 ASSERT_EQ(g_gCallResult, PrintFunc("void", "InstanceVoidInt", &callee, obj, 5L));
536
537 frameHandler.GetVReg(1).Set(0);
538 frameHandler.GetAcc().SetValue(5L);
539 uint8_t callAccInsn[] = {static_cast<uint8_t>(Opcode::CALL_ACC_SHORT_V4_IMM4_ID16), 0x10, 0, 0};
540 g_gCallResult = "";
541 InterpreterToCompiledCodeBridge(callAccInsn, frame, &callee, thread_);
542 ASSERT_EQ(g_gCallResult, PrintFunc("void", "InstanceVoidInt", &callee, obj, 5L));
543
544 FreeFrame(frame);
545 }
546
VoidVReg(Method * method,int64_t value)547 static void VoidVReg(Method *method, int64_t value)
548 {
549 g_gCallResult = PrintFunc("void", __FUNCTION__, method, value);
550 }
551
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeVReg)552 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeVReg)
553 {
554 uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::TAGGED});
555 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
556 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(VoidVReg));
557 Frame *frame = CreateFrame(2U, nullptr, nullptr);
558 auto frameHandler = StaticFrameHandler(frame);
559 frameHandler.GetVReg(1).Set(5U);
560
561 uint8_t callShortInsn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x01, 0, 0, 0, 0};
562 g_gCallResult = "";
563 InterpreterToCompiledCodeBridge(callShortInsn, frame, &callee, thread_);
564 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidVReg", &callee, 5L));
565
566 uint8_t callRangeInsn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x01, 0, 0, 0, 0};
567 g_gCallResult = "";
568 InterpreterToCompiledCodeBridge(callRangeInsn, frame, &callee, thread_);
569 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidVReg", &callee, 5L));
570
571 g_gCallResult = "";
572 int64_t arg[] = {5L, 8L};
573 InvokeCompiledCodeWithArgArray(arg, frame, &callee, thread_);
574 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidVReg", &callee, 5L));
575
576 frameHandler.GetVReg(1).Set(0);
577 frameHandler.GetAcc().SetValue(5L);
578 uint8_t callAccShort[] = {static_cast<uint8_t>(Opcode::CALL_ACC_SHORT_V4_IMM4_ID16), 0x01, 0, 0, 0, 0};
579 g_gCallResult = "";
580 InterpreterToCompiledCodeBridge(callAccShort, frame, &callee, thread_);
581 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidVReg", &callee, 5L));
582 FreeFrame(frame);
583 }
584
VoidIntVReg(Method * method,int32_t a0,int64_t value)585 static void VoidIntVReg(Method *method, int32_t a0, int64_t value)
586 {
587 g_gCallResult = PrintFunc("void", __FUNCTION__, method, a0, value);
588 }
589
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeIntVReg)590 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeIntVReg)
591 {
592 uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32, TypeId::TAGGED});
593 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
594 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(VoidIntVReg));
595 Frame *frame = CreateFrame(2U, nullptr, nullptr);
596 auto frameHandler = StaticFrameHandler(frame);
597 frameHandler.GetVReg(0).Set(2U);
598 frameHandler.GetVReg(1).Set(5U);
599
600 uint8_t callShortInsn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x10, 0, 0, 0, 0};
601 g_gCallResult = "";
602 InterpreterToCompiledCodeBridge(callShortInsn, frame, &callee, thread_);
603 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidIntVReg", &callee, 2L, 5L));
604
605 uint8_t callRangeInsn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
606 g_gCallResult = "";
607 InterpreterToCompiledCodeBridge(callRangeInsn, frame, &callee, thread_);
608 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidIntVReg", &callee, 2L, 5L));
609
610 g_gCallResult = "";
611 int64_t arg[] = {2L, 5L, 8L};
612 InvokeCompiledCodeWithArgArray(arg, frame, &callee, thread_);
613 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidIntVReg", &callee, 2L, 5L));
614
615 frameHandler.GetAcc().SetValue(5L);
616 frameHandler.GetVReg(1).Set(0);
617 uint8_t callAccShortInsn[] = {static_cast<uint8_t>(Opcode::CALL_ACC_SHORT_V4_IMM4_ID16), 0x10, 0, 0};
618 g_gCallResult = "";
619 InterpreterToCompiledCodeBridge(callAccShortInsn, frame, &callee, thread_);
620 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidIntVReg", &callee, 2L, 5L));
621
622 FreeFrame(frame);
623 }
624
625 // arm max number of register parameters
Void3Int(Method * method,int32_t a0,int32_t a1,int32_t a2)626 static void Void3Int(Method *method, int32_t a0, int32_t a1, int32_t a2)
627 {
628 g_gCallResult = PrintFunc("void", __FUNCTION__, method, a0, a1, a2);
629 }
630
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke3Int)631 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke3Int)
632 {
633 uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I32});
634 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
635 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void3Int));
636 Frame *frame = CreateFrame(3U, nullptr, nullptr);
637 auto frameHandler = StaticFrameHandler(frame);
638 frameHandler.GetAcc().SetValue(0);
639 frameHandler.GetVReg(0U).Set(1U);
640 frameHandler.GetVReg(1U).Set(2U);
641 frameHandler.GetVReg(2U).Set(3U);
642
643 uint8_t callInsn[] = {static_cast<uint8_t>(Opcode::CALL_V4_V4_V4_V4_ID16), 0x10, 0x02, 0, 0, 0, 0};
644 g_gCallResult = "";
645 InterpreterToCompiledCodeBridge(callInsn, frame, &callee, thread_);
646 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void3Int", &callee, 1L, 2L, 3L));
647
648 // callee(acc, v1, v2)
649 uint8_t callAccInsn[] = {static_cast<uint8_t>(Opcode::CALL_ACC_V4_V4_V4_IMM4_ID16), 0x21, 0x00, 0, 0};
650 g_gCallResult = "";
651 InterpreterToCompiledCodeBridge(callAccInsn, frame, &callee, thread_);
652 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void3Int", &callee, 0L, 2L, 3L));
653
654 uint8_t callRangeInsn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
655 g_gCallResult = "";
656 InterpreterToCompiledCodeBridge(callRangeInsn, frame, &callee, thread_);
657 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void3Int", &callee, 1L, 2L, 3L));
658
659 int64_t args[] = {1L, 2L, 3L};
660 g_gCallResult = "";
661 InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
662 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void3Int", &callee, 1L, 2L, 3L));
663
664 FreeFrame(frame);
665 }
666
Void2IntLongInt(Method * method,int32_t a0,int32_t a1,int64_t a2,int32_t a3)667 static void Void2IntLongInt(Method *method, int32_t a0, int32_t a1, int64_t a2, int32_t a3)
668 {
669 g_gCallResult = PrintFunc("void", __FUNCTION__, method, a0, a1, a2, a3);
670 }
671
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke2IntLongInt)672 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke2IntLongInt)
673 {
674 uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I64, TypeId::I32});
675 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
676 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void2IntLongInt));
677 Frame *frame = CreateFrame(4U, nullptr, nullptr);
678 auto frameHandler = StaticFrameHandler(frame);
679 frameHandler.GetVReg(0U).Set(1U);
680 frameHandler.GetVReg(1U).Set(2U);
681 frameHandler.GetVReg(2U).Set(3U);
682 frameHandler.GetVReg(3U).Set(4U);
683
684 uint8_t callInsn[] = {static_cast<uint8_t>(Opcode::CALL_V4_V4_V4_V4_ID16), 0x10, 0x32, 0, 0, 0, 0};
685 g_gCallResult = "";
686 InterpreterToCompiledCodeBridge(callInsn, frame, &callee, thread_);
687 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void2IntLongInt", &callee, 1L, 2L, 3L, 4L));
688
689 uint8_t callRangeInsn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
690 g_gCallResult = "";
691 InterpreterToCompiledCodeBridge(callRangeInsn, frame, &callee, thread_);
692 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void2IntLongInt", &callee, 1L, 2L, 3L, 4L));
693
694 int64_t args[] = {1L, 2L, 3L, 4L};
695 g_gCallResult = "";
696 InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
697 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void2IntLongInt", &callee, 1L, 2L, 3L, 4L));
698
699 frameHandler.GetVReg(2U).Set(0);
700 frameHandler.GetAcc().SetValue(3L);
701 uint8_t callAccInsn[] = {static_cast<uint8_t>(Opcode::CALL_ACC_V4_V4_V4_IMM4_ID16), 0x10, 0x23, 0, 0, 0, 0};
702 g_gCallResult = "";
703 InterpreterToCompiledCodeBridge(callAccInsn, frame, &callee, thread_);
704 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void2IntLongInt", &callee, 1L, 2L, 3L, 4L));
705
706 FreeFrame(frame);
707 }
708
VoidLong(Method * method,int64_t a0)709 static void VoidLong(Method *method, int64_t a0)
710 {
711 g_gCallResult = PrintFunc("void", __FUNCTION__, method, a0);
712 }
713
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeLong)714 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeLong)
715 {
716 uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I64});
717 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
718 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(VoidLong));
719 Frame *frame = CreateFrame(1, nullptr, nullptr);
720 auto frameHandler = StaticFrameHandler(frame);
721 frameHandler.GetVReg(0).Set(9U);
722
723 uint8_t callInsn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
724 g_gCallResult = "";
725 InterpreterToCompiledCodeBridge(callInsn, frame, &callee, thread_);
726 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidLong", &callee, 9L));
727
728 uint8_t callRangeInsn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
729 g_gCallResult = "";
730 InterpreterToCompiledCodeBridge(callRangeInsn, frame, &callee, thread_);
731 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidLong", &callee, 9L));
732
733 int64_t args[] = {9L};
734 g_gCallResult = "";
735 InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
736 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidLong", &callee, 9L));
737
738 FreeFrame(frame);
739 }
740
VoidDouble(Method * method,double a0)741 static void VoidDouble(Method *method, double a0)
742 {
743 g_gCallResult = PrintFunc("void", __FUNCTION__, method, a0);
744 }
745
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeDouble)746 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeDouble)
747 {
748 uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::F64});
749 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
750 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(VoidDouble));
751 Frame *frame = CreateFrame(1, nullptr, nullptr);
752 auto frameHandler = StaticFrameHandler(frame);
753 frameHandler.GetVReg(0).Set(4.0_D);
754
755 uint8_t callInsn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
756 g_gCallResult = "";
757 InterpreterToCompiledCodeBridge(callInsn, frame, &callee, thread_);
758 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidDouble", &callee, 4.0_D));
759
760 uint8_t callRangeInsn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
761 g_gCallResult = "";
762 InterpreterToCompiledCodeBridge(callRangeInsn, frame, &callee, thread_);
763 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidDouble", &callee, 4.0_D));
764
765 int64_t args[] = {bit_cast<int64_t>(4.0_D)};
766 g_gCallResult = "";
767 InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
768 ASSERT_EQ(g_gCallResult, PrintFunc("void", "VoidDouble", &callee, 4.0_D));
769
770 FreeFrame(frame);
771 }
772
Void4Int(Method * method,int32_t a0,int32_t a1,int32_t a2,int32_t a3)773 static void Void4Int(Method *method, int32_t a0, int32_t a1, int32_t a2, int32_t a3)
774 {
775 g_gCallResult = PrintFunc("void", __FUNCTION__, method, a0, a1, a2, a3);
776 }
777
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke4Int)778 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke4Int)
779 {
780 uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32});
781 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
782 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void4Int));
783 Frame *frame = CreateFrame(4U, nullptr, nullptr);
784 auto frameHandler = StaticFrameHandler(frame);
785 frameHandler.GetVReg(0U).Set(1U);
786 frameHandler.GetVReg(1U).Set(2U);
787 frameHandler.GetVReg(2U).Set(3U);
788 frameHandler.GetVReg(3U).Set(4U);
789
790 uint8_t callInsn[] = {static_cast<uint8_t>(Opcode::CALL_V4_V4_V4_V4_ID16), 0x10, 0x32, 0, 0, 0, 0};
791 g_gCallResult = "";
792 InterpreterToCompiledCodeBridge(callInsn, frame, &callee, thread_);
793 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void4Int", &callee, 1L, 2L, 3L, 4L));
794
795 uint8_t callRangeInsn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
796 g_gCallResult = "";
797 InterpreterToCompiledCodeBridge(callRangeInsn, frame, &callee, thread_);
798 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void4Int", &callee, 1L, 2L, 3L, 4L));
799
800 int64_t args[] = {1L, 2L, 3L, 4L};
801 g_gCallResult = "";
802 InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
803 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void4Int", &callee, 1L, 2L, 3L, 4L));
804
805 frameHandler.GetVReg(3U).Set(0);
806 frameHandler.GetAcc().SetValue(4L);
807 uint8_t callAccInsn[] = {static_cast<uint8_t>(Opcode::CALL_ACC_V4_V4_V4_IMM4_ID16), 0x10, 0x32, 0, 0, 0, 0};
808 g_gCallResult = "";
809 InterpreterToCompiledCodeBridge(callAccInsn, frame, &callee, thread_);
810 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void4Int", &callee, 1L, 2L, 3L, 4L));
811
812 FreeFrame(frame);
813 }
814
Void2Long(Method * method,int64_t a0,int64_t a1)815 static void Void2Long(Method *method, int64_t a0, int64_t a1)
816 {
817 g_gCallResult = PrintFunc("void", __FUNCTION__, method, a0, a1);
818 }
819
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke2Long)820 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke2Long)
821 {
822 uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I64, TypeId::I64});
823 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
824 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void2Long));
825 Frame *frame = CreateFrame(2U, nullptr, nullptr);
826 auto frameHandler = StaticFrameHandler(frame);
827 frameHandler.GetVReg(0).Set(3U);
828 frameHandler.GetVReg(1).Set(9U);
829
830 uint8_t callInsn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x10, 0, 0, 0, 0};
831 g_gCallResult = "";
832 InterpreterToCompiledCodeBridge(callInsn, frame, &callee, thread_);
833 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void2Long", &callee, 3L, 9L));
834
835 uint8_t callRangeInsn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
836 g_gCallResult = "";
837 InterpreterToCompiledCodeBridge(callRangeInsn, frame, &callee, thread_);
838 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void2Long", &callee, 3L, 9L));
839
840 int64_t args[] = {3L, 9L};
841 g_gCallResult = "";
842 InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
843 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void2Long", &callee, 3L, 9L));
844
845 FreeFrame(frame);
846 }
847
Void4IntDouble(Method * method,int32_t a0,int32_t a1,int32_t a2,int32_t a3,double a4)848 static void Void4IntDouble(Method *method, int32_t a0, int32_t a1, int32_t a2, int32_t a3, double a4)
849 {
850 g_gCallResult = PrintFunc("void", __FUNCTION__, method, a0, a1, a2, a3, a4);
851 }
852
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke4IntDouble)853 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke4IntDouble)
854 {
855 uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::F64});
856 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
857 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void4IntDouble));
858 Frame *frame = CreateFrame(5U, nullptr, nullptr);
859 auto frameHandler = StaticFrameHandler(frame);
860 frameHandler.GetVReg(0U).Set(1U);
861 frameHandler.GetVReg(1U).Set(2U);
862 frameHandler.GetVReg(2U).Set(3U);
863 frameHandler.GetVReg(3U).Set(4U);
864 frameHandler.GetVReg(4U).Set(5.0_D);
865
866 uint8_t callRangeInsn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
867 g_gCallResult = "";
868 InterpreterToCompiledCodeBridge(callRangeInsn, frame, &callee, thread_);
869 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void4IntDouble", &callee, 1L, 2L, 3L, 4L, 5.0_D));
870
871 int64_t args[] = {1L, 2L, 3L, 4L, bit_cast<int64_t>(5.0_D)};
872 g_gCallResult = "";
873 InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
874 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void4IntDouble", &callee, 1L, 2L, 3L, 4L, 5.0_D));
875
876 FreeFrame(frame);
877 }
878
879 // aarch64 max number of register parameters
Void7Int(Method * method,int32_t a0,int32_t a1,int32_t a2,int32_t a3,int32_t a4,int32_t a5,int32_t a6)880 static void Void7Int(Method *method, int32_t a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6)
881 {
882 g_gCallResult = PrintFunc("void", __FUNCTION__, method, a0, a1, a2, a3, a4, a5, a6);
883 }
884
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke7Int)885 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke7Int)
886 {
887 uint16_t *shorty = MakeShorty(
888 {TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32});
889 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
890 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void7Int));
891 Frame *frame = CreateFrame(7U, nullptr, nullptr);
892 auto frameHandler = StaticFrameHandler(frame);
893 frameHandler.GetVReg(0U).Set(1U);
894 frameHandler.GetVReg(1U).Set(2U);
895 frameHandler.GetVReg(2U).Set(3U);
896 frameHandler.GetVReg(3U).Set(4U);
897 frameHandler.GetVReg(4U).Set(5U);
898 frameHandler.GetVReg(5U).Set(6U);
899 frameHandler.GetVReg(6U).Set(7U);
900
901 uint8_t callRangeInsn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
902 g_gCallResult = "";
903 InterpreterToCompiledCodeBridge(callRangeInsn, frame, &callee, thread_);
904 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void7Int", &callee, 1L, 2L, 3L, 4L, 5L, 6L, 7L));
905
906 int64_t args[] = {1L, 2L, 3L, 4L, 5L, 6L, 7L};
907 g_gCallResult = "";
908 InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
909 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void7Int", &callee, 1L, 2L, 3L, 4L, 5L, 6L, 7L));
910
911 FreeFrame(frame);
912 }
913
Void7Int8Double(Method * method,int32_t a0,int32_t a1,int32_t a2,int32_t a3,int32_t a4,int32_t a5,int32_t a6,double d0,double d1,double d2,double d3,double d4,double d5,double d6,double d7)914 static void Void7Int8Double(Method *method, int32_t a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5,
915 int32_t a6, double d0, double d1, double d2, double d3, double d4, double d5, double d6,
916 double d7)
917 {
918 g_gCallResult = PrintFunc("void", __FUNCTION__, method, a0, a1, a2, a3, a4, a5, a6, d0, d1, d2, d3, d4, d5, d6, d7);
919 }
920
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke7Int8Double)921 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke7Int8Double)
922 {
923 uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32,
924 TypeId::I32, TypeId::I32, TypeId::F64, TypeId::F64, TypeId::F64, TypeId::F64,
925 TypeId::F64, TypeId::F64, TypeId::F64, TypeId::F64});
926 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
927 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void7Int8Double));
928 Frame *frame = CreateFrame(15U, nullptr, nullptr);
929 auto frameHandler = StaticFrameHandler(frame);
930 frameHandler.GetVReg(0U).Set(1U);
931 frameHandler.GetVReg(1U).Set(2U);
932 frameHandler.GetVReg(2U).Set(3U);
933 frameHandler.GetVReg(3U).Set(4U);
934 frameHandler.GetVReg(4U).Set(5U);
935 frameHandler.GetVReg(5U).Set(6U);
936 frameHandler.GetVReg(6U).Set(7U);
937 frameHandler.GetVReg(7U).Set(8.0_D);
938 frameHandler.GetVReg(8U).Set(9.0_D);
939 frameHandler.GetVReg(9U).Set(10.0_D);
940 frameHandler.GetVReg(10U).Set(11.0_D);
941 frameHandler.GetVReg(11U).Set(12.0_D);
942 frameHandler.GetVReg(12U).Set(13.0_D);
943 frameHandler.GetVReg(13U).Set(14.0_D);
944 frameHandler.GetVReg(14U).Set(15.0_D);
945
946 uint8_t callRangeInsn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
947 g_gCallResult = "";
948 InterpreterToCompiledCodeBridge(callRangeInsn, frame, &callee, thread_);
949 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void7Int8Double", &callee, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8.0_D, 9.0_D,
950 10.0_D, 11.0_D, 12.0_D, 13.0_D, 14.0_D, 15.0_D));
951
952 int64_t args[] = {1L,
953 2L,
954 3L,
955 4L,
956 5L,
957 6L,
958 7L,
959 bit_cast<int64_t>(8.0_D),
960 bit_cast<int64_t>(9.0_D),
961 bit_cast<int64_t>(10.0_D),
962 bit_cast<int64_t>(11.0_D),
963 bit_cast<int64_t>(12.0_D),
964 bit_cast<int64_t>(13.0_D),
965 bit_cast<int64_t>(14.0_D),
966 bit_cast<int64_t>(15.0_D)};
967 g_gCallResult = "";
968 InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
969 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void7Int8Double", &callee, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8.0_D, 9.0_D,
970 10.0_D, 11.0_D, 12.0_D, 13.0_D, 14.0_D, 15.0_D));
971
972 FreeFrame(frame);
973 }
974
Void8Int(Method * method,int32_t a0,int32_t a1,int32_t a2,int32_t a3,int32_t a4,int32_t a5,int32_t a6,int32_t a7)975 static void Void8Int(Method *method, int32_t a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6,
976 int32_t a7)
977 {
978 g_gCallResult = PrintFunc("void", __FUNCTION__, method, a0, a1, a2, a3, a4, a5, a6, a7);
979 }
980
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke8Int)981 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke8Int)
982 {
983 uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32,
984 TypeId::I32, TypeId::I32, TypeId::I32});
985 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
986 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void8Int));
987 Frame *frame = CreateFrame(8U, nullptr, nullptr);
988 auto frameHandler = StaticFrameHandler(frame);
989 frameHandler.GetVReg(0U).Set(1U);
990 frameHandler.GetVReg(1U).Set(2U);
991 frameHandler.GetVReg(2U).Set(3U);
992 frameHandler.GetVReg(3U).Set(4U);
993 frameHandler.GetVReg(4U).Set(5U);
994 frameHandler.GetVReg(5U).Set(6U);
995 frameHandler.GetVReg(6U).Set(7U);
996 frameHandler.GetVReg(7U).Set(8U);
997
998 uint8_t callRangeInsn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
999 g_gCallResult = "";
1000 InterpreterToCompiledCodeBridge(callRangeInsn, frame, &callee, thread_);
1001 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void8Int", &callee, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L));
1002
1003 int64_t args[] = {1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L};
1004 g_gCallResult = "";
1005 InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
1006 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void8Int", &callee, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L));
1007
1008 FreeFrame(frame);
1009 }
1010
Void6IntVReg(Method * method,int32_t a0,int32_t a1,int32_t a2,int32_t a3,int32_t a4,int32_t a5,int64_t value)1011 static void Void6IntVReg(Method *method, int32_t a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5,
1012 int64_t value)
1013 {
1014 g_gCallResult = PrintFunc("void", __FUNCTION__, method, a0, a1, a2, a3, a4, a5, value);
1015 }
1016
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke6IntVReg)1017 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke6IntVReg)
1018 {
1019 uint16_t *shorty = MakeShorty(
1020 {TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::TAGGED});
1021 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
1022 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void6IntVReg));
1023 Frame *frame = CreateFrame(8U, nullptr, nullptr);
1024 auto frameHandler = StaticFrameHandler(frame);
1025 frameHandler.GetVReg(0U).Set(1U);
1026 frameHandler.GetVReg(1U).Set(2U);
1027 frameHandler.GetVReg(2U).Set(3U);
1028 frameHandler.GetVReg(3U).Set(4U);
1029 frameHandler.GetVReg(4U).Set(5U);
1030 frameHandler.GetVReg(5U).Set(6U);
1031 frameHandler.GetVReg(6U).Set(7U);
1032
1033 uint8_t callRangeInsn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
1034 g_gCallResult = "";
1035 InterpreterToCompiledCodeBridge(callRangeInsn, frame, &callee, thread_);
1036 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void6IntVReg", &callee, 1L, 2L, 3L, 4L, 5L, 6L, 7L));
1037
1038 int64_t args[] = {1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L};
1039 g_gCallResult = "";
1040 InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
1041 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void6IntVReg", &callee, 1L, 2L, 3L, 4L, 5L, 6L, 7L));
1042
1043 FreeFrame(frame);
1044 }
1045
Void7IntVReg(Method * method,int32_t a0,int32_t a1,int32_t a2,int32_t a3,int32_t a4,int32_t a5,int32_t a6,int64_t value)1046 static void Void7IntVReg(Method *method, int32_t a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5,
1047 int32_t a6, int64_t value)
1048 {
1049 g_gCallResult = PrintFunc("void", __FUNCTION__, method, a0, a1, a2, a3, a4, a5, a6, value);
1050 }
1051
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke7IntVReg)1052 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke7IntVReg)
1053 {
1054 uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32,
1055 TypeId::I32, TypeId::I32, TypeId::TAGGED});
1056 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
1057 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void7IntVReg));
1058 Frame *frame = CreateFrame(8U, nullptr, nullptr);
1059 auto frameHandler = StaticFrameHandler(frame);
1060 frameHandler.GetVReg(0U).Set(1U);
1061 frameHandler.GetVReg(1U).Set(2U);
1062 frameHandler.GetVReg(2U).Set(3U);
1063 frameHandler.GetVReg(3U).Set(4U);
1064 frameHandler.GetVReg(4U).Set(5U);
1065 frameHandler.GetVReg(5U).Set(6U);
1066 frameHandler.GetVReg(6U).Set(7U);
1067 frameHandler.GetVReg(7U).Set(8U);
1068
1069 uint8_t callRangeInsn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
1070 g_gCallResult = "";
1071 InterpreterToCompiledCodeBridge(callRangeInsn, frame, &callee, thread_);
1072 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void7IntVReg", &callee, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L));
1073
1074 int64_t args[] = {1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L};
1075 g_gCallResult = "";
1076 InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
1077 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void7IntVReg", &callee, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L));
1078
1079 FreeFrame(frame);
1080 }
1081
Void8Int9Double(Method * method,int32_t a0,int32_t a1,int32_t a2,int32_t a3,int32_t a4,int32_t a5,int32_t a6,int32_t a7,double d0,double d1,double d2,double d3,double d4,double d5,double d6,double d7,double d8)1082 static void Void8Int9Double(Method *method, int32_t a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5,
1083 int32_t a6, int32_t a7, double d0, double d1, double d2, double d3, double d4, double d5,
1084 double d6, double d7, double d8)
1085 {
1086 g_gCallResult =
1087 PrintFunc("void", __FUNCTION__, method, a0, a1, a2, a3, a4, a5, a6, a7, d0, d1, d2, d3, d4, d5, d6, d7, d8);
1088 }
1089
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke8Int9Double)1090 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke8Int9Double)
1091 {
1092 uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32,
1093 TypeId::I32, TypeId::I32, TypeId::I32, TypeId::F64, TypeId::F64, TypeId::F64,
1094 TypeId::F64, TypeId::F64, TypeId::F64, TypeId::F64, TypeId::F64, TypeId::F64});
1095 Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
1096 callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void8Int9Double));
1097 Frame *frame = CreateFrame(17U, nullptr, nullptr);
1098 auto frameHandler = StaticFrameHandler(frame);
1099 frameHandler.GetVReg(0U).Set(1U);
1100 frameHandler.GetVReg(1U).Set(2U);
1101 frameHandler.GetVReg(2U).Set(3U);
1102 frameHandler.GetVReg(3U).Set(4U);
1103 frameHandler.GetVReg(4U).Set(5U);
1104 frameHandler.GetVReg(5U).Set(6U);
1105 frameHandler.GetVReg(6U).Set(7U);
1106 frameHandler.GetVReg(7U).Set(8U);
1107 frameHandler.GetVReg(8U).Set(9.0_D);
1108 frameHandler.GetVReg(9U).Set(10.0_D);
1109 frameHandler.GetVReg(10U).Set(11.0_D);
1110 frameHandler.GetVReg(11U).Set(12.0_D);
1111 frameHandler.GetVReg(12U).Set(13.0_D);
1112 frameHandler.GetVReg(13U).Set(14.0_D);
1113 frameHandler.GetVReg(14U).Set(15.0_D);
1114 frameHandler.GetVReg(15U).Set(16.0_D);
1115 frameHandler.GetVReg(16U).Set(17.0_D);
1116
1117 uint8_t callRangeInsn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
1118 g_gCallResult = "";
1119 InterpreterToCompiledCodeBridge(callRangeInsn, frame, &callee, thread_);
1120 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void8Int9Double", &callee, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9.0_D,
1121 10.0_D, 11.0_D, 12.0_D, 13.0_D, 14.0_D, 15.0_D, 16.0_D, 17.0_D));
1122
1123 int64_t args[] = {1L,
1124 2L,
1125 3L,
1126 4L,
1127 5L,
1128 6L,
1129 7L,
1130 8L,
1131 bit_cast<int64_t>(9.0_D),
1132 bit_cast<int64_t>(10.0_D),
1133 bit_cast<int64_t>(11.0_D),
1134 bit_cast<int64_t>(12.0_D),
1135 bit_cast<int64_t>(13.0_D),
1136 bit_cast<int64_t>(14.0_D),
1137 bit_cast<int64_t>(15.0_D),
1138 bit_cast<int64_t>(16.0_D),
1139 bit_cast<int64_t>(17.0_D)};
1140 g_gCallResult = "";
1141 InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
1142 ASSERT_EQ(g_gCallResult, PrintFunc("void", "Void8Int9Double", &callee, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9.0_D,
1143 10.0_D, 11.0_D, 12.0_D, 13.0_D, 14.0_D, 15.0_D, 16.0_D, 17.0_D));
1144
1145 FreeFrame(frame);
1146 }
1147
1148 } // namespace ark::test
1149
1150 // NOLINTEND(readability-magic-numbers,modernize-avoid-c-arrays)
1151