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