• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 "libpandafile/file_items.h"
24 #include "libpandafile/value.h"
25 #include "runtime/bridge/bridge.h"
26 #include "runtime/entrypoints/entrypoints.h"
27 #include "runtime/include/method.h"
28 #include "runtime/include/runtime.h"
29 #include "runtime/include/thread.h"
30 #include "runtime/interpreter/frame.h"
31 #include "runtime/tests/test_utils.h"
32 
33 using TypeId = panda::panda_file::Type::TypeId;
34 using Opcode = panda::BytecodeInstruction::Opcode;
35 
36 namespace panda::test {
37 
38 static std::string g_call_result;
39 
40 class InterpreterToCompiledCodeBridgeTest : public testing::Test {
41 public:
InterpreterToCompiledCodeBridgeTest()42     InterpreterToCompiledCodeBridgeTest()
43     {
44         RuntimeOptions options;
45         options.SetShouldLoadBootPandaFiles(false);
46         options.SetShouldInitializeIntrinsics(false);
47         options.SetGcType("epsilon");
48         Runtime::Create(options);
49 
50         thread_ = MTManagedThread::GetCurrent();
51         thread_->ManagedCodeBegin();
52         g_call_result = "";
53     }
54 
~InterpreterToCompiledCodeBridgeTest()55     ~InterpreterToCompiledCodeBridgeTest()
56     {
57         thread_->ManagedCodeEnd();
58         Runtime::Destroy();
59     }
60 
MakeShorty(const std::initializer_list<TypeId> & shorty)61     uint16_t *MakeShorty(const std::initializer_list<TypeId> &shorty)
62     {
63         constexpr size_t ELEM_SIZE = 4;
64         constexpr size_t ELEM_COUNT = std::numeric_limits<uint16_t>::digits / ELEM_SIZE;
65 
66         uint16_t val = 0;
67         uint32_t count = 0;
68         for (auto it = shorty.begin(); it != shorty.end(); ++it) {
69             if (count == ELEM_COUNT) {
70                 shorty_.push_back(val);
71                 val = 0;
72                 count = 0;
73             }
74             val |= static_cast<uint8_t>(*it) << ELEM_SIZE * count;
75             ++count;
76         }
77         if (count == ELEM_COUNT) {
78             shorty_.push_back(val);
79             val = 0;
80             count = 0;
81         }
82         shorty_.push_back(val);
83         return shorty_.data();
84     }
85 
86 protected:
87     MTManagedThread *thread_;
88     std::vector<uint16_t> shorty_;
89 };
90 
91 // Test interpreter -> compiled code bridge
92 
93 template <typename Arg>
ArgsToString(const Arg & arg)94 std::string ArgsToString(const Arg &arg)
95 {
96     std::ostringstream out;
97     out << arg;
98     return out.str();
99 }
100 
101 template <typename Arg, typename... Args>
ArgsToString(const Arg & a0,Args...args)102 std::string ArgsToString(const Arg &a0, Args... args)
103 {
104     std::ostringstream out;
105     out << a0 << ", " << ArgsToString(args...);
106     return out.str();
107 }
108 
109 template <typename... Args>
PrintFunc(const char * ret,const char * name,Args...args)110 std::string PrintFunc(const char *ret, const char *name, Args... args)
111 {
112     std::ostringstream out;
113     out << ret << " " << name << "(" << ArgsToString(args...) << ")";
114     return out.str();
115 }
116 
VoidNoArg(Method * method)117 static void VoidNoArg(Method *method)
118 {
119     g_call_result = PrintFunc("void", __FUNCTION__, method);
120 }
121 
122 template <bool is_dynamic = false>
CreateFrame(size_t nregs,Method * method,Frame * prev)123 static Frame *CreateFrame(size_t nregs, Method *method, Frame *prev)
124 {
125     return panda::CreateFrameWithSize(Frame::GetActualSize<is_dynamic>(nregs), nregs, method, prev);
126 }
127 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeVoidNoArg)128 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeVoidNoArg)
129 {
130     uint16_t *shorty = MakeShorty({TypeId::VOID});
131     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
132     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(VoidNoArg));
133     Frame *frame = CreateFrame(0, nullptr, nullptr);
134 
135     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
136     g_call_result = "";
137     InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
138     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidNoArg", &callee));
139 
140     uint8_t insn2[] = {static_cast<uint8_t>(Opcode::CALL_ACC_SHORT_V4_IMM4_ID16), 0x00, 0, 0, 0, 0};
141     g_call_result = "";
142     InterpreterToCompiledCodeBridge(insn2, frame, &callee, thread_);
143     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidNoArg", &callee));
144 
145     g_call_result = "";
146     InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
147     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidNoArg", &callee));
148 
149     FreeFrame(frame);
150 }
151 
InstanceVoidNoArg(Method * method,ObjectHeader * this_)152 static void InstanceVoidNoArg(Method *method, ObjectHeader *this_)
153 {
154     g_call_result = PrintFunc("void", __FUNCTION__, method, this_);
155 }
156 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeInstanceVoidNoArg)157 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeInstanceVoidNoArg)
158 {
159     uint16_t *shorty = MakeShorty({TypeId::VOID});
160     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), 0, 1, shorty);
161     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(InstanceVoidNoArg));
162     Frame *frame = CreateFrame(1, nullptr, nullptr);
163     auto frame_handler = StaticFrameHandler(frame);
164 
165     ObjectHeader *obj1 = panda::mem::AllocateNullifiedPayloadString(5);
166     frame_handler.GetAccAsVReg().SetReference(obj1);
167     ObjectHeader *obj2 = panda::mem::AllocateNullifiedPayloadString(4);
168     frame_handler.GetVReg(0).SetReference(obj2);
169 
170     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
171     g_call_result = "";
172     InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
173     ASSERT_EQ(g_call_result, PrintFunc("void", "InstanceVoidNoArg", &callee, obj2));
174 
175     uint8_t insn2[] = {static_cast<uint8_t>(Opcode::CALL_ACC_SHORT_V4_IMM4_ID16), 0x00, 0, 0, 0, 0};
176     g_call_result = "";
177     InterpreterToCompiledCodeBridge(insn2, frame, &callee, thread_);
178     ASSERT_EQ(g_call_result, PrintFunc("void", "InstanceVoidNoArg", &callee, obj1));
179 
180     g_call_result = "";
181     int64_t args[] = {static_cast<int64_t>(ToUintPtr(obj2))};
182     InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
183     ASSERT_EQ(g_call_result, PrintFunc("void", "InstanceVoidNoArg", &callee, obj2));
184 
185     FreeFrame(frame);
186 }
187 
ByteNoArg(Method * method)188 static uint8_t ByteNoArg(Method *method)
189 {
190     g_call_result = PrintFunc("uint8_t", __FUNCTION__, method);
191     return uint8_t(5);
192 }
193 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeByteNoArg)194 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeByteNoArg)
195 {
196     uint16_t *shorty = MakeShorty({TypeId::U8});
197     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
198     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(ByteNoArg));
199     Frame *frame = CreateFrame(0, nullptr, nullptr);
200     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
201 
202     g_call_result = "";
203     InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
204     EXPECT_EQ(g_call_result, PrintFunc("uint8_t", "ByteNoArg", &callee));
205     EXPECT_EQ(frame->GetAcc().Get(), uint8_t(5));
206     EXPECT_EQ(frame->GetAcc().GetTag(), 0);
207 
208     uint8_t insn_acc[] = {static_cast<uint8_t>(Opcode::CALL_ACC_SHORT_V4_IMM4_ID16), 0x00, 0, 0, 0, 0};
209     g_call_result = "";
210     InterpreterToCompiledCodeBridge(insn_acc, frame, &callee, thread_);
211     EXPECT_EQ(g_call_result, PrintFunc("uint8_t", "ByteNoArg", &callee));
212     EXPECT_EQ(frame->GetAcc().Get(), uint8_t(5));
213     EXPECT_EQ(frame->GetAcc().GetTag(), 0);
214 
215     g_call_result = "";
216     DecodedTaggedValue res = InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
217     EXPECT_EQ(int32_t(res.value), uint8_t(5));
218     EXPECT_EQ(res.tag, 0UL);
219     EXPECT_EQ(g_call_result, PrintFunc("uint8_t", "ByteNoArg", &callee));
220 
221     FreeFrame(frame);
222 }
223 
SignedByteNoArg(Method * method)224 static int8_t SignedByteNoArg(Method *method)
225 {
226     g_call_result = PrintFunc("int8_t", __FUNCTION__, method);
227     return int8_t(-5);
228 }
229 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeSignedByteNoArg)230 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeSignedByteNoArg)
231 {
232     uint16_t *shorty = MakeShorty({TypeId::I8});
233     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
234     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(SignedByteNoArg));
235     Frame *frame = CreateFrame(0, nullptr, nullptr);
236     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
237 
238     g_call_result = "";
239     InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
240     EXPECT_EQ(g_call_result, PrintFunc("int8_t", "SignedByteNoArg", &callee));
241     EXPECT_EQ(frame->GetAcc().Get(), int8_t(-5));
242     EXPECT_EQ(frame->GetAcc().GetTag(), 0);
243 
244     uint8_t insn_acc[] = {static_cast<uint8_t>(Opcode::CALL_ACC_SHORT_V4_IMM4_ID16), 0x00, 0, 0, 0, 0};
245     g_call_result = "";
246     InterpreterToCompiledCodeBridge(insn_acc, frame, &callee, thread_);
247     EXPECT_EQ(g_call_result, PrintFunc("int8_t", "SignedByteNoArg", &callee));
248     EXPECT_EQ(frame->GetAcc().Get(), int8_t(-5));
249     EXPECT_EQ(frame->GetAcc().GetTag(), 0);
250 
251     g_call_result = "";
252     DecodedTaggedValue res = InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
253     EXPECT_EQ(int32_t(res.value), int8_t(-5));
254     EXPECT_EQ(res.tag, 0UL);
255     EXPECT_EQ(g_call_result, PrintFunc("int8_t", "SignedByteNoArg", &callee));
256 
257     FreeFrame(frame);
258 }
259 
BoolNoArg(Method * method)260 static bool BoolNoArg(Method *method)
261 {
262     g_call_result = PrintFunc("bool", __FUNCTION__, method);
263     return true;
264 }
265 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeBoolNoArg)266 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeBoolNoArg)
267 {
268     uint16_t *shorty = MakeShorty({TypeId::U1});
269     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
270     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(BoolNoArg));
271     Frame *frame = CreateFrame(0, nullptr, nullptr);
272     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
273 
274     g_call_result = "";
275     InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
276     EXPECT_EQ(g_call_result, PrintFunc("bool", "BoolNoArg", &callee));
277     EXPECT_EQ(frame->GetAcc().Get(), true);
278     EXPECT_EQ(frame->GetAcc().GetTag(), 0);
279 
280     g_call_result = "";
281     DecodedTaggedValue res = InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
282     EXPECT_EQ(int32_t(res.value), true);
283     EXPECT_EQ(res.tag, 0UL);
284     EXPECT_EQ(g_call_result, PrintFunc("bool", "BoolNoArg", &callee));
285 
286     FreeFrame(frame);
287 }
288 
ShortNoArg(Method * method)289 static uint16_t ShortNoArg(Method *method)
290 {
291     g_call_result = PrintFunc("uint16_t", __FUNCTION__, method);
292     return uint16_t(5);
293 }
294 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeShortNoArg)295 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeShortNoArg)
296 {
297     uint16_t *shorty = MakeShorty({TypeId::U16});
298     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
299     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(ShortNoArg));
300     Frame *frame = CreateFrame(0, nullptr, nullptr);
301     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
302 
303     g_call_result = "";
304     InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
305     EXPECT_EQ(g_call_result, PrintFunc("uint16_t", "ShortNoArg", &callee));
306     EXPECT_EQ(frame->GetAcc().Get(), uint16_t(5));
307     EXPECT_EQ(frame->GetAcc().GetTag(), 0);
308 
309     g_call_result = "";
310     DecodedTaggedValue res = InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
311     EXPECT_EQ(int32_t(res.value), uint16_t(5));
312     EXPECT_EQ(res.tag, 0UL);
313     EXPECT_EQ(g_call_result, PrintFunc("uint16_t", "ShortNoArg", &callee));
314 
315     FreeFrame(frame);
316 }
317 
SignedShortNoArg(Method * method)318 static int16_t SignedShortNoArg(Method *method)
319 {
320     g_call_result = PrintFunc("int16_t", __FUNCTION__, method);
321     return int16_t(-5);
322 }
323 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeSignedShortNoArg)324 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeSignedShortNoArg)
325 {
326     uint16_t *shorty = MakeShorty({TypeId::I16});
327     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
328     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(SignedShortNoArg));
329     Frame *frame = CreateFrame(0, nullptr, nullptr);
330     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
331 
332     g_call_result = "";
333     InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
334     EXPECT_EQ(g_call_result, PrintFunc("int16_t", "SignedShortNoArg", &callee));
335     EXPECT_EQ(frame->GetAcc().Get(), int16_t(-5));
336     EXPECT_EQ(frame->GetAcc().GetTag(), 0);
337 
338     g_call_result = "";
339     DecodedTaggedValue res = InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
340     EXPECT_EQ(int32_t(res.value), int16_t(-5));
341     EXPECT_EQ(res.tag, 0UL);
342     EXPECT_EQ(g_call_result, PrintFunc("int16_t", "SignedShortNoArg", &callee));
343 
344     FreeFrame(frame);
345 }
346 
IntNoArg(Method * method)347 static int32_t IntNoArg(Method *method)
348 {
349     g_call_result = PrintFunc("int32_t", __FUNCTION__, method);
350     return 5;
351 }
352 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeIntNoArg)353 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeIntNoArg)
354 {
355     uint16_t *shorty = MakeShorty({TypeId::I32});
356     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
357     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(IntNoArg));
358     Frame *frame = CreateFrame(0, nullptr, nullptr);
359     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
360 
361     g_call_result = "";
362     InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
363     ASSERT_EQ(g_call_result, PrintFunc("int32_t", "IntNoArg", &callee));
364     ASSERT_EQ(frame->GetAcc().Get(), 5);
365     EXPECT_EQ(frame->GetAcc().GetTag(), 0);
366 
367     g_call_result = "";
368     DecodedTaggedValue res = InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
369     ASSERT_EQ(res.value, 5);
370     EXPECT_EQ(res.tag, 0UL);
371     ASSERT_EQ(g_call_result, PrintFunc("int32_t", "IntNoArg", &callee));
372 
373     FreeFrame(frame);
374 }
375 
LongNoArg(Method * method)376 static int64_t LongNoArg(Method *method)
377 {
378     g_call_result = PrintFunc("int64_t", __FUNCTION__, method);
379     return 8;
380 }
381 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeLongNoArg)382 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeLongNoArg)
383 {
384     uint16_t *shorty = MakeShorty({TypeId::I64});
385     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
386     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(LongNoArg));
387     Frame *frame = CreateFrame(0, nullptr, nullptr);
388     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
389 
390     g_call_result = "";
391     InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
392     ASSERT_EQ(g_call_result, PrintFunc("int64_t", "LongNoArg", &callee));
393     ASSERT_EQ(frame->GetAcc().Get(), 8);
394     EXPECT_EQ(frame->GetAcc().GetTag(), 0);
395 
396     g_call_result = "";
397     DecodedTaggedValue res = InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
398     ASSERT_EQ(res.value, 8);
399     EXPECT_EQ(res.tag, 0UL);
400     ASSERT_EQ(g_call_result, PrintFunc("int64_t", "LongNoArg", &callee));
401 
402     FreeFrame(frame);
403 }
404 
DoubleNoArg(Method * method)405 static double DoubleNoArg(Method *method)
406 {
407     g_call_result = PrintFunc("double", __FUNCTION__, method);
408     return 3.0;
409 }
410 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeDoubleNoArg)411 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeDoubleNoArg)
412 {
413     uint16_t *shorty = MakeShorty({TypeId::F64});
414     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
415     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(DoubleNoArg));
416     Frame *frame = CreateFrame(0, nullptr, nullptr);
417     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
418 
419     g_call_result = "";
420     InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
421     ASSERT_EQ(g_call_result, PrintFunc("double", "DoubleNoArg", &callee));
422     ASSERT_EQ(frame->GetAcc().GetDouble(), 3.0);
423     EXPECT_EQ(frame->GetAcc().GetTag(), 0);
424 
425     g_call_result = "";
426     DecodedTaggedValue res = InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
427     ASSERT_EQ(bit_cast<double>(res.value), 3.0);
428     EXPECT_EQ(res.tag, 0UL);
429     ASSERT_EQ(g_call_result, PrintFunc("double", "DoubleNoArg", &callee));
430 
431     FreeFrame(frame);
432 }
433 
ObjNoArg(Method * method)434 static ObjectHeader *ObjNoArg(Method *method)
435 {
436     g_call_result = PrintFunc("Object", __FUNCTION__, method);
437     return nullptr;
438 }
439 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeObjNoArg)440 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeObjNoArg)
441 {
442     uint16_t *shorty = MakeShorty({TypeId::REFERENCE});
443     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
444     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(ObjNoArg));
445     Frame *frame = CreateFrame(0, nullptr, nullptr);
446     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
447 
448     g_call_result = "";
449     InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
450     ASSERT_EQ(g_call_result, PrintFunc("Object", "ObjNoArg", &callee));
451     ASSERT_EQ(frame->GetAcc().GetReference(), nullptr);
452     EXPECT_EQ(frame->GetAcc().GetTag(), 1);
453 
454     g_call_result = "";
455     DecodedTaggedValue res = InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
456     ASSERT_EQ(reinterpret_cast<ObjectHeader *>(res.value), nullptr);
457     EXPECT_EQ(res.tag, 1UL);
458     ASSERT_EQ(g_call_result, PrintFunc("Object", "ObjNoArg", &callee));
459 
460     FreeFrame(frame);
461 }
462 
VRegNoArg(Method * method)463 static DecodedTaggedValue VRegNoArg(Method *method)
464 {
465     g_call_result = PrintFunc("vreg", __FUNCTION__, method);
466     return DecodedTaggedValue(5, 7);
467 }
468 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeVRegNoArg)469 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeVRegNoArg)
470 {
471     uint16_t *shorty = MakeShorty({TypeId::TAGGED});
472     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
473     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(VRegNoArg));
474     Frame *frame = CreateFrame(0, nullptr, nullptr);
475     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
476 
477     g_call_result = "";
478     InterpreterToCompiledCodeBridge(insn, frame, &callee, thread_);
479     ASSERT_EQ(g_call_result, PrintFunc("vreg", "VRegNoArg", &callee));
480     ASSERT_EQ(frame->GetAcc().GetValue(), 5);
481     ASSERT_EQ(frame->GetAcc().GetTag(), 7);
482 
483     g_call_result = "";
484     DecodedTaggedValue res = InvokeCompiledCodeWithArgArray(nullptr, frame, &callee, thread_);
485     ASSERT_EQ(g_call_result, PrintFunc("vreg", "VRegNoArg", &callee));
486     ASSERT_EQ(res.value, 5);
487     ASSERT_EQ(res.tag, 7);
488 
489     FreeFrame(frame);
490 }
491 
VoidInt(Method * method,int32_t a0)492 static void VoidInt(Method *method, int32_t a0)
493 {
494     g_call_result = PrintFunc("void", __FUNCTION__, method, a0);
495 }
496 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeInt)497 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeInt)
498 {
499     uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32});
500     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
501     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(VoidInt));
502     Frame *frame = CreateFrame(2, nullptr, nullptr);
503     frame->GetVReg(1).Set(5);
504 
505     uint8_t call_short_insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x01, 0, 0, 0, 0};
506     g_call_result = "";
507     InterpreterToCompiledCodeBridge(call_short_insn, frame, &callee, thread_);
508     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidInt", &callee, 5));
509 
510     uint8_t call_range_insn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x01, 0, 0, 0, 0};
511     g_call_result = "";
512     InterpreterToCompiledCodeBridge(call_range_insn, frame, &callee, thread_);
513     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidInt", &callee, 5));
514 
515     g_call_result = "";
516     int64_t arg = 5;
517     InvokeCompiledCodeWithArgArray(&arg, frame, &callee, thread_);
518     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidInt", &callee, 5));
519 
520     frame->GetVReg(1).Set(0);
521     frame->GetAcc().SetValue(5);
522     uint8_t call_acc_insn[] = {static_cast<uint8_t>(Opcode::CALL_ACC_SHORT_V4_IMM4_ID16), 0x00, 0, 0};
523     g_call_result = "";
524     InterpreterToCompiledCodeBridge(call_acc_insn, frame, &callee, thread_);
525     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidInt", &callee, 5));
526 
527     FreeFrame(frame);
528 }
529 
InstanceVoidInt(Method * method,ObjectHeader * this_,int32_t a0)530 static void InstanceVoidInt(Method *method, ObjectHeader *this_, int32_t a0)
531 {
532     g_call_result = PrintFunc("void", __FUNCTION__, method, this_, a0);
533 }
534 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeInstanceInt)535 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeInstanceInt)
536 {
537     uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32});
538     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), 0, 0, shorty);
539     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(InstanceVoidInt));
540     Frame *frame = CreateFrame(2, nullptr, nullptr);
541     auto frame_handler = StaticFrameHandler(frame);
542     ObjectHeader *obj = panda::mem::AllocateNullifiedPayloadString(1);
543     frame_handler.GetVReg(0).SetReference(obj);
544     frame_handler.GetVReg(1).Set(5);
545 
546     uint8_t call_short_insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x10, 0, 0, 0, 0};
547     g_call_result = "";
548     InterpreterToCompiledCodeBridge(call_short_insn, frame, &callee, thread_);
549     ASSERT_EQ(g_call_result, PrintFunc("void", "InstanceVoidInt", &callee, obj, 5));
550 
551     uint8_t call_range_insn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
552     g_call_result = "";
553     InterpreterToCompiledCodeBridge(call_range_insn, frame, &callee, thread_);
554     ASSERT_EQ(g_call_result, PrintFunc("void", "InstanceVoidInt", &callee, obj, 5));
555 
556     g_call_result = "";
557     int64_t args[] = {static_cast<int64_t>(ToUintPtr(obj)), 5};
558     InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
559     ASSERT_EQ(g_call_result, PrintFunc("void", "InstanceVoidInt", &callee, obj, 5));
560 
561     frame_handler.GetVReg(1).Set(0);
562     frame_handler.GetAcc().SetValue(5);
563     uint8_t call_acc_insn[] = {static_cast<uint8_t>(Opcode::CALL_ACC_SHORT_V4_IMM4_ID16), 0x10, 0, 0};
564     g_call_result = "";
565     InterpreterToCompiledCodeBridge(call_acc_insn, frame, &callee, thread_);
566     ASSERT_EQ(g_call_result, PrintFunc("void", "InstanceVoidInt", &callee, obj, 5));
567 
568     FreeFrame(frame);
569 }
570 
VoidVReg(Method * method,int64_t value)571 static void VoidVReg(Method *method, int64_t value)
572 {
573     g_call_result = PrintFunc("void", __FUNCTION__, method, value);
574 }
575 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeVReg)576 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeVReg)
577 {
578     uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::TAGGED});
579     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
580     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(VoidVReg));
581     Frame *frame = CreateFrame(2, nullptr, nullptr);
582     auto frame_handler = StaticFrameHandler(frame);
583     frame_handler.GetVReg(1).Set(5);
584 
585     uint8_t call_short_insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x01, 0, 0, 0, 0};
586     g_call_result = "";
587     InterpreterToCompiledCodeBridge(call_short_insn, frame, &callee, thread_);
588     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidVReg", &callee, 5));
589 
590     uint8_t call_range_insn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x01, 0, 0, 0, 0};
591     g_call_result = "";
592     InterpreterToCompiledCodeBridge(call_range_insn, frame, &callee, thread_);
593     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidVReg", &callee, 5));
594 
595     g_call_result = "";
596     int64_t arg[] = {5, 8};
597     InvokeCompiledCodeWithArgArray(arg, frame, &callee, thread_);
598     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidVReg", &callee, 5));
599 
600     frame_handler.GetVReg(1).Set(0);
601     frame_handler.GetAcc().SetValue(5);
602     uint8_t call_acc_short[] = {static_cast<uint8_t>(Opcode::CALL_ACC_SHORT_V4_IMM4_ID16), 0x01, 0, 0, 0, 0};
603     g_call_result = "";
604     InterpreterToCompiledCodeBridge(call_acc_short, frame, &callee, thread_);
605     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidVReg", &callee, 5));
606     FreeFrame(frame);
607 }
608 
VoidIntVReg(Method * method,int32_t a0,int64_t value)609 static void VoidIntVReg(Method *method, int32_t a0, int64_t value)
610 {
611     g_call_result = PrintFunc("void", __FUNCTION__, method, a0, value);
612 }
613 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeIntVReg)614 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeIntVReg)
615 {
616     uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32, TypeId::TAGGED});
617     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
618     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(VoidIntVReg));
619     Frame *frame = CreateFrame(2, nullptr, nullptr);
620     auto frame_handler = StaticFrameHandler(frame);
621     frame_handler.GetVReg(0).Set(2);
622     frame_handler.GetVReg(1).Set(5);
623 
624     uint8_t call_short_insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x10, 0, 0, 0, 0};
625     g_call_result = "";
626     InterpreterToCompiledCodeBridge(call_short_insn, frame, &callee, thread_);
627     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidIntVReg", &callee, 2, 5));
628 
629     uint8_t call_range_insn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
630     g_call_result = "";
631     InterpreterToCompiledCodeBridge(call_range_insn, frame, &callee, thread_);
632     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidIntVReg", &callee, 2, 5));
633 
634     g_call_result = "";
635     int64_t arg[] = {2, 5, 8};
636     InvokeCompiledCodeWithArgArray(arg, frame, &callee, thread_);
637     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidIntVReg", &callee, 2, 5));
638 
639     frame_handler.GetAcc().SetValue(5);
640     frame_handler.GetVReg(1).Set(0);
641     uint8_t call_acc_short_insn[] = {static_cast<uint8_t>(Opcode::CALL_ACC_SHORT_V4_IMM4_ID16), 0x10, 0, 0};
642     g_call_result = "";
643     InterpreterToCompiledCodeBridge(call_acc_short_insn, frame, &callee, thread_);
644     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidIntVReg", &callee, 2, 5));
645 
646     FreeFrame(frame);
647 }
648 
649 // arm max number of register parameters
Void3Int(Method * method,int32_t a0,int32_t a1,int32_t a2)650 static void Void3Int(Method *method, int32_t a0, int32_t a1, int32_t a2)
651 {
652     g_call_result = PrintFunc("void", __FUNCTION__, method, a0, a1, a2);
653 }
654 
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke3Int)655 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke3Int)
656 {
657     uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I32});
658     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
659     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void3Int));
660     Frame *frame = CreateFrame(3, nullptr, nullptr);
661     auto frame_handler = StaticFrameHandler(frame);
662     frame_handler.GetAcc().SetValue(0);
663     frame_handler.GetVReg(0).Set(1);
664     frame_handler.GetVReg(1).Set(2);
665     frame_handler.GetVReg(2).Set(3);
666 
667     uint8_t call_insn[] = {static_cast<uint8_t>(Opcode::CALL_V4_V4_V4_V4_ID16), 0x10, 0x02, 0, 0, 0, 0};
668     g_call_result = "";
669     InterpreterToCompiledCodeBridge(call_insn, frame, &callee, thread_);
670     ASSERT_EQ(g_call_result, PrintFunc("void", "Void3Int", &callee, 1, 2, 3));
671 
672     // callee(acc, v1, v2)
673     uint8_t call_acc_insn[] = {static_cast<uint8_t>(Opcode::CALL_ACC_V4_V4_V4_IMM4_ID16), 0x21, 0x00, 0, 0};
674     g_call_result = "";
675     InterpreterToCompiledCodeBridge(call_acc_insn, frame, &callee, thread_);
676     ASSERT_EQ(g_call_result, PrintFunc("void", "Void3Int", &callee, 0, 2, 3));
677 
678     uint8_t call_range_insn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
679     g_call_result = "";
680     InterpreterToCompiledCodeBridge(call_range_insn, frame, &callee, thread_);
681     ASSERT_EQ(g_call_result, PrintFunc("void", "Void3Int", &callee, 1, 2, 3));
682 
683     int64_t args[] = {1, 2, 3};
684     g_call_result = "";
685     InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
686     ASSERT_EQ(g_call_result, PrintFunc("void", "Void3Int", &callee, 1, 2, 3));
687 
688     FreeFrame(frame);
689 }
690 
Void2IntLongInt(Method * method,int32_t a0,int32_t a1,int64_t a2,int32_t a3)691 static void Void2IntLongInt(Method *method, int32_t a0, int32_t a1, int64_t a2, int32_t a3)
692 {
693     g_call_result = PrintFunc("void", __FUNCTION__, method, a0, a1, a2, a3);
694 }
695 
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke2IntLongInt)696 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke2IntLongInt)
697 {
698     uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I64, TypeId::I32});
699     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
700     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void2IntLongInt));
701     Frame *frame = CreateFrame(4, nullptr, nullptr);
702     auto frame_handler = StaticFrameHandler(frame);
703     frame_handler.GetVReg(0).Set(1);
704     frame_handler.GetVReg(1).Set(2);
705     frame_handler.GetVReg(2).Set(3);
706     frame_handler.GetVReg(3).Set(4);
707 
708     uint8_t call_insn[] = {static_cast<uint8_t>(Opcode::CALL_V4_V4_V4_V4_ID16), 0x10, 0x32, 0, 0, 0, 0};
709     g_call_result = "";
710     InterpreterToCompiledCodeBridge(call_insn, frame, &callee, thread_);
711     ASSERT_EQ(g_call_result, PrintFunc("void", "Void2IntLongInt", &callee, 1, 2, 3, 4));
712 
713     uint8_t call_range_insn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
714     g_call_result = "";
715     InterpreterToCompiledCodeBridge(call_range_insn, frame, &callee, thread_);
716     ASSERT_EQ(g_call_result, PrintFunc("void", "Void2IntLongInt", &callee, 1, 2, 3, 4));
717 
718     int64_t args[] = {1, 2, 3, 4};
719     g_call_result = "";
720     InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
721     ASSERT_EQ(g_call_result, PrintFunc("void", "Void2IntLongInt", &callee, 1, 2, 3, 4));
722 
723     frame_handler.GetVReg(2).Set(0);
724     frame_handler.GetAcc().SetValue(3);
725     uint8_t call_acc_insn[] = {static_cast<uint8_t>(Opcode::CALL_ACC_V4_V4_V4_IMM4_ID16), 0x10, 0x23, 0, 0, 0, 0};
726     g_call_result = "";
727     InterpreterToCompiledCodeBridge(call_acc_insn, frame, &callee, thread_);
728     ASSERT_EQ(g_call_result, PrintFunc("void", "Void2IntLongInt", &callee, 1, 2, 3, 4));
729 
730     FreeFrame(frame);
731 }
732 
VoidLong(Method * method,int64_t a0)733 static void VoidLong(Method *method, int64_t a0)
734 {
735     g_call_result = PrintFunc("void", __FUNCTION__, method, a0);
736 }
737 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeLong)738 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeLong)
739 {
740     uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I64});
741     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
742     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(VoidLong));
743     Frame *frame = CreateFrame(1, nullptr, nullptr);
744     auto frame_handler = StaticFrameHandler(frame);
745     frame_handler.GetVReg(0).Set(9);
746 
747     uint8_t call_insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
748     g_call_result = "";
749     InterpreterToCompiledCodeBridge(call_insn, frame, &callee, thread_);
750     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidLong", &callee, 9));
751 
752     uint8_t call_range_insn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
753     g_call_result = "";
754     InterpreterToCompiledCodeBridge(call_range_insn, frame, &callee, thread_);
755     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidLong", &callee, 9));
756 
757     int64_t args[] = {9};
758     g_call_result = "";
759     InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
760     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidLong", &callee, 9));
761 
762     FreeFrame(frame);
763 }
764 
VoidDouble(Method * method,double a0)765 static void VoidDouble(Method *method, double a0)
766 {
767     g_call_result = PrintFunc("void", __FUNCTION__, method, a0);
768 }
769 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeDouble)770 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeDouble)
771 {
772     uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::F64});
773     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
774     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(VoidDouble));
775     Frame *frame = CreateFrame(1, nullptr, nullptr);
776     auto frame_handler = StaticFrameHandler(frame);
777     frame_handler.GetVReg(0).Set(4.0);
778 
779     uint8_t call_insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x00, 0, 0, 0, 0};
780     g_call_result = "";
781     InterpreterToCompiledCodeBridge(call_insn, frame, &callee, thread_);
782     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidDouble", &callee, 4.0));
783 
784     uint8_t call_range_insn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
785     g_call_result = "";
786     InterpreterToCompiledCodeBridge(call_range_insn, frame, &callee, thread_);
787     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidDouble", &callee, 4.0));
788 
789     int64_t args[] = {bit_cast<int64_t>(4.0)};
790     g_call_result = "";
791     InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
792     ASSERT_EQ(g_call_result, PrintFunc("void", "VoidDouble", &callee, 4.0));
793 
794     FreeFrame(frame);
795 }
796 
Void4Int(Method * method,int32_t a0,int32_t a1,int32_t a2,int32_t a3)797 static void Void4Int(Method *method, int32_t a0, int32_t a1, int32_t a2, int32_t a3)
798 {
799     g_call_result = PrintFunc("void", __FUNCTION__, method, a0, a1, a2, a3);
800 }
801 
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke4Int)802 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke4Int)
803 {
804     uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32});
805     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
806     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void4Int));
807     Frame *frame = CreateFrame(4, nullptr, nullptr);
808     auto frame_handler = StaticFrameHandler(frame);
809     frame_handler.GetVReg(0).Set(1);
810     frame_handler.GetVReg(1).Set(2);
811     frame_handler.GetVReg(2).Set(3);
812     frame_handler.GetVReg(3).Set(4);
813 
814     uint8_t call_insn[] = {static_cast<uint8_t>(Opcode::CALL_V4_V4_V4_V4_ID16), 0x10, 0x32, 0, 0, 0, 0};
815     g_call_result = "";
816     InterpreterToCompiledCodeBridge(call_insn, frame, &callee, thread_);
817     ASSERT_EQ(g_call_result, PrintFunc("void", "Void4Int", &callee, 1, 2, 3, 4));
818 
819     uint8_t call_range_insn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
820     g_call_result = "";
821     InterpreterToCompiledCodeBridge(call_range_insn, frame, &callee, thread_);
822     ASSERT_EQ(g_call_result, PrintFunc("void", "Void4Int", &callee, 1, 2, 3, 4));
823 
824     int64_t args[] = {1, 2, 3, 4};
825     g_call_result = "";
826     InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
827     ASSERT_EQ(g_call_result, PrintFunc("void", "Void4Int", &callee, 1, 2, 3, 4));
828 
829     frame_handler.GetVReg(3).Set(0);
830     frame_handler.GetAcc().SetValue(4);
831     uint8_t call_acc_insn[] = {static_cast<uint8_t>(Opcode::CALL_ACC_V4_V4_V4_IMM4_ID16), 0x10, 0x32, 0, 0, 0, 0};
832     g_call_result = "";
833     InterpreterToCompiledCodeBridge(call_acc_insn, frame, &callee, thread_);
834     ASSERT_EQ(g_call_result, PrintFunc("void", "Void4Int", &callee, 1, 2, 3, 4));
835 
836     FreeFrame(frame);
837 }
838 
Void2Long(Method * method,int64_t a0,int64_t a1)839 static void Void2Long(Method *method, int64_t a0, int64_t a1)
840 {
841     g_call_result = PrintFunc("void", __FUNCTION__, method, a0, a1);
842 }
843 
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke2Long)844 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke2Long)
845 {
846     uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I64, TypeId::I64});
847     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
848     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void2Long));
849     Frame *frame = CreateFrame(2, nullptr, nullptr);
850     auto frame_handler = StaticFrameHandler(frame);
851     frame_handler.GetVReg(0).Set(3);
852     frame_handler.GetVReg(1).Set(9);
853 
854     uint8_t call_insn[] = {static_cast<uint8_t>(Opcode::CALL_SHORT_V4_V4_ID16), 0x10, 0, 0, 0, 0};
855     g_call_result = "";
856     InterpreterToCompiledCodeBridge(call_insn, frame, &callee, thread_);
857     ASSERT_EQ(g_call_result, PrintFunc("void", "Void2Long", &callee, 3, 9));
858 
859     uint8_t call_range_insn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
860     g_call_result = "";
861     InterpreterToCompiledCodeBridge(call_range_insn, frame, &callee, thread_);
862     ASSERT_EQ(g_call_result, PrintFunc("void", "Void2Long", &callee, 3, 9));
863 
864     int64_t args[] = {3, 9};
865     g_call_result = "";
866     InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
867     ASSERT_EQ(g_call_result, PrintFunc("void", "Void2Long", &callee, 3, 9));
868 
869     FreeFrame(frame);
870 }
871 
Void4IntDouble(Method * method,int32_t a0,int32_t a1,int32_t a2,int32_t a3,double a4)872 static void Void4IntDouble(Method *method, int32_t a0, int32_t a1, int32_t a2, int32_t a3, double a4)
873 {
874     g_call_result = PrintFunc("void", __FUNCTION__, method, a0, a1, a2, a3, a4);
875 }
876 
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke4IntDouble)877 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke4IntDouble)
878 {
879     uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::F64});
880     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
881     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void4IntDouble));
882     Frame *frame = CreateFrame(5, nullptr, nullptr);
883     auto frame_handler = StaticFrameHandler(frame);
884     frame_handler.GetVReg(0).Set(1);
885     frame_handler.GetVReg(1).Set(2);
886     frame_handler.GetVReg(2).Set(3);
887     frame_handler.GetVReg(3).Set(4);
888     frame_handler.GetVReg(4).Set(5.0);
889 
890     uint8_t call_range_insn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
891     g_call_result = "";
892     InterpreterToCompiledCodeBridge(call_range_insn, frame, &callee, thread_);
893     ASSERT_EQ(g_call_result, PrintFunc("void", "Void4IntDouble", &callee, 1, 2, 3, 4, 5.0));
894 
895     int64_t args[] = {1, 2, 3, 4, bit_cast<int64_t>(5.0)};
896     g_call_result = "";
897     InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
898     ASSERT_EQ(g_call_result, PrintFunc("void", "Void4IntDouble", &callee, 1, 2, 3, 4, 5.0));
899 
900     FreeFrame(frame);
901 }
902 
903 // 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)904 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)
905 {
906     g_call_result = PrintFunc("void", __FUNCTION__, method, a0, a1, a2, a3, a4, a5, a6);
907 }
908 
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke7Int)909 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke7Int)
910 {
911     uint16_t *shorty = MakeShorty(
912         {TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32});
913     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
914     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void7Int));
915     Frame *frame = CreateFrame(7, nullptr, nullptr);
916     auto frame_handler = StaticFrameHandler(frame);
917     frame_handler.GetVReg(0).Set(1);
918     frame_handler.GetVReg(1).Set(2);
919     frame_handler.GetVReg(2).Set(3);
920     frame_handler.GetVReg(3).Set(4);
921     frame_handler.GetVReg(4).Set(5);
922     frame_handler.GetVReg(5).Set(6);
923     frame_handler.GetVReg(6).Set(7);
924 
925     uint8_t call_range_insn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
926     g_call_result = "";
927     InterpreterToCompiledCodeBridge(call_range_insn, frame, &callee, thread_);
928     ASSERT_EQ(g_call_result, PrintFunc("void", "Void7Int", &callee, 1, 2, 3, 4, 5, 6, 7));
929 
930     int64_t args[] = {1, 2, 3, 4, 5, 6, 7};
931     g_call_result = "";
932     InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
933     ASSERT_EQ(g_call_result, PrintFunc("void", "Void7Int", &callee, 1, 2, 3, 4, 5, 6, 7));
934 
935     FreeFrame(frame);
936 }
937 
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)938 static void Void7Int8Double(Method *method, int32_t a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5,
939                             int32_t a6, double d0, double d1, double d2, double d3, double d4, double d5, double d6,
940                             double d7)
941 {
942     g_call_result = PrintFunc("void", __FUNCTION__, method, a0, a1, a2, a3, a4, a5, a6, d0, d1, d2, d3, d4, d5, d6, d7);
943 }
944 
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke7Int8Double)945 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke7Int8Double)
946 {
947     uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32,
948                                    TypeId::I32, TypeId::I32, TypeId::F64, TypeId::F64, TypeId::F64, TypeId::F64,
949                                    TypeId::F64, TypeId::F64, TypeId::F64, TypeId::F64});
950     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
951     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void7Int8Double));
952     Frame *frame = CreateFrame(15, nullptr, nullptr);
953     auto frame_handler = StaticFrameHandler(frame);
954     frame_handler.GetVReg(0).Set(1);
955     frame_handler.GetVReg(1).Set(2);
956     frame_handler.GetVReg(2).Set(3);
957     frame_handler.GetVReg(3).Set(4);
958     frame_handler.GetVReg(4).Set(5);
959     frame_handler.GetVReg(5).Set(6);
960     frame_handler.GetVReg(6).Set(7);
961     frame_handler.GetVReg(7).Set(8.0);
962     frame_handler.GetVReg(8).Set(9.0);
963     frame_handler.GetVReg(9).Set(10.0);
964     frame_handler.GetVReg(10).Set(11.0);
965     frame_handler.GetVReg(11).Set(12.0);
966     frame_handler.GetVReg(12).Set(13.0);
967     frame_handler.GetVReg(13).Set(14.0);
968     frame_handler.GetVReg(14).Set(15.0);
969 
970     uint8_t call_range_insn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
971     g_call_result = "";
972     InterpreterToCompiledCodeBridge(call_range_insn, frame, &callee, thread_);
973     ASSERT_EQ(g_call_result, PrintFunc("void", "Void7Int8Double", &callee, 1, 2, 3, 4, 5, 6, 7, 8.0, 9.0, 10.0, 11.0,
974                                        12.0, 13.0, 14.0, 15.0));
975 
976     int64_t args[] = {1,
977                       2,
978                       3,
979                       4,
980                       5,
981                       6,
982                       7,
983                       bit_cast<int64_t>(8.0),
984                       bit_cast<int64_t>(9.0),
985                       bit_cast<int64_t>(10.0),
986                       bit_cast<int64_t>(11.0),
987                       bit_cast<int64_t>(12.0),
988                       bit_cast<int64_t>(13.0),
989                       bit_cast<int64_t>(14.0),
990                       bit_cast<int64_t>(15.0)};
991     g_call_result = "";
992     InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
993     ASSERT_EQ(g_call_result, PrintFunc("void", "Void7Int8Double", &callee, 1, 2, 3, 4, 5, 6, 7, 8.0, 9.0, 10.0, 11.0,
994                                        12.0, 13.0, 14.0, 15.0));
995 
996     FreeFrame(frame);
997 }
998 
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)999 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,
1000                      int32_t a7)
1001 {
1002     g_call_result = PrintFunc("void", __FUNCTION__, method, a0, a1, a2, a3, a4, a5, a6, a7);
1003 }
1004 
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke8Int)1005 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke8Int)
1006 {
1007     uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32,
1008                                    TypeId::I32, TypeId::I32, TypeId::I32});
1009     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
1010     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void8Int));
1011     Frame *frame = CreateFrame(8, nullptr, nullptr);
1012     auto frame_handler = StaticFrameHandler(frame);
1013     frame_handler.GetVReg(0).Set(1);
1014     frame_handler.GetVReg(1).Set(2);
1015     frame_handler.GetVReg(2).Set(3);
1016     frame_handler.GetVReg(3).Set(4);
1017     frame_handler.GetVReg(4).Set(5);
1018     frame_handler.GetVReg(5).Set(6);
1019     frame_handler.GetVReg(6).Set(7);
1020     frame_handler.GetVReg(7).Set(8);
1021 
1022     uint8_t call_range_insn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
1023     g_call_result = "";
1024     InterpreterToCompiledCodeBridge(call_range_insn, frame, &callee, thread_);
1025     ASSERT_EQ(g_call_result, PrintFunc("void", "Void8Int", &callee, 1, 2, 3, 4, 5, 6, 7, 8));
1026 
1027     int64_t args[] = {1, 2, 3, 4, 5, 6, 7, 8};
1028     g_call_result = "";
1029     InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
1030     ASSERT_EQ(g_call_result, PrintFunc("void", "Void8Int", &callee, 1, 2, 3, 4, 5, 6, 7, 8));
1031 
1032     FreeFrame(frame);
1033 }
1034 
Void6IntVReg(Method * method,int32_t a0,int32_t a1,int32_t a2,int32_t a3,int32_t a4,int32_t a5,int64_t value)1035 static void Void6IntVReg(Method *method, int32_t a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5,
1036                          int64_t value)
1037 {
1038     g_call_result = PrintFunc("void", __FUNCTION__, method, a0, a1, a2, a3, a4, a5, value);
1039 }
1040 
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke6IntVReg)1041 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke6IntVReg)
1042 {
1043     uint16_t *shorty = MakeShorty(
1044         {TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::TAGGED});
1045     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
1046     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void6IntVReg));
1047     Frame *frame = CreateFrame(8, nullptr, nullptr);
1048     auto frame_handler = StaticFrameHandler(frame);
1049     frame_handler.GetVReg(0).Set(1);
1050     frame_handler.GetVReg(1).Set(2);
1051     frame_handler.GetVReg(2).Set(3);
1052     frame_handler.GetVReg(3).Set(4);
1053     frame_handler.GetVReg(4).Set(5);
1054     frame_handler.GetVReg(5).Set(6);
1055     frame_handler.GetVReg(6).Set(7);
1056 
1057     uint8_t call_range_insn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
1058     g_call_result = "";
1059     InterpreterToCompiledCodeBridge(call_range_insn, frame, &callee, thread_);
1060     ASSERT_EQ(g_call_result, PrintFunc("void", "Void6IntVReg", &callee, 1, 2, 3, 4, 5, 6, 7));
1061 
1062     int64_t args[] = {1, 2, 3, 4, 5, 6, 7, 8};
1063     g_call_result = "";
1064     InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
1065     ASSERT_EQ(g_call_result, PrintFunc("void", "Void6IntVReg", &callee, 1, 2, 3, 4, 5, 6, 7));
1066 
1067     FreeFrame(frame);
1068 }
1069 
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)1070 static void Void7IntVReg(Method *method, int32_t a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5,
1071                          int32_t a6, int64_t value)
1072 {
1073     g_call_result = PrintFunc("void", __FUNCTION__, method, a0, a1, a2, a3, a4, a5, a6, value);
1074 }
1075 
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke7IntVReg)1076 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke7IntVReg)
1077 {
1078     uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32,
1079                                    TypeId::I32, TypeId::I32, TypeId::TAGGED});
1080     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
1081     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void7IntVReg));
1082     Frame *frame = CreateFrame(8, nullptr, nullptr);
1083     auto frame_handler = StaticFrameHandler(frame);
1084     frame_handler.GetVReg(0).Set(1);
1085     frame_handler.GetVReg(1).Set(2);
1086     frame_handler.GetVReg(2).Set(3);
1087     frame_handler.GetVReg(3).Set(4);
1088     frame_handler.GetVReg(4).Set(5);
1089     frame_handler.GetVReg(5).Set(6);
1090     frame_handler.GetVReg(6).Set(7);
1091     frame_handler.GetVReg(7).Set(8);
1092 
1093     uint8_t call_range_insn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
1094     g_call_result = "";
1095     InterpreterToCompiledCodeBridge(call_range_insn, frame, &callee, thread_);
1096     ASSERT_EQ(g_call_result, PrintFunc("void", "Void7IntVReg", &callee, 1, 2, 3, 4, 5, 6, 7, 8));
1097 
1098     int64_t args[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
1099     g_call_result = "";
1100     InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
1101     ASSERT_EQ(g_call_result, PrintFunc("void", "Void7IntVReg", &callee, 1, 2, 3, 4, 5, 6, 7, 8));
1102 
1103     FreeFrame(frame);
1104 }
1105 
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)1106 static void Void8Int9Double(Method *method, int32_t a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5,
1107                             int32_t a6, int32_t a7, double d0, double d1, double d2, double d3, double d4, double d5,
1108                             double d6, double d7, double d8)
1109 {
1110     g_call_result =
1111         PrintFunc("void", __FUNCTION__, method, a0, a1, a2, a3, a4, a5, a6, a7, d0, d1, d2, d3, d4, d5, d6, d7, d8);
1112 }
1113 
TEST_F(InterpreterToCompiledCodeBridgeTest,Invoke8Int9Double)1114 TEST_F(InterpreterToCompiledCodeBridgeTest, Invoke8Int9Double)
1115 {
1116     uint16_t *shorty = MakeShorty({TypeId::VOID, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32, TypeId::I32,
1117                                    TypeId::I32, TypeId::I32, TypeId::I32, TypeId::F64, TypeId::F64, TypeId::F64,
1118                                    TypeId::F64, TypeId::F64, TypeId::F64, TypeId::F64, TypeId::F64, TypeId::F64});
1119     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, shorty);
1120     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(Void8Int9Double));
1121     Frame *frame = CreateFrame(17, nullptr, nullptr);
1122     auto frame_handler = StaticFrameHandler(frame);
1123     frame_handler.GetVReg(0).Set(1);
1124     frame_handler.GetVReg(1).Set(2);
1125     frame_handler.GetVReg(2).Set(3);
1126     frame_handler.GetVReg(3).Set(4);
1127     frame_handler.GetVReg(4).Set(5);
1128     frame_handler.GetVReg(5).Set(6);
1129     frame_handler.GetVReg(6).Set(7);
1130     frame_handler.GetVReg(7).Set(8);
1131     frame_handler.GetVReg(8).Set(9.0);
1132     frame_handler.GetVReg(9).Set(10.0);
1133     frame_handler.GetVReg(10).Set(11.0);
1134     frame_handler.GetVReg(11).Set(12.0);
1135     frame_handler.GetVReg(12).Set(13.0);
1136     frame_handler.GetVReg(13).Set(14.0);
1137     frame_handler.GetVReg(14).Set(15.0);
1138     frame_handler.GetVReg(15).Set(16.0);
1139     frame_handler.GetVReg(16).Set(17.0);
1140 
1141     uint8_t call_range_insn[] = {static_cast<uint8_t>(Opcode::CALL_RANGE_V8_ID16), 0x00, 0, 0, 0, 0};
1142     g_call_result = "";
1143     InterpreterToCompiledCodeBridge(call_range_insn, frame, &callee, thread_);
1144     ASSERT_EQ(g_call_result, PrintFunc("void", "Void8Int9Double", &callee, 1, 2, 3, 4, 5, 6, 7, 8, 9.0, 10.0, 11.0,
1145                                        12.0, 13.0, 14.0, 15.0, 16.0, 17.0));
1146 
1147     int64_t args[] = {1,
1148                       2,
1149                       3,
1150                       4,
1151                       5,
1152                       6,
1153                       7,
1154                       8,
1155                       bit_cast<int64_t>(9.0),
1156                       bit_cast<int64_t>(10.0),
1157                       bit_cast<int64_t>(11.0),
1158                       bit_cast<int64_t>(12.0),
1159                       bit_cast<int64_t>(13.0),
1160                       bit_cast<int64_t>(14.0),
1161                       bit_cast<int64_t>(15.0),
1162                       bit_cast<int64_t>(16.0),
1163                       bit_cast<int64_t>(17.0)};
1164     g_call_result = "";
1165     InvokeCompiledCodeWithArgArray(args, frame, &callee, thread_);
1166     ASSERT_EQ(g_call_result, PrintFunc("void", "Void8Int9Double", &callee, 1, 2, 3, 4, 5, 6, 7, 8, 9.0, 10.0, 11.0,
1167                                        12.0, 13.0, 14.0, 15.0, 16.0, 17.0));
1168 
1169     FreeFrame(frame);
1170 }
1171 
1172 #if !defined(PANDA_TARGET_ARM32) && !defined(PANDA_TARGET_X86)
NoArgDyn(Method * method,uint32_t num_args)1173 static TaggedValue NoArgDyn(Method *method, uint32_t num_args)
1174 {
1175     g_call_result = PrintFunc("any", __FUNCTION__, method, num_args);
1176     return TaggedValue(77.0);
1177 }
1178 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeNoArgDyn)1179 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeNoArgDyn)
1180 {
1181     Frame *frame = CreateFrame<true>(0, nullptr, nullptr);
1182     auto frame_handler = DynamicFrameHandler(frame);
1183     TaggedValue value_out(77.0);
1184 
1185     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, nullptr);
1186     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(NoArgDyn));
1187 
1188     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALLI_DYN_SHORT_IMM4_V4_V4_V4), 0x00, 0x00};
1189     g_call_result = "";
1190     frame_handler.GetAcc().SetValue(0);
1191     InterpreterToCompiledCodeBridgeDyn(insn, frame, &callee, thread_);
1192     ASSERT_EQ(g_call_result, PrintFunc("any", "NoArgDyn", &callee, 0));
1193     ASSERT_EQ(frame_handler.GetAcc().GetValue(), value_out.GetRawData());
1194 
1195     uint8_t range_insn[] = {static_cast<uint8_t>(Opcode::CALLI_DYN_RANGE_IMM16_V16), 0x00, 0x00, 0x00, 0x00};
1196     g_call_result = "";
1197     frame_handler.GetAcc().SetValue(0);
1198     InterpreterToCompiledCodeBridgeDyn(range_insn, frame, &callee, thread_);
1199     ASSERT_EQ(g_call_result, PrintFunc("any", "NoArgDyn", &callee, 0));
1200     ASSERT_EQ(frame_handler.GetAcc().GetValue(), value_out.GetRawData());
1201 
1202     g_call_result = "";
1203     uint64_t res = InvokeCompiledCodeWithArgArrayDyn(nullptr, 0, frame, &callee, thread_);
1204     ASSERT_EQ(g_call_result, PrintFunc("any", "NoArgDyn", &callee, 0));
1205     ASSERT_EQ(res, value_out.GetRawData());
1206 
1207     FreeFrame(frame);
1208 }
1209 
OneArgDyn(Method * method,uint32_t num_args,int64_t arg0)1210 static TaggedValue OneArgDyn(Method *method, uint32_t num_args, int64_t arg0)
1211 {
1212     g_call_result = PrintFunc("any", __FUNCTION__, method, num_args, arg0);
1213     return TaggedValue(24.0);
1214 }
1215 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeOneArgDyn)1216 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeOneArgDyn)
1217 {
1218     Frame *frame = CreateFrame<true>(1, nullptr, nullptr);
1219     auto frame_handler = DynamicFrameHandler(frame);
1220     TaggedValue value_in0(42.0);
1221     TaggedValue value_out(24.0);
1222     frame_handler.GetVReg(0).SetValue(value_in0.GetRawData());
1223 
1224     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, nullptr);
1225     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(OneArgDyn));
1226 
1227     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALLI_DYN_SHORT_IMM4_V4_V4_V4), 0x01, 0x00};
1228     g_call_result = "";
1229     frame_handler.GetAcc().SetValue(0);
1230     InterpreterToCompiledCodeBridgeDyn(insn, frame, &callee, thread_);
1231     ASSERT_EQ(g_call_result, PrintFunc("any", "OneArgDyn", &callee, 1, value_in0.GetRawData()));
1232     ASSERT_EQ(frame_handler.GetAcc().GetValue(), value_out.GetRawData());
1233 
1234     uint8_t range_insn[] = {static_cast<uint8_t>(Opcode::CALLI_DYN_RANGE_IMM16_V16), 0x01, 0x00, 0x00, 0x00};
1235     g_call_result = "";
1236     frame_handler.GetAcc().SetValue(0);
1237     InterpreterToCompiledCodeBridgeDyn(range_insn, frame, &callee, thread_);
1238     ASSERT_EQ(g_call_result, PrintFunc("any", "OneArgDyn", &callee, 1, value_in0.GetRawData()));
1239     ASSERT_EQ(frame_handler.GetAcc().GetValue(), value_out.GetRawData());
1240 
1241     uint64_t args[] = {value_in0.GetRawData()};
1242     g_call_result = "";
1243     uint64_t res = InvokeCompiledCodeWithArgArrayDyn(args, 1, frame, &callee, thread_);
1244     ASSERT_EQ(g_call_result, PrintFunc("any", "OneArgDyn", &callee, 1, value_in0.GetRawData()));
1245     ASSERT_EQ(res, value_out.GetRawData());
1246 
1247     FreeFrame(frame);
1248 }
1249 
OneVarArgDyn(Method * method,uint32_t num_args,...)1250 static TaggedValue OneVarArgDyn(Method *method, uint32_t num_args, ...)
1251 {
1252     if (num_args != 1) {
1253         g_call_result = PrintFunc("any", __FUNCTION__, method, num_args);
1254         return TaggedValue(1.0);
1255     }
1256 
1257     va_list args;
1258     va_start(args, num_args);
1259     int64_t arg0 = va_arg(args, int64_t);
1260     g_call_result = PrintFunc("any", __FUNCTION__, method, num_args, arg0);
1261     va_end(args);
1262     return TaggedValue(-1.0);
1263 }
1264 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeOneVarArgDyn)1265 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeOneVarArgDyn)
1266 {
1267     Frame *frame = CreateFrame<true>(1, nullptr, nullptr);
1268     auto frame_handler = DynamicFrameHandler(frame);
1269     TaggedValue value_in0(42.0);
1270     TaggedValue value_out(-1.0);
1271     frame_handler.GetVReg(0).SetValue(value_in0.GetRawData());
1272 
1273     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, nullptr);
1274     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(OneVarArgDyn));
1275 
1276     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALLI_DYN_SHORT_IMM4_V4_V4_V4), 0x01, 0x00};
1277     g_call_result = "";
1278     frame_handler.GetAcc().SetValue(0);
1279     InterpreterToCompiledCodeBridgeDyn(insn, frame, &callee, thread_);
1280     ASSERT_EQ(g_call_result, PrintFunc("any", "OneVarArgDyn", &callee, 1, value_in0.GetRawData()));
1281     ASSERT_EQ(frame_handler.GetAcc().GetValue(), value_out.GetRawData());
1282 
1283     uint64_t args[] = {value_in0.GetRawData()};
1284     g_call_result = "";
1285     uint64_t res = InvokeCompiledCodeWithArgArrayDyn(args, 1, frame, &callee, thread_);
1286     ASSERT_EQ(g_call_result, PrintFunc("any", "OneVarArgDyn", &callee, 1, value_in0.GetRawData()));
1287     ASSERT_EQ(res, value_out.GetRawData());
1288 
1289     FreeFrame(frame);
1290 }
1291 
TwoArgDyn(Method * method,uint32_t num_args,int64_t arg0,int64_t arg1)1292 static TaggedValue TwoArgDyn(Method *method, uint32_t num_args, int64_t arg0, int64_t arg1)
1293 {
1294     g_call_result = PrintFunc("any", __FUNCTION__, method, num_args, arg0, arg1);
1295     return TaggedValue(64.0);
1296 }
1297 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeTwoArgDyn)1298 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeTwoArgDyn)
1299 {
1300     Frame *frame = CreateFrame<true>(2, nullptr, nullptr);
1301     auto frame_handler = DynamicFrameHandler(frame);
1302     TaggedValue value_in0(16.0);
1303     TaggedValue value_in1(32.0);
1304     TaggedValue value_out(64.0);
1305     frame_handler.GetVReg(0).SetValue(value_in0.GetRawData());
1306     frame_handler.GetVReg(1).SetValue(value_in1.GetRawData());
1307 
1308     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, nullptr);
1309     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(TwoArgDyn));
1310 
1311     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALLI_DYN_SHORT_IMM4_V4_V4_V4), 0x02, 0x01};
1312     g_call_result = "";
1313     frame_handler.GetAcc().SetValue(0);
1314     InterpreterToCompiledCodeBridgeDyn(insn, frame, &callee, thread_);
1315     ASSERT_EQ(g_call_result, PrintFunc("any", "TwoArgDyn", &callee, 2, value_in0.GetRawData(), value_in1.GetRawData()));
1316     ASSERT_EQ(frame_handler.GetAcc().GetValue(), value_out.GetRawData());
1317 
1318     uint8_t range_insn[] = {static_cast<uint8_t>(Opcode::CALLI_DYN_RANGE_IMM16_V16), 0x02, 0x00, 0x00, 0x00};
1319     g_call_result = "";
1320     frame_handler.GetAcc().SetValue(0);
1321     InterpreterToCompiledCodeBridgeDyn(range_insn, frame, &callee, thread_);
1322     ASSERT_EQ(g_call_result, PrintFunc("any", "TwoArgDyn", &callee, 2, value_in0.GetRawData(), value_in1.GetRawData()));
1323     ASSERT_EQ(frame_handler.GetAcc().GetValue(), value_out.GetRawData());
1324 
1325     uint64_t args[] = {value_in0.GetRawData(), value_in1.GetRawData()};
1326     g_call_result = "";
1327     uint64_t res = InvokeCompiledCodeWithArgArrayDyn(args, 2, frame, &callee, thread_);
1328     ASSERT_EQ(g_call_result, PrintFunc("any", "TwoArgDyn", &callee, 2, value_in0.GetRawData(), value_in1.GetRawData()));
1329     ASSERT_EQ(res, value_out.GetRawData());
1330 
1331     FreeFrame(frame);
1332 }
1333 
TwoVarArgDyn(Method * method,uint32_t num_args,...)1334 static TaggedValue TwoVarArgDyn(Method *method, uint32_t num_args, ...)
1335 {
1336     if (num_args != 2) {
1337         g_call_result = PrintFunc("any", __FUNCTION__, method, num_args);
1338         return TaggedValue(2.0);
1339     }
1340 
1341     va_list args;
1342     va_start(args, num_args);
1343     int64_t arg0 = va_arg(args, int64_t);
1344     int64_t arg1 = va_arg(args, int64_t);
1345     g_call_result = PrintFunc("any", __FUNCTION__, method, num_args, arg0, arg1);
1346     va_end(args);
1347     return TaggedValue(-2.0);
1348 }
1349 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeTwoVarArgDyn)1350 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeTwoVarArgDyn)
1351 {
1352     Frame *frame = CreateFrame<true>(2, nullptr, nullptr);
1353     auto frame_handler = DynamicFrameHandler(frame);
1354     TaggedValue value_in0(19.0);
1355     TaggedValue value_in1(84.0);
1356     TaggedValue value_out(-2.0);
1357     frame_handler.GetVReg(0).SetValue(value_in0.GetRawData());
1358     frame_handler.GetVReg(1).SetValue(value_in1.GetRawData());
1359 
1360     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, nullptr);
1361     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(TwoVarArgDyn));
1362 
1363     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALLI_DYN_SHORT_IMM4_V4_V4_V4), 0x02, 0x01};
1364     g_call_result = "";
1365     frame_handler.GetAcc().SetValue(0);
1366     InterpreterToCompiledCodeBridgeDyn(insn, frame, &callee, thread_);
1367     ASSERT_EQ(g_call_result,
1368               PrintFunc("any", "TwoVarArgDyn", &callee, 2, value_in0.GetRawData(), value_in1.GetRawData()));
1369     ASSERT_EQ(frame_handler.GetAcc().GetValue(), value_out.GetRawData());
1370 
1371     uint64_t args[] = {value_in0.GetRawData(), value_in1.GetRawData()};
1372     g_call_result = "";
1373     uint64_t res = InvokeCompiledCodeWithArgArrayDyn(args, 2, frame, &callee, thread_);
1374     ASSERT_EQ(g_call_result,
1375               PrintFunc("any", "TwoVarArgDyn", &callee, 2, value_in0.GetRawData(), value_in1.GetRawData()));
1376     ASSERT_EQ(res, value_out.GetRawData());
1377 
1378     FreeFrame(frame);
1379 }
1380 
ThreeArgDyn(Method * method,uint32_t num_args,int64_t arg0,int64_t arg1,int64_t arg2)1381 static TaggedValue ThreeArgDyn(Method *method, uint32_t num_args, int64_t arg0, int64_t arg1, int64_t arg2)
1382 {
1383     g_call_result = PrintFunc("any", __FUNCTION__, method, num_args, arg0, arg1, arg2);
1384     return TaggedValue(1961.0);
1385 }
1386 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeThreeArgDyn)1387 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeThreeArgDyn)
1388 {
1389     Frame *frame = CreateFrame<true>(3, nullptr, nullptr);
1390     auto frame_handler = DynamicFrameHandler(frame);
1391     TaggedValue value_in0(1147.0);
1392     TaggedValue value_in1(1703.0);
1393     TaggedValue value_in2(1938.0);
1394     TaggedValue value_out(1961.0);
1395     frame_handler.GetVReg(0).SetValue(value_in0.GetRawData());
1396     frame_handler.GetVReg(1).SetValue(value_in1.GetRawData());
1397     frame_handler.GetVReg(2).SetValue(value_in2.GetRawData());
1398 
1399     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, nullptr);
1400     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(ThreeArgDyn));
1401 
1402     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALLI_DYN_IMM4_V4_V4_V4_V4_V4), 0x03, 0x21, 0x00};
1403     g_call_result = "";
1404     frame_handler.GetAcc().SetValue(0);
1405     InterpreterToCompiledCodeBridgeDyn(insn, frame, &callee, thread_);
1406     ASSERT_EQ(g_call_result, PrintFunc("any", "ThreeArgDyn", &callee, 3, value_in0.GetRawData(), value_in1.GetRawData(),
1407                                        value_in2.GetRawData()));
1408     ASSERT_EQ(frame_handler.GetAcc().GetValue(), value_out.GetRawData());
1409 
1410     uint8_t range_insn[] = {static_cast<uint8_t>(Opcode::CALLI_DYN_RANGE_IMM16_V16), 0x03, 0x00, 0x00, 0x00};
1411     g_call_result = "";
1412     frame_handler.GetAcc().SetValue(0);
1413     InterpreterToCompiledCodeBridgeDyn(range_insn, frame, &callee, thread_);
1414     ASSERT_EQ(g_call_result, PrintFunc("any", "ThreeArgDyn", &callee, 3, value_in0.GetRawData(), value_in1.GetRawData(),
1415                                        value_in2.GetRawData()));
1416     ASSERT_EQ(frame_handler.GetAcc().GetValue(), value_out.GetRawData());
1417 
1418     uint64_t args[] = {value_in0.GetRawData(), value_in1.GetRawData(), value_in2.GetRawData()};
1419     g_call_result = "";
1420     uint64_t res = InvokeCompiledCodeWithArgArrayDyn(args, 3, frame, &callee, thread_);
1421     ASSERT_EQ(g_call_result, PrintFunc("any", "ThreeArgDyn", &callee, 3, value_in0.GetRawData(), value_in1.GetRawData(),
1422                                        value_in2.GetRawData()));
1423     ASSERT_EQ(res, value_out.GetRawData());
1424 
1425     FreeFrame(frame);
1426 }
1427 
ThreeVarArgDyn(Method * method,uint32_t num_args,...)1428 static TaggedValue ThreeVarArgDyn(Method *method, uint32_t num_args, ...)
1429 {
1430     if (num_args != 3) {
1431         g_call_result = PrintFunc("any", __FUNCTION__, method, num_args);
1432         return TaggedValue(3.0);
1433     }
1434 
1435     va_list args;
1436     va_start(args, num_args);
1437     int64_t arg0 = va_arg(args, int64_t);
1438     int64_t arg1 = va_arg(args, int64_t);
1439     int64_t arg2 = va_arg(args, int64_t);
1440     g_call_result = PrintFunc("any", __FUNCTION__, method, num_args, arg0, arg1, arg2);
1441     va_end(args);
1442     return TaggedValue(-3.0);
1443 }
1444 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeThreeVarArgDyn)1445 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeThreeVarArgDyn)
1446 {
1447     Frame *frame = CreateFrame<true>(3, nullptr, nullptr);
1448     auto frame_handler = DynamicFrameHandler(frame);
1449     TaggedValue value_in0(1147.0);
1450     TaggedValue value_in1(1703.0);
1451     TaggedValue value_in2(1938.0);
1452     TaggedValue value_out(-3.0);
1453     frame_handler.GetVReg(0).SetValue(value_in0.GetRawData());
1454     frame_handler.GetVReg(1).SetValue(value_in1.GetRawData());
1455     frame_handler.GetVReg(2).SetValue(value_in2.GetRawData());
1456 
1457     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, nullptr);
1458     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(ThreeVarArgDyn));
1459 
1460     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALLI_DYN_IMM4_V4_V4_V4_V4_V4), 0x03, 0x21, 0x00};
1461     g_call_result = "";
1462     frame_handler.GetAcc().SetValue(0);
1463     InterpreterToCompiledCodeBridgeDyn(insn, frame, &callee, thread_);
1464     ASSERT_EQ(g_call_result, PrintFunc("any", "ThreeVarArgDyn", &callee, 3, value_in0.GetRawData(),
1465                                        value_in1.GetRawData(), value_in2.GetRawData()));
1466     ASSERT_EQ(frame_handler.GetAcc().GetValue(), value_out.GetRawData());
1467 
1468     uint64_t args[] = {value_in0.GetRawData(), value_in1.GetRawData(), value_in2.GetRawData()};
1469     g_call_result = "";
1470     uint64_t res = InvokeCompiledCodeWithArgArrayDyn(args, 3, frame, &callee, thread_);
1471     ASSERT_EQ(g_call_result, PrintFunc("any", "ThreeVarArgDyn", &callee, 3, value_in0.GetRawData(),
1472                                        value_in1.GetRawData(), value_in2.GetRawData()));
1473     ASSERT_EQ(res, value_out.GetRawData());
1474 
1475     FreeFrame(frame);
1476 }
1477 
FourArgDyn(Method * method,uint32_t num_args,int64_t arg0,int64_t arg1,int64_t arg2,int64_t arg3)1478 static TaggedValue FourArgDyn(Method *method, uint32_t num_args, int64_t arg0, int64_t arg1, int64_t arg2, int64_t arg3)
1479 {
1480     g_call_result = PrintFunc("any", __FUNCTION__, method, num_args, arg0, arg1, arg2, arg3);
1481     return TaggedValue(3.14);
1482 }
1483 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeFourArgDyn)1484 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeFourArgDyn)
1485 {
1486     Frame *frame = CreateFrame<true>(4, nullptr, nullptr);
1487     auto frame_handler = DynamicFrameHandler(frame);
1488     TaggedValue value_in0(1.0);
1489     TaggedValue value_in1(2.0);
1490     TaggedValue value_in2(3.0);
1491     TaggedValue value_in3(4.0);
1492     TaggedValue value_out(3.14);
1493     frame_handler.GetVReg(0).SetValue(value_in0.GetRawData());
1494     frame_handler.GetVReg(1).SetValue(value_in1.GetRawData());
1495     frame_handler.GetVReg(2).SetValue(value_in2.GetRawData());
1496     frame_handler.GetVReg(3).SetValue(value_in3.GetRawData());
1497 
1498     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, nullptr);
1499     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(FourArgDyn));
1500 
1501     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALLI_DYN_IMM4_V4_V4_V4_V4_V4), 0x04, 0x21, 0x03};
1502     g_call_result = "";
1503     frame_handler.GetAcc().SetValue(0);
1504     InterpreterToCompiledCodeBridgeDyn(insn, frame, &callee, thread_);
1505     ASSERT_EQ(g_call_result, PrintFunc("any", "FourArgDyn", &callee, 4, value_in0.GetRawData(), value_in1.GetRawData(),
1506                                        value_in2.GetRawData(), value_in3.GetRawData()));
1507     ASSERT_EQ(frame_handler.GetAcc().GetValue(), value_out.GetRawData());
1508 
1509     uint8_t range_insn[] = {static_cast<uint8_t>(Opcode::CALLI_DYN_RANGE_IMM16_V16), 0x04, 0x00, 0x00, 0x00};
1510     g_call_result = "";
1511     frame_handler.GetAcc().SetValue(0);
1512     InterpreterToCompiledCodeBridgeDyn(range_insn, frame, &callee, thread_);
1513     ASSERT_EQ(g_call_result, PrintFunc("any", "FourArgDyn", &callee, 4, value_in0.GetRawData(), value_in1.GetRawData(),
1514                                        value_in2.GetRawData(), value_in3.GetRawData()));
1515     ASSERT_EQ(frame_handler.GetAcc().GetValue(), value_out.GetRawData());
1516 
1517     uint64_t args[] = {value_in0.GetRawData(), value_in1.GetRawData(), value_in2.GetRawData(), value_in3.GetRawData()};
1518     g_call_result = "";
1519     uint64_t res = InvokeCompiledCodeWithArgArrayDyn(args, 4, frame, &callee, thread_);
1520     ASSERT_EQ(g_call_result, PrintFunc("any", "FourArgDyn", &callee, 4, value_in0.GetRawData(), value_in1.GetRawData(),
1521                                        value_in2.GetRawData(), value_in3.GetRawData()));
1522     ASSERT_EQ(res, value_out.GetRawData());
1523 
1524     FreeFrame(frame);
1525 }
1526 
FourVarArgDyn(Method * method,uint32_t num_args,...)1527 static TaggedValue FourVarArgDyn(Method *method, uint32_t num_args, ...)
1528 {
1529     if (num_args != 4) {
1530         g_call_result = PrintFunc("any", __FUNCTION__, method, num_args);
1531         return TaggedValue(4.0);
1532     }
1533 
1534     va_list args;
1535     va_start(args, num_args);
1536     int64_t arg0 = va_arg(args, int64_t);
1537     int64_t arg1 = va_arg(args, int64_t);
1538     int64_t arg2 = va_arg(args, int64_t);
1539     int64_t arg3 = va_arg(args, int64_t);
1540     g_call_result = PrintFunc("any", __FUNCTION__, method, num_args, arg0, arg1, arg2, arg3);
1541     va_end(args);
1542     return TaggedValue(-4.0);
1543 }
1544 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeFourVarArgDyn)1545 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeFourVarArgDyn)
1546 {
1547     Frame *frame = CreateFrame<true>(4, nullptr, nullptr);
1548     auto frame_handler = DynamicFrameHandler(frame);
1549     TaggedValue value_in0(1.0);
1550     TaggedValue value_in1(2.0);
1551     TaggedValue value_in2(3.0);
1552     TaggedValue value_in3(4.0);
1553     TaggedValue value_out(-4.0);
1554     frame_handler.GetVReg(0).SetValue(value_in0.GetRawData());
1555     frame_handler.GetVReg(1).SetValue(value_in1.GetRawData());
1556     frame_handler.GetVReg(2).SetValue(value_in2.GetRawData());
1557     frame_handler.GetVReg(3).SetValue(value_in3.GetRawData());
1558 
1559     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, nullptr);
1560     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(FourVarArgDyn));
1561 
1562     uint8_t insn[] = {static_cast<uint8_t>(Opcode::CALLI_DYN_IMM4_V4_V4_V4_V4_V4), 0x04, 0x21, 0x03};
1563     g_call_result = "";
1564     frame_handler.GetAcc().SetValue(0);
1565     InterpreterToCompiledCodeBridgeDyn(insn, frame, &callee, thread_);
1566     ASSERT_EQ(g_call_result, PrintFunc("any", "FourVarArgDyn", &callee, 4, value_in0.GetRawData(),
1567                                        value_in1.GetRawData(), value_in2.GetRawData(), value_in3.GetRawData()));
1568     ASSERT_EQ(frame_handler.GetAcc().GetValue(), value_out.GetRawData());
1569 
1570     uint64_t args[] = {value_in0.GetRawData(), value_in1.GetRawData(), value_in2.GetRawData(), value_in3.GetRawData()};
1571     g_call_result = "";
1572     uint64_t res = InvokeCompiledCodeWithArgArrayDyn(args, 4, frame, &callee, thread_);
1573     ASSERT_EQ(g_call_result, PrintFunc("any", "FourVarArgDyn", &callee, 4, value_in0.GetRawData(),
1574                                        value_in1.GetRawData(), value_in2.GetRawData(), value_in3.GetRawData()));
1575     ASSERT_EQ(res, value_out.GetRawData());
1576 
1577     FreeFrame(frame);
1578 }
1579 
FiveArgDyn(Method * method,uint32_t num_args,int64_t arg0,int64_t arg1,int64_t arg2,int64_t arg3,int64_t arg4)1580 static TaggedValue FiveArgDyn(Method *method, uint32_t num_args, int64_t arg0, int64_t arg1, int64_t arg2, int64_t arg3,
1581                               int64_t arg4)
1582 {
1583     g_call_result = PrintFunc("any", __FUNCTION__, method, num_args, arg0, arg1, arg2, arg3, arg4);
1584     return TaggedValue(1515.0);
1585 }
1586 
TEST_F(InterpreterToCompiledCodeBridgeTest,InvokeFiveArgDyn)1587 TEST_F(InterpreterToCompiledCodeBridgeTest, InvokeFiveArgDyn)
1588 {
1589     Frame *frame = CreateFrame<true>(5, nullptr, nullptr);
1590     auto frame_handler = DynamicFrameHandler(frame);
1591     TaggedValue value_in0(1.0);
1592     TaggedValue value_in1(2.0);
1593     TaggedValue value_in2(3.0);
1594     TaggedValue value_in3(4.0);
1595     TaggedValue value_in4(5.0);
1596     TaggedValue value_out(1515.0);
1597     frame_handler.GetVReg(0).SetValue(value_in0.GetRawData());
1598     frame_handler.GetVReg(1).SetValue(value_in1.GetRawData());
1599     frame_handler.GetVReg(2).SetValue(value_in2.GetRawData());
1600     frame_handler.GetVReg(3).SetValue(value_in3.GetRawData());
1601     frame_handler.GetVReg(4).SetValue(value_in4.GetRawData());
1602 
1603     Method callee(nullptr, nullptr, panda_file::File::EntityId(), panda_file::File::EntityId(), ACC_STATIC, 0, nullptr);
1604     callee.SetCompiledEntryPoint(reinterpret_cast<const void *>(FiveArgDyn));
1605 
1606     uint8_t range_insn[] = {static_cast<uint8_t>(Opcode::CALLI_DYN_RANGE_IMM16_V16), 0x05, 0x00, 0x00, 0x00};
1607     g_call_result = "";
1608     frame_handler.GetAcc().SetValue(0);
1609     InterpreterToCompiledCodeBridgeDyn(range_insn, frame, &callee, thread_);
1610     ASSERT_EQ(g_call_result, PrintFunc("any", "FiveArgDyn", &callee, 5, value_in0.GetRawData(), value_in1.GetRawData(),
1611                                        value_in2.GetRawData(), value_in3.GetRawData(), value_in4.GetRawData()));
1612     ASSERT_EQ(frame_handler.GetAcc().GetValue(), value_out.GetRawData());
1613 
1614     uint64_t args[] = {value_in0.GetRawData(), value_in1.GetRawData(), value_in2.GetRawData(), value_in3.GetRawData(),
1615                        value_in4.GetRawData()};
1616     g_call_result = "";
1617     uint64_t res = InvokeCompiledCodeWithArgArrayDyn(args, 5, frame, &callee, thread_);
1618     ASSERT_EQ(g_call_result, PrintFunc("any", "FiveArgDyn", &callee, 5, value_in0.GetRawData(), value_in1.GetRawData(),
1619                                        value_in2.GetRawData(), value_in3.GetRawData(), value_in4.GetRawData()));
1620     ASSERT_EQ(res, value_out.GetRawData());
1621 
1622     FreeFrame(frame);
1623 }
1624 #endif
1625 }  // namespace panda::test
1626