• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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