1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <cstdint>
17 #include <unistd.h>
18
19 #include "ecmascript/builtins/builtins_promise_handler.h"
20 #include "ecmascript/compiler/assembler/assembler.h"
21 #include "ecmascript/compiler/assembler_module.h"
22 #include "ecmascript/compiler/binary_section.h"
23 #include "ecmascript/compiler/common_stubs.h"
24 #include "ecmascript/compiler/call_signature.h"
25 #include "ecmascript/compiler/gate_accessor.h"
26 #include "ecmascript/compiler/llvm_codegen.h"
27 #include "ecmascript/compiler/llvm_ir_builder.h"
28 #include "ecmascript/compiler/stub.h"
29 #include "ecmascript/compiler/scheduler.h"
30 #include "ecmascript/compiler/verifier.h"
31 #include "ecmascript/aot_file_manager.h"
32 #include "ecmascript/ecma_vm.h"
33 #include "ecmascript/interpreter/fast_runtime_stub-inl.h"
34 #include "ecmascript/js_array.h"
35 #include "ecmascript/mem/native_area_allocator.h"
36 #include "ecmascript/message_string.h"
37 #include "ecmascript/stackmap/llvm_stackmap_parser.h"
38 #include "ecmascript/stubs/runtime_stubs.h"
39 #include "ecmascript/tests/test_helper.h"
40
41 #include "llvm/IR/Instructions.h"
42 #include "llvm/IRReader/IRReader.h"
43 #include "llvm/Support/Host.h"
44 #include "llvm/Support/SourceMgr.h"
45
46 #include "gtest/gtest.h"
47
48 namespace panda::test {
49 using namespace panda::ecmascript;
50 using namespace panda::ecmascript::kungfu;
51 using BuiltinsPromiseHandler = builtins::BuiltinsPromiseHandler;
52
53 class StubTest : public testing::Test {
54 public:
SetUp()55 void SetUp() override
56 {
57 TestHelper::CreateEcmaVMWithScope(instance, thread, scope, true);
58 BytecodeStubCSigns::Initialize();
59 CommonStubCSigns::Initialize();
60 RuntimeStubCSigns::Initialize();
61 auto logOpt = thread->GetEcmaVM()->GetJSOptions().GetCompilerLogOption();
62 log = new CompilerLog(logOpt);
63 stubModule.SetUpForCommonStubs();
64 }
65
TearDown()66 void TearDown() override
67 {
68 TestHelper::DestroyEcmaVMWithScope(instance, scope);
69 if (log != nullptr) {
70 delete log;
71 }
72 }
73
PrintCircuitByBasicBlock(const std::vector<std::vector<GateRef>> & cfg,const Circuit & netOfGates) const74 void PrintCircuitByBasicBlock([[maybe_unused]] const std::vector<std::vector<GateRef>> &cfg,
75 [[maybe_unused]] const Circuit &netOfGates) const
76 {
77 if (thread->GetEcmaVM()->GetJSOptions().WasSetCompilerLogOption()) {
78 GateAccessor acc(const_cast<Circuit*>(&netOfGates));
79 for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) {
80 LOG_COMPILER(INFO) << (acc.GetMetaData(cfg[bbIdx].front())->IsCFGMerge() ? "MERGE_" : "BB_")
81 << bbIdx << ":";
82 for (size_t instIdx = cfg[bbIdx].size(); instIdx > 0; instIdx--) {
83 acc.Print(cfg[bbIdx][instIdx - 1]);
84 }
85 }
86 }
87 }
88
NewAotFunction(uint32_t numArgs,uintptr_t codeEntry)89 JSTaggedValue NewAotFunction(uint32_t numArgs, uintptr_t codeEntry)
90 {
91 auto ecmaVm = thread->GetEcmaVM();
92 ObjectFactory *factory = ecmaVm->GetFactory();
93 JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv();
94 JSHandle<Method> method = factory->NewMethodForNativeFunction(reinterpret_cast<void *>(codeEntry));
95 method->SetAotCodeBit(true);
96 method->SetNativeBit(false);
97 method->SetNumArgsWithCallField(numArgs);
98 method->SetCodeEntryOrLiteral(reinterpret_cast<uintptr_t>(codeEntry));
99 JSHandle<JSFunction> jsfunc = factory->NewJSFunction(env, method);
100 return jsfunc.GetTaggedValue();
101 }
102
103 EcmaVM *instance {nullptr};
104 EcmaHandleScope *scope {nullptr};
105 JSThread *thread {nullptr};
106 CompilerLog *log {nullptr};
107 LLVMModule stubModule {"stub_tests", "x86_64-unknown-linux-gnu"};
108 };
109
HWTEST_F_L0(StubTest,FastAddTest)110 HWTEST_F_L0(StubTest, FastAddTest)
111 {
112 auto module = stubModule.GetModule();
113 auto function = stubModule.GetFunction(CommonStubCSigns::Add);
114 ecmascript::NativeAreaAllocator allocator;
115 Circuit netOfGates(&allocator);
116 CallSignature callSignature;
117 AddCallSignature::Initialize(&callSignature);
118 Stub stub(&callSignature, &netOfGates);
119 AddStubBuilder optimizer(&callSignature, stub.GetEnvironment());
120 stub.SetStubBuilder(&optimizer);
121 stub.GenerateCircuit(stubModule.GetCompilationConfig());
122 netOfGates.PrintAllGates();
123 Scheduler::ControlFlowGraph cfg;
124 Scheduler::Run(&netOfGates, cfg);
125 PrintCircuitByBasicBlock(cfg, netOfGates);
126 LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
127 CallSignature::CallConv::CCallConv);
128 llvmBuilder.Build();
129 LLVMAssembler assembler(module);
130 assembler.Run(*log);
131 // Testcase build and run
132 auto fn = reinterpret_cast<JSTaggedValue (*)(uintptr_t, int64_t, int64_t)>(
133 assembler.GetFuncPtrFromCompiledModule(function));
134 auto resA = fn(thread->GetGlueAddr(), JSTaggedValue(1).GetRawData(),
135 JSTaggedValue(1).GetRawData());
136 auto resB = fn(thread->GetGlueAddr(), JSTaggedValue(2).GetRawData(),
137 JSTaggedValue(2).GetRawData()); // 2 : test case
138 auto resC = fn(thread->GetGlueAddr(), JSTaggedValue(11).GetRawData(),
139 JSTaggedValue(11).GetRawData()); // 11 : test case
140 LOG_COMPILER(INFO) << "res for FastAdd(1, 1) = " << resA.GetNumber();
141 LOG_COMPILER(INFO) << "res for FastAdd(2, 2) = " << resB.GetNumber();
142 LOG_COMPILER(INFO) << "res for FastAdd(11, 11) = " << resC.GetNumber();
143 EXPECT_EQ(resA.GetNumber(), JSTaggedValue(2).GetNumber());
144 EXPECT_EQ(resB.GetNumber(), JSTaggedValue(4).GetNumber());
145 EXPECT_EQ(resC.GetNumber(), JSTaggedValue(22).GetNumber());
146 int x1 = 2147483647;
147 int y1 = 15;
148 auto resG = fn(thread->GetGlueAddr(), JSTaggedValue(x1).GetRawData(), JSTaggedValue(y1).GetRawData());
149 auto expectedG = SlowRuntimeStub::Add2(thread, JSTaggedValue(x1), JSTaggedValue(y1));
150 EXPECT_EQ(resG, expectedG);
151 }
152
HWTEST_F_L0(StubTest,FastSubTest)153 HWTEST_F_L0(StubTest, FastSubTest)
154 {
155 auto module = stubModule.GetModule();
156 auto function = stubModule.GetFunction(CommonStubCSigns::Sub);
157 ecmascript::NativeAreaAllocator allocator;
158 Circuit netOfGates(&allocator);
159 CallSignature callSignature;
160 SubCallSignature::Initialize(&callSignature);
161 Stub stub(&callSignature, &netOfGates);
162 SubStubBuilder optimizer(&callSignature, stub.GetEnvironment());
163 stub.SetStubBuilder(&optimizer);
164 stub.GenerateCircuit(stubModule.GetCompilationConfig());
165 netOfGates.PrintAllGates();
166 Scheduler::ControlFlowGraph cfg;
167 Scheduler::Run(&netOfGates, cfg);
168 PrintCircuitByBasicBlock(cfg, netOfGates);
169 LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
170 CallSignature::CallConv::CCallConv);
171 llvmBuilder.Build();
172 LLVMAssembler assembler(module);
173 assembler.Run(*log);
174 // Testcase build and run
175 auto fn = reinterpret_cast<JSTaggedValue (*)(uintptr_t, int64_t, int64_t)>(
176 assembler.GetFuncPtrFromCompiledModule(function));
177 auto resA = fn(thread->GetGlueAddr(), JSTaggedValue(2).GetRawData(),
178 JSTaggedValue(1).GetRawData()); // 2 : test case
179 auto resB = fn(thread->GetGlueAddr(), JSTaggedValue(7).GetRawData(),
180 JSTaggedValue(2).GetRawData()); // 7, 2 : test cases
181 auto resC = fn(thread->GetGlueAddr(), JSTaggedValue(11).GetRawData(),
182 JSTaggedValue(11).GetRawData()); // 11 : test case
183 LOG_COMPILER(INFO) << "res for FastSub(2, 1) = " << resA.GetNumber();
184 LOG_COMPILER(INFO) << "res for FastSub(7, 2) = " << resB.GetNumber();
185 LOG_COMPILER(INFO) << "res for FastSub(11, 11) = " << resC.GetNumber();
186 EXPECT_EQ(resA, JSTaggedValue(1));
187 EXPECT_EQ(resB, JSTaggedValue(5));
188 EXPECT_EQ(resC, JSTaggedValue(0));
189 }
190
191
HWTEST_F_L0(StubTest,FastMulTest)192 HWTEST_F_L0(StubTest, FastMulTest)
193 {
194 auto module = stubModule.GetModule();
195 auto function = stubModule.GetFunction(CommonStubCSigns::Mul);
196 ecmascript::NativeAreaAllocator allocator;
197 Circuit netOfGates(&allocator);
198 CallSignature callSignature;
199 MulCallSignature::Initialize(&callSignature);
200 Stub stub(&callSignature, &netOfGates);
201 MulStubBuilder optimizer(&callSignature, stub.GetEnvironment());
202 stub.SetStubBuilder(&optimizer);
203 stub.GenerateCircuit(stubModule.GetCompilationConfig());
204 netOfGates.PrintAllGates();
205 Scheduler::ControlFlowGraph cfg;
206 Scheduler::Run(&netOfGates, cfg);
207 PrintCircuitByBasicBlock(cfg, netOfGates);
208 LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
209 CallSignature::CallConv::CCallConv);
210 llvmBuilder.Build();
211 LLVMAssembler assembler(module);
212 assembler.Run(*log);
213 // Testcase build and run
214 auto fn = reinterpret_cast<JSTaggedValue (*)(uintptr_t, int64_t, int64_t)>(
215 assembler.GetFuncPtrFromCompiledModule(function));
216 auto resA = fn(thread->GetGlueAddr(), JSTaggedValue(-2).GetRawData(),
217 JSTaggedValue(1).GetRawData()); // -2 : test case
218 auto resB = fn(thread->GetGlueAddr(), JSTaggedValue(-7).GetRawData(),
219 JSTaggedValue(-2).GetRawData()); // -7, -2 : test case
220 auto resC = fn(thread->GetGlueAddr(), JSTaggedValue(11).GetRawData(),
221 JSTaggedValue(11).GetRawData()); // 11 : test case
222 LOG_COMPILER(INFO) << "res for FastMul(-2, 1) = " << std::dec << resA.GetNumber();
223 LOG_COMPILER(INFO) << "res for FastMul(-7, -2) = " << std::dec << resB.GetNumber();
224 LOG_COMPILER(INFO) << "res for FastMul(11, 11) = " << std::dec << resC.GetNumber();
225 EXPECT_EQ(resA.GetNumber(), -2); // -2: test case
226 EXPECT_EQ(resB.GetNumber(), 14); // 14: test case
227 EXPECT_EQ(resC.GetNumber(), 121); // 121: test case
228 int x = 7;
229 double y = 1125899906842624;
230 auto resD = fn(thread->GetGlueAddr(), JSTaggedValue(x).GetRawData(), JSTaggedValue(y).GetRawData());
231 JSTaggedValue expectedD = FastRuntimeStub::FastMul(JSTaggedValue(x), JSTaggedValue(y));
232 EXPECT_EQ(resD, expectedD);
233 x = -1;
234 y = 1.7976931348623157e+308;
235 auto resE = fn(thread->GetGlueAddr(), JSTaggedValue(x).GetRawData(), JSTaggedValue(y).GetRawData());
236 JSTaggedValue expectedE = FastRuntimeStub::FastMul(JSTaggedValue(x), JSTaggedValue(y));
237 EXPECT_EQ(resE, expectedE);
238 x = -1;
239 y = -1 * std::numeric_limits<double>::infinity();
240 auto resF = fn(thread->GetGlueAddr(), JSTaggedValue(x).GetRawData(), JSTaggedValue(y).GetRawData());
241 JSTaggedValue expectedF = FastRuntimeStub::FastMul(JSTaggedValue(x), JSTaggedValue(y));
242 EXPECT_EQ(resF, expectedF);
243 int x1 = 2147483647;
244 int y1 = 15;
245 auto resG = fn(thread->GetGlueAddr(), JSTaggedValue(x1).GetRawData(), JSTaggedValue(y1).GetRawData());
246 auto expectedG = FastRuntimeStub::FastMul(JSTaggedValue(x1), JSTaggedValue(y1));
247 EXPECT_EQ(resG, expectedG);
248 }
249
HWTEST_F_L0(StubTest,FastDivTest)250 HWTEST_F_L0(StubTest, FastDivTest)
251 {
252 auto module = stubModule.GetModule();
253 auto function = stubModule.GetFunction(CommonStubCSigns::Div);
254 ecmascript::NativeAreaAllocator allocator;
255 Circuit netOfGates(&allocator);
256 CallSignature callSignature;
257 DivCallSignature::Initialize(&callSignature);
258 Stub stub(&callSignature, &netOfGates);
259 DivStubBuilder optimizer(&callSignature, stub.GetEnvironment());
260 stub.SetStubBuilder(&optimizer);
261 stub.GenerateCircuit(stubModule.GetCompilationConfig());
262 netOfGates.PrintAllGates();
263 Scheduler::ControlFlowGraph cfg;
264 Scheduler::Run(&netOfGates, cfg);
265 PrintCircuitByBasicBlock(cfg, netOfGates);
266 LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
267 CallSignature::CallConv::CCallConv);
268 llvmBuilder.Build();
269 LLVMAssembler assembler(module);
270 assembler.Run(*log);
271 auto fn = reinterpret_cast<JSTaggedValue (*)(uintptr_t, int64_t, int64_t)>(
272 assembler.GetFuncPtrFromCompiledModule(function));
273 // test normal Division operation
274 uint64_t x1 = JSTaggedValue(50).GetRawData();
275 uint64_t y1 = JSTaggedValue(25).GetRawData();
276 LOG_COMPILER(INFO) << "x1 = " << x1 << " y1 = " << y1;
277 auto res1 = fn(thread->GetGlueAddr(), x1, y1);
278 LOG_COMPILER(INFO) << "res for FastDiv(50, 25) = " << res1.GetRawData();
279 auto expectedG1 = FastRuntimeStub::FastDiv(JSTaggedValue(x1), JSTaggedValue(y1));
280 EXPECT_EQ(res1, expectedG1);
281
282 // test x == 0.0 or std::isnan(x)
283 uint64_t x2 = JSTaggedValue(base::NAN_VALUE).GetRawData();
284 uint64_t y2 = JSTaggedValue(0).GetRawData();
285 LOG_COMPILER(INFO) << "x2 = " << x1 << " y2 = " << y2;
286 auto res2 = fn(thread->GetGlueAddr(), x2, y2);
287 LOG_COMPILER(INFO) << "res for FastDiv(base::NAN_VALUE, 0) = " << res2.GetRawData();
288 auto expectedG2 = FastRuntimeStub::FastDiv(JSTaggedValue(x2), JSTaggedValue(y2));
289 EXPECT_EQ(res2, expectedG2);
290
291 // test other
292 uint64_t x3 = JSTaggedValue(7).GetRawData();
293 uint64_t y3 = JSTaggedValue(0).GetRawData();
294 LOG_COMPILER(INFO) << "x2 = " << x3 << " y2 = " << y3;
295 auto res3 = fn(thread->GetGlueAddr(), x3, y3);
296 LOG_COMPILER(INFO) << "res for FastDiv(7, 0) = " << res3.GetRawData();
297 auto expectedG3 = FastRuntimeStub::FastDiv(JSTaggedValue(x3), JSTaggedValue(y3));
298 EXPECT_EQ(res3, expectedG3);
299 }
300
HWTEST_F_L0(StubTest,FastModTest)301 HWTEST_F_L0(StubTest, FastModTest)
302 {
303 auto module = stubModule.GetModule();
304 auto function = stubModule.GetFunction(CommonStubCSigns::Mod);
305 ecmascript::NativeAreaAllocator allocator;
306 Circuit netOfGates(&allocator);
307 CallSignature callSignature;
308 ModCallSignature::Initialize(&callSignature);
309 Stub stub(&callSignature, &netOfGates);
310 ModStubBuilder optimizer(&callSignature, stub.GetEnvironment());
311 stub.SetStubBuilder(&optimizer);
312 stub.GenerateCircuit(stubModule.GetCompilationConfig());
313 netOfGates.PrintAllGates();
314 Scheduler::ControlFlowGraph cfg;
315 Scheduler::Run(&netOfGates, cfg);
316 PrintCircuitByBasicBlock(cfg, netOfGates);
317 LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
318 CallSignature::CallConv::CCallConv);
319 llvmBuilder.Build();
320 LLVMAssembler assembler(module);
321 assembler.Run(*log);
322 auto fn = reinterpret_cast<JSTaggedValue (*)(uintptr_t, int64_t, int64_t)>(
323 assembler.GetFuncPtrFromCompiledModule(function));
324 // test left, right are all integer
325 int x = 7;
326 int y = 3;
327 auto result = fn(thread->GetGlueAddr(), JSTaggedValue(x).GetRawData(), JSTaggedValue(y).GetRawData());
328 JSTaggedValue expectRes = FastRuntimeStub::FastMod(JSTaggedValue(x), JSTaggedValue(y));
329 EXPECT_EQ(result, expectRes);
330
331 // test y == 0.0 || std::isnan(y) || std::isnan(x) || std::isinf(x) return NAN_VALUE
332 double x2 = 7.3;
333 int y2 = base::NAN_VALUE;
334 auto result2 = fn(thread->GetGlueAddr(), JSTaggedValue(x2).GetRawData(), JSTaggedValue(y2).GetRawData());
335 auto expectRes2 = FastRuntimeStub::FastMod(JSTaggedValue(x2), JSTaggedValue(y2));
336 EXPECT_EQ(result2, expectRes2);
337 LOG_COMPILER(INFO) << "result2 for FastMod(7, 'helloworld') = " << result2.GetRawData();
338 LOG_COMPILER(INFO) << "expectRes2 for FastMod(7, 'helloworld') = " << expectRes2.GetRawData();
339
340 // // test modular operation under normal conditions
341 auto sp = const_cast<JSTaggedType *>(thread->GetCurrentSPFrame());
342 double x3 = 33.0;
343 double y3 = 44.0;
344 auto result3 = fn(thread->GetGlueAddr(), JSTaggedValue(x3).GetRawData(), JSTaggedValue(y3).GetRawData());
345 auto expectRes3 = FastRuntimeStub::FastMod(JSTaggedValue(x3), JSTaggedValue(y3));
346 EXPECT_EQ(result3, expectRes3);
347 thread->SetCurrentSPFrame(sp);
348
349 // test x == 0.0 || std::isinf(y) return x
350 double x4 = base::NAN_VALUE;
351 int y4 = 7;
352 auto result4 = fn(thread->GetGlueAddr(), JSTaggedValue(x4).GetRawData(), JSTaggedValue(y4).GetRawData());
353 auto expectRes4 = FastRuntimeStub::FastMod(JSTaggedValue(x4), JSTaggedValue(y4));
354
355 LOG_COMPILER(INFO) << "result4 for FastMod(base::NAN_VALUE, 7) = " << result4.GetRawData();
356 LOG_COMPILER(INFO) << "expectRes4 for FastMod(base::NAN_VALUE, 7) = " << expectRes4.GetRawData();
357 EXPECT_EQ(result4, expectRes4);
358
359 // test all non-conforming conditions
360 int x5 = 7;
361 auto *factory = thread->GetEcmaVM()->GetFactory();
362 thread->SetLastLeaveFrame(nullptr);
363 auto y5 = factory->NewFromASCII("hello world");
364 auto result5 = FastRuntimeStub::FastMod(JSTaggedValue(x5), y5.GetTaggedValue());
365 LOG_COMPILER(INFO) << "result1 for FastMod(7, 'helloworld') = " << result5.GetRawData();
366 EXPECT_EQ(result5, JSTaggedValue::Hole());
367 }
368
HWTEST_F_L0(StubTest,TryLoadICByName)369 HWTEST_F_L0(StubTest, TryLoadICByName)
370 {
371 auto module = stubModule.GetModule();
372 auto findFunction = stubModule.GetFunction(CommonStubCSigns::TryLoadICByName);
373 ecmascript::NativeAreaAllocator allocator;
374 Circuit netOfGates(&allocator);
375 CallSignature callSignature;
376 TryLoadICByNameCallSignature::Initialize(&callSignature);
377 Stub stub(&callSignature, &netOfGates);
378 TryLoadICByNameStubBuilder optimizer(&callSignature, stub.GetEnvironment());
379 stub.SetStubBuilder(&optimizer);
380 stub.GenerateCircuit(stubModule.GetCompilationConfig());
381 netOfGates.PrintAllGates();
382 Scheduler::ControlFlowGraph cfg;
383 Scheduler::Run(&netOfGates, cfg);
384 PrintCircuitByBasicBlock(cfg, netOfGates);
385 LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, findFunction, stubModule.GetCompilationConfig(),
386 CallSignature::CallConv::CCallConv);
387 llvmBuilder.Build();
388 LLVMAssembler assembler(module);
389 assembler.Run(*log);
390 }
391
HWTEST_F_L0(StubTest,TryLoadICByValue)392 HWTEST_F_L0(StubTest, TryLoadICByValue)
393 {
394 auto module = stubModule.GetModule();
395 auto findFunction = stubModule.GetFunction(CommonStubCSigns::TryLoadICByValue);
396 ecmascript::NativeAreaAllocator allocator;
397 Circuit netOfGates(&allocator);
398 CallSignature callSignature;
399 TryLoadICByValueCallSignature::Initialize(&callSignature);
400 Stub stub(&callSignature, &netOfGates);
401 TryLoadICByValueStubBuilder optimizer(&callSignature, stub.GetEnvironment());
402 stub.SetStubBuilder(&optimizer);
403 stub.GenerateCircuit(stubModule.GetCompilationConfig());
404 netOfGates.PrintAllGates();
405 Scheduler::ControlFlowGraph cfg;
406 Scheduler::Run(&netOfGates, cfg);
407 PrintCircuitByBasicBlock(cfg, netOfGates);
408 LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, findFunction, stubModule.GetCompilationConfig(),
409 CallSignature::CallConv::CCallConv);
410 llvmBuilder.Build();
411 LLVMAssembler assembler(module);
412 assembler.Run(*log);
413 }
414
HWTEST_F_L0(StubTest,TryStoreICByName)415 HWTEST_F_L0(StubTest, TryStoreICByName)
416 {
417 auto module = stubModule.GetModule();
418 auto findFunction = stubModule.GetFunction(CommonStubCSigns::TryStoreICByName);
419 ecmascript::NativeAreaAllocator allocator;
420 Circuit netOfGates(&allocator);
421 CallSignature callSignature;
422 TryStoreICByNameCallSignature::Initialize(&callSignature);
423 Stub stub(&callSignature, &netOfGates);
424 TryStoreICByNameStubBuilder optimizer(&callSignature, stub.GetEnvironment());
425 stub.SetStubBuilder(&optimizer);
426 stub.GenerateCircuit(stubModule.GetCompilationConfig());
427 netOfGates.PrintAllGates();
428 Scheduler::ControlFlowGraph cfg;
429 Scheduler::Run(&netOfGates, cfg);
430 PrintCircuitByBasicBlock(cfg, netOfGates);
431 LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, findFunction, stubModule.GetCompilationConfig(),
432 CallSignature::CallConv::CCallConv);
433 llvmBuilder.Build();
434 LLVMAssembler assembler(module);
435 assembler.Run(*log);
436 }
437
HWTEST_F_L0(StubTest,TryStoreICByValue)438 HWTEST_F_L0(StubTest, TryStoreICByValue)
439 {
440 auto module = stubModule.GetModule();
441 auto findFunction = stubModule.GetFunction(CommonStubCSigns::TryStoreICByValue);
442 ecmascript::NativeAreaAllocator allocator;
443 Circuit netOfGates(&allocator);
444 CallSignature callSignature;
445 TryStoreICByValueCallSignature::Initialize(&callSignature);
446 Stub stub(&callSignature, &netOfGates);
447 TryStoreICByValueStubBuilder optimizer(&callSignature, stub.GetEnvironment());
448 stub.SetStubBuilder(&optimizer);
449 stub.GenerateCircuit(stubModule.GetCompilationConfig());
450 netOfGates.PrintAllGates();
451 Scheduler::ControlFlowGraph cfg;
452 Scheduler::Run(&netOfGates, cfg);
453 PrintCircuitByBasicBlock(cfg, netOfGates);
454 LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, findFunction, stubModule.GetCompilationConfig(),
455 CallSignature::CallConv::CCallConv);
456 llvmBuilder.Build();
457 LLVMAssembler assembler(module);
458 assembler.Run(*log);
459 }
460
461 struct ThreadTy {
462 intptr_t magic; // 0x11223344
463 intptr_t fp;
464 };
465 class StubCallRunTimeThreadFpLock {
466 public:
StubCallRunTimeThreadFpLock(struct ThreadTy * thread,intptr_t newFp)467 StubCallRunTimeThreadFpLock(struct ThreadTy *thread, intptr_t newFp) : oldRbp_(thread->fp), thread_(thread)
468 {
469 thread_->fp = *(reinterpret_cast<int64_t *>(newFp));
470 LOG_COMPILER(INFO) << "StubCallRunTimeThreadFpLock newFp: " << newFp << " oldRbp_ : " << oldRbp_
471 << " thread_->fp:" << thread_->fp;
472 }
~StubCallRunTimeThreadFpLock()473 ~StubCallRunTimeThreadFpLock()
474 {
475 LOG_COMPILER(INFO) << "~StubCallRunTimeThreadFpLock oldRbp_: " << oldRbp_ << " thread_->fp:" << thread_->fp;
476 thread_->fp = oldRbp_;
477 }
478
479 private:
480 intptr_t oldRbp_;
481 struct ThreadTy *thread_;
482 };
483
484 extern "C" {
RuntimeFunc(struct ThreadTy * fpInfo)485 int64_t RuntimeFunc(struct ThreadTy *fpInfo)
486 {
487 int64_t *rbp;
488 asm("mov %%rbp, %0" : "=rm"(rbp));
489 if (fpInfo->fp == *rbp) {
490 return 1;
491 }
492 return 0;
493 }
494
495 int64_t (*g_stub2Func)(struct ThreadTy *) = nullptr;
496
RuntimeFunc1(struct ThreadTy * fpInfo)497 int RuntimeFunc1(struct ThreadTy *fpInfo)
498 {
499 LOG_COMPILER(INFO) << "RuntimeFunc1 -";
500 int64_t newRbp;
501 asm("mov %%rbp, %0" : "=rm"(newRbp));
502 StubCallRunTimeThreadFpLock lock(fpInfo, newRbp);
503
504 LOG_COMPILER(INFO) << std::hex << "g_stub2Func " << reinterpret_cast<uintptr_t>(g_stub2Func);
505 if (g_stub2Func != nullptr) {
506 g_stub2Func(fpInfo);
507 }
508 LOG_COMPILER(INFO) << "RuntimeFunc1 +";
509 return 0;
510 }
511
RuntimeFunc2(struct ThreadTy * fpInfo)512 int RuntimeFunc2(struct ThreadTy *fpInfo)
513 {
514 LOG_COMPILER(INFO) << "RuntimeFunc2 -";
515 // update thread.fp
516 int64_t newRbp;
517 asm("mov %%rbp, %0" : "=rm"(newRbp));
518 StubCallRunTimeThreadFpLock lock(fpInfo, newRbp);
519 auto rbp = reinterpret_cast<int64_t *>(fpInfo->fp);
520
521 LOG_COMPILER(INFO) << " RuntimeFunc2 rbp:" << rbp;
522 for (int i = 0; i < 40; i++) { // print 40 ptr value for debug
523 LOG_COMPILER(INFO) << std::hex << &(rbp[i]) << " :" << rbp[i];
524 }
525 /* walk back
526 stack frame: 0 pre rbp <-- rbp
527 -8 type
528 -16 pre frame thread fp
529 */
530 int64_t *frameType = nullptr;
531 int64_t *gcFp = nullptr;
532 LOG_COMPILER(INFO) << "-----------------walkback----------------";
533 do {
534 frameType = rbp - 1;
535 if (*frameType == 1) {
536 gcFp = rbp - 2; // 2: 2 stack slot
537 } else {
538 gcFp = rbp;
539 }
540 rbp = reinterpret_cast<intptr_t *>(*gcFp);
541 LOG_COMPILER(INFO) << std::hex << "frameType :" << *frameType << " gcFp:" << *gcFp;
542 } while (*gcFp != 0);
543 LOG_COMPILER(INFO) << "+++++++++++++++++walkback++++++++++++++++";
544 LOG_COMPILER(INFO) << "call RuntimeFunc2 func ThreadTy fp: " << fpInfo->fp << " magic:" << fpInfo->magic;
545 LOG_COMPILER(INFO) << "RuntimeFunc2 +";
546 return 0;
547 }
548 }
549
550 /*
551 c++:main
552 --> js (stub1(struct ThreadTy *))
553 stack frame: 0 pre rbp <-- rbp
554 -8 type
555 -16 pre frame thread fp
556 --> c++(int RuntimeFunc1(struct ThreadTy *fpInfo))
557 --> js (int stub2(struct ThreadTy *))
558 stack frame: 0 pre rbp <-- rbp
559 -8 type
560 -16 pre frame thread fp
561 --> js (int stub3(struct ThreadTy *))
562 stack frame: 0 pre rbp <-- rbp
563 -8 type
564 --> c++(int RuntimeFunc2(struct ThreadTy *fpInfo))
565
566 result:
567 -----------------walkback----------------
568 frameType :0 gcFp:7fffffffd780
569 frameType :1 gcFp:7fffffffd820
570 frameType :1 gcFp:0
571 +++++++++++++++++walkback++++++++++++++++
572 #0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:40
573 #1 0x00007ffff03778b1 in __GI_abort () at abort.c:79
574 #2 0x0000555555610f1c in RuntimeFunc2 ()
575 #3 0x00007fffebf7b1fb in stub3 ()
576 #4 0x00007fffebf7b1ab in stub2 ()
577 #5 0x0000555555610afe in RuntimeFunc1 ()
578 #6 0x00007fffebf7b14e in stub1 ()
579 #7 0x000055555561197c in panda::test::StubTest_JSEntryTest_Test::TestBody() ()
580 */
581
CallingFp(LLVMModuleRef & module,LLVMBuilderRef & builder)582 LLVMValueRef CallingFp(LLVMModuleRef &module, LLVMBuilderRef &builder)
583 {
584 /* 0:calling 1:its caller */
585 std::vector<LLVMValueRef> args = {LLVMConstInt(LLVMInt32Type(), 0, false)};
586 auto fn = LLVMGetNamedFunction(module, "llvm.frameaddress.p0i8");
587 if (!fn) {
588 LOG_COMPILER(INFO) << "Could not find function ";
589 return LLVMConstInt(LLVMInt64Type(), 0, false);
590 }
591 LLVMValueRef fAddrRet = LLVMBuildCall(builder, fn, args.data(), 1, "");
592 LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder, fAddrRet, LLVMInt64Type(), "cast_int64_t");
593 return frameAddr;
594 }
595
HWTEST_F_L0(StubTest,GetPropertyByIndexStub)596 HWTEST_F_L0(StubTest, GetPropertyByIndexStub)
597 {
598 auto module = stubModule.GetModule();
599 auto function = stubModule.GetFunction(CommonStubCSigns::GetPropertyByIndex);
600 ecmascript::NativeAreaAllocator allocator;
601 Circuit netOfGates(&allocator);
602 CallSignature callSignature;
603 GetPropertyByIndexCallSignature::Initialize(&callSignature);
604 Stub stub(&callSignature, &netOfGates);
605 GetPropertyByIndexStubBuilder optimizer(&callSignature, stub.GetEnvironment());
606 stub.SetStubBuilder(&optimizer);
607 stub.GenerateCircuit(stubModule.GetCompilationConfig());
608 netOfGates.PrintAllGates();
609 Scheduler::ControlFlowGraph cfg;
610 Scheduler::Run(&netOfGates, cfg);
611 PrintCircuitByBasicBlock(cfg, netOfGates);
612 LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
613 CallSignature::CallConv::CCallConv);
614 llvmBuilder.Build();
615 LLVMAssembler assembler(module);
616 assembler.Run(*log);
617 auto *getpropertyByIndex = reinterpret_cast<JSTaggedValue (*)(uintptr_t, JSTaggedValue, uint32_t)>(
618 reinterpret_cast<uintptr_t>(assembler.GetFuncPtrFromCompiledModule(function)));
619 auto *factory = thread->GetEcmaVM()->GetFactory();
620 JSHandle<JSObject> obj = factory->NewEmptyJSObject();
621 int x = 213;
622 int y = 10;
623 FastRuntimeStub::SetPropertyByIndex<true>(thread, obj.GetTaggedValue(), 1, JSTaggedValue(x));
624 FastRuntimeStub::SetPropertyByIndex<true>(thread, obj.GetTaggedValue(), 10250, JSTaggedValue(y));
625 JSTaggedValue resVal = getpropertyByIndex(thread->GetGlueAddr(), obj.GetTaggedValue(), 1);
626 EXPECT_EQ(resVal.GetNumber(), x);
627 resVal = getpropertyByIndex(thread->GetGlueAddr(), obj.GetTaggedValue(), 10250);
628 EXPECT_EQ(resVal.GetNumber(), y);
629 }
630
HWTEST_F_L0(StubTest,GetPropertyByNameStub)631 HWTEST_F_L0(StubTest, GetPropertyByNameStub)
632 {
633 auto module = stubModule.GetModule();
634 auto function = stubModule.GetFunction(CommonStubCSigns::DeprecatedGetPropertyByName);
635 ecmascript::NativeAreaAllocator allocator;
636 Circuit netOfGates(&allocator);
637 CallSignature callSignature;
638 DeprecatedGetPropertyByNameCallSignature::Initialize(&callSignature);
639 Stub stub(&callSignature, &netOfGates);
640 DeprecatedGetPropertyByNameStubBuilder optimizer(&callSignature, stub.GetEnvironment());
641 stub.SetStubBuilder(&optimizer);
642 stub.GenerateCircuit(stubModule.GetCompilationConfig());
643 netOfGates.PrintAllGates();
644 bool result = Verifier::Run(&netOfGates);
645 ASSERT_TRUE(result);
646 Scheduler::ControlFlowGraph cfg;
647 Scheduler::Run(&netOfGates, cfg);
648 PrintCircuitByBasicBlock(cfg, netOfGates);
649 LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
650 CallSignature::CallConv::CCallConv);
651 llvmBuilder.Build();
652 LLVMAssembler assembler(module);
653 assembler.Run(*log);
654 auto *getPropertyByNamePtr = reinterpret_cast<JSTaggedValue (*)(uintptr_t, uint64_t, uint64_t)>(
655 reinterpret_cast<uintptr_t>(assembler.GetFuncPtrFromCompiledModule(function)));
656 auto *factory = thread->GetEcmaVM()->GetFactory();
657 JSHandle<JSObject> obj = factory->NewEmptyJSObject();
658 int x = 256;
659 int y = 10;
660 JSHandle<JSTaggedValue> strA(factory->NewFromASCII("a"));
661 JSHandle<JSTaggedValue> strBig(factory->NewFromASCII("biggest"));
662 FastRuntimeStub::SetPropertyByName(thread, obj.GetTaggedValue(), strA.GetTaggedValue(), JSTaggedValue(x));
663 FastRuntimeStub::SetPropertyByName(thread, obj.GetTaggedValue(), strBig.GetTaggedValue(), JSTaggedValue(y));
664 JSTaggedValue resVal = getPropertyByNamePtr(thread->GetGlueAddr(), obj.GetTaggedValue().GetRawData(),
665 strA.GetTaggedValue().GetRawData());
666 EXPECT_EQ(resVal.GetNumber(), x);
667 resVal = getPropertyByNamePtr(thread->GetGlueAddr(), obj.GetTaggedValue().GetRawData(),
668 strBig.GetTaggedValue().GetRawData());
669 EXPECT_EQ(resVal.GetNumber(), y);
670 }
671
HWTEST_F_L0(StubTest,GetPropertyByValueStub)672 HWTEST_F_L0(StubTest, GetPropertyByValueStub)
673 {
674 auto module = stubModule.GetModule();
675 LLVMValueRef getPropertyByIndexfunction = stubModule.GetFunction(CommonStubCSigns::GetPropertyByIndex);
676 ecmascript::NativeAreaAllocator allocator;
677 Circuit netOfGates2(&allocator);
678 CallSignature callSignature;
679 GetPropertyByIndexCallSignature::Initialize(&callSignature);
680 Stub stub(&callSignature, &netOfGates2);
681 GetPropertyByIndexStubBuilder optimizer(&callSignature, stub.GetEnvironment());
682 stub.SetStubBuilder(&optimizer);
683 stub.GenerateCircuit(stubModule.GetCompilationConfig());
684 netOfGates2.PrintAllGates();
685 Scheduler::ControlFlowGraph cfg;
686 Scheduler::Run(&netOfGates2, cfg);
687 LLVMIRBuilder llvmBuilder2(&cfg, &netOfGates2, &stubModule, getPropertyByIndexfunction,
688 stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv);
689 llvmBuilder2.Build();
690
691 LLVMValueRef getPropertyByNamefunction = stubModule.GetFunction(CommonStubCSigns::DeprecatedGetPropertyByName);
692 Circuit netOfGates1(&allocator);
693 CallSignature callSignature1;
694 DeprecatedGetPropertyByNameCallSignature::Initialize(&callSignature1);
695 Stub stub1(&callSignature1, &netOfGates1);
696 DeprecatedGetPropertyByNameStubBuilder getPropertyByNameStub(&callSignature, stub1.GetEnvironment());
697 stub1.SetStubBuilder(&getPropertyByNameStub);
698 stub1.GenerateCircuit(stubModule.GetCompilationConfig());
699 bool result = Verifier::Run(&netOfGates1);
700 ASSERT_TRUE(result);
701 Scheduler::ControlFlowGraph cfg1;
702 Scheduler::Run(&netOfGates1, cfg1);
703 LLVMIRBuilder llvmBuilder1(&cfg1, &netOfGates1, &stubModule, getPropertyByNamefunction,
704 stubModule.GetCompilationConfig(), CallSignature::CallConv::CCallConv);
705 llvmBuilder1.Build();
706
707 LLVMValueRef function = stubModule.GetFunction(CommonStubCSigns::DeprecatedGetPropertyByValue);
708 Circuit netOfGates(&allocator);
709 CallSignature callSignature2;
710 DeprecatedGetPropertyByValueCallSignature::Initialize(&callSignature2);
711 Stub stub2(&callSignature2, &netOfGates);
712 DeprecatedGetPropertyByValueStubBuilder getPropertyByValueStub(&callSignature, stub2.GetEnvironment());
713 stub2.SetStubBuilder(&getPropertyByValueStub);
714 stub2.GenerateCircuit(stubModule.GetCompilationConfig());
715 netOfGates.PrintAllGates();
716 result = Verifier::Run(&netOfGates);
717 ASSERT_TRUE(result);
718 Scheduler::ControlFlowGraph cfg2;
719 Scheduler::Run(&netOfGates, cfg2);
720 PrintCircuitByBasicBlock(cfg2, netOfGates);
721
722 LLVMIRBuilder llvmBuilder(&cfg2, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
723 CallSignature::CallConv::CCallConv);
724 llvmBuilder.Build();
725 LLVMAssembler assembler(module);
726 assembler.Run(*log);
727 auto *getPropertyByValuePtr = reinterpret_cast<JSTaggedValue (*)(uintptr_t, uint64_t, uint64_t)>(
728 reinterpret_cast<uintptr_t>(assembler.GetFuncPtrFromCompiledModule(function)));
729 auto *getPropertyByNamePtr = reinterpret_cast<JSTaggedValue (*)(uintptr_t, uint64_t, uint64_t)>(
730 reinterpret_cast<uintptr_t>(assembler.GetFuncPtrFromCompiledModule(getPropertyByNamefunction)));
731 auto *getpropertyByIndexPtr = reinterpret_cast<JSTaggedValue (*)(uintptr_t, JSTaggedValue, uint32_t)>(
732 reinterpret_cast<uintptr_t>(assembler.GetFuncPtrFromCompiledModule(getPropertyByIndexfunction)));
733
734 thread->SetFastStubEntry(CommonStubCSigns::GetPropertyByIndex, reinterpret_cast<uintptr_t>(getpropertyByIndexPtr));
735 thread->SetFastStubEntry(CommonStubCSigns::DeprecatedGetPropertyByName,
736 reinterpret_cast<uintptr_t>(getPropertyByNamePtr));
737 auto *factory = thread->GetEcmaVM()->GetFactory();
738 JSHandle<JSObject> obj = factory->NewEmptyJSObject();
739 int x = 213;
740 int y = 10;
741 auto sp = const_cast<JSTaggedType *>(thread->GetCurrentSPFrame());
742 FastRuntimeStub::SetPropertyByIndex<true>(thread, obj.GetTaggedValue(), 1, JSTaggedValue(x));
743 FastRuntimeStub::SetPropertyByIndex<true>(thread, obj.GetTaggedValue(), 10250, JSTaggedValue(y));
744
745 JSHandle<JSTaggedValue> strA(factory->NewFromASCII("a"));
746 JSHandle<JSTaggedValue> strBig(factory->NewFromASCII("biggest"));
747 JSHandle<JSTaggedValue> strDigit(factory->NewFromASCII("10250"));
748
749 FastRuntimeStub::SetPropertyByName(thread, obj.GetTaggedValue(), strA.GetTaggedValue(), JSTaggedValue(x));
750 FastRuntimeStub::SetPropertyByName(thread, obj.GetTaggedValue(), strBig.GetTaggedValue(), JSTaggedValue(y));
751 JSTaggedValue resVal1 = getPropertyByNamePtr(thread->GetGlueAddr(), obj.GetTaggedValue().GetRawData(),
752 strA.GetTaggedValue().GetRawData());
753 EXPECT_EQ(resVal1.GetNumber(), x);
754 JSTaggedValue resVal = getPropertyByValuePtr(thread->GetGlueAddr(), obj.GetTaggedValue().GetRawData(),
755 strA.GetTaggedValue().GetRawData());
756 EXPECT_EQ(resVal.GetNumber(), x);
757 resVal = getPropertyByValuePtr(thread->GetGlueAddr(), obj.GetTaggedValue().GetRawData(),
758 strBig.GetTaggedValue().GetRawData());
759 EXPECT_EQ(resVal.GetNumber(), y);
760 resVal = getpropertyByIndexPtr(thread->GetGlueAddr(), obj.GetTaggedValue(), 1);
761 EXPECT_EQ(resVal.GetNumber(), x);
762 resVal = getPropertyByValuePtr(thread->GetGlueAddr(), obj.GetTaggedValue().GetRawData(),
763 JSTaggedValue(10250).GetRawData());
764 EXPECT_EQ(resVal.GetNumber(), y);
765 resVal = getPropertyByValuePtr(thread->GetGlueAddr(), obj.GetTaggedValue().GetRawData(),
766 strDigit.GetTaggedValue().GetRawData());
767 EXPECT_EQ(resVal.GetNumber(), y);
768 thread->SetCurrentSPFrame(sp);
769 thread->SetLastLeaveFrame(nullptr);
770 JSHandle<JSTaggedValue> strHello(factory->NewFromASCII("hello world"));
771 double key = 4.29497e+09;
772 resVal = getPropertyByValuePtr(thread->GetGlueAddr(), strHello.GetTaggedValue().GetRawData(),
773 JSTaggedValue(key).GetRawData());
774 EXPECT_EQ(resVal.GetRawData(), JSTaggedValue::Hole().GetRawData());
775 }
776
HWTEST_F_L0(StubTest,FastTypeOfTest)777 HWTEST_F_L0(StubTest, FastTypeOfTest)
778 {
779 auto module = stubModule.GetModule();
780 auto function = stubModule.GetFunction(CommonStubCSigns::TypeOf);
781 ecmascript::NativeAreaAllocator allocator;
782 Circuit netOfGates(&allocator);
783 CallSignature callSignature;
784 TypeOfCallSignature::Initialize(&callSignature);
785 Stub stub(&callSignature, &netOfGates);
786 TypeOfStubBuilder optimizer(&callSignature, stub.GetEnvironment());
787 stub.SetStubBuilder(&optimizer);
788 stub.GenerateCircuit(stubModule.GetCompilationConfig());
789 netOfGates.PrintAllGates();
790 bool verRes = Verifier::Run(&netOfGates);
791 ASSERT_TRUE(verRes);
792 Scheduler::ControlFlowGraph cfg;
793 Scheduler::Run(&netOfGates, cfg);
794 PrintCircuitByBasicBlock(cfg, netOfGates);
795 LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
796 CallSignature::CallConv::CCallConv);
797 llvmBuilder.Build();
798 char *error = nullptr;
799 LLVMVerifyModule(module, LLVMAbortProcessAction, &error);
800 LLVMAssembler assembler(module);
801 assembler.Run(*log);
802 auto *typeOfPtr =
803 reinterpret_cast<JSTaggedValue (*)(uintptr_t, uint64_t)>(assembler.GetFuncPtrFromCompiledModule(function));
804 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
805
806 // obj is JSTaggedValue::VALUE_TRUE
807 JSTaggedValue resultVal = typeOfPtr(thread->GetGlueAddr(), JSTaggedValue::True().GetRawData());
808 JSTaggedValue expectResult = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue::True());
809 EXPECT_EQ(resultVal, globalConst->GetBooleanString());
810 EXPECT_EQ(resultVal, expectResult);
811
812 // obj is JSTaggedValue::VALUE_FALSE
813 JSTaggedValue resultVal2 = typeOfPtr(thread->GetGlueAddr(), JSTaggedValue::False().GetRawData());
814 JSTaggedValue expectResult2 = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue::False());
815 EXPECT_EQ(resultVal2, globalConst->GetBooleanString());
816 EXPECT_EQ(resultVal2, expectResult2);
817
818 // obj is JSTaggedValue::VALUE_NULL
819 JSTaggedValue resultVal3 = typeOfPtr(thread->GetGlueAddr(), JSTaggedValue::Null().GetRawData());
820 JSTaggedValue expectResult3 = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue::Null());
821 EXPECT_EQ(resultVal3, globalConst->GetObjectString());
822 EXPECT_EQ(resultVal3, expectResult3);
823
824 // obj is JSTaggedValue::VALUE_UNDEFINED
825 JSTaggedValue resultVal4 = typeOfPtr(thread->GetGlueAddr(), JSTaggedValue::Undefined().GetRawData());
826 JSTaggedValue expectResult4 = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue::Undefined());
827 EXPECT_EQ(resultVal4, globalConst->GetUndefinedString());
828 EXPECT_EQ(resultVal4, expectResult4);
829
830 // obj is IsNumber
831 JSTaggedValue resultVal5 = typeOfPtr(thread->GetGlueAddr(), JSTaggedValue(5).GetRawData());
832 JSTaggedValue expectResult5 = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue(5));
833 EXPECT_EQ(resultVal5, globalConst->GetNumberString());
834 EXPECT_EQ(resultVal5, expectResult5);
835
836 // obj is String
837 auto *factory = thread->GetEcmaVM()->GetFactory();
838 JSHandle<EcmaString> str1 = factory->NewFromASCII("a");
839 JSHandle<EcmaString> str2 = factory->NewFromASCII("a");
840 JSTaggedValue expectResult6 = FastRuntimeStub::FastTypeOf(thread, str1.GetTaggedValue());
841 JSTaggedValue resultVal6 = typeOfPtr(thread->GetGlueAddr(), str2.GetTaggedValue().GetRawData());
842 EXPECT_EQ(resultVal6, globalConst->GetStringString());
843 EXPECT_EQ(resultVal6, expectResult6);
844
845 // obj is Symbol
846 JSHandle<GlobalEnv> globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
847 JSTaggedValue symbol = globalEnv->GetIteratorSymbol().GetTaggedValue();
848 JSTaggedValue expectResult7= FastRuntimeStub::FastTypeOf(thread, symbol);
849 JSTaggedValue resultVal7 = typeOfPtr(thread->GetGlueAddr(), symbol.GetRawData());
850 EXPECT_EQ(resultVal7, globalConst->GetSymbolString());
851 EXPECT_EQ(resultVal7, expectResult7);
852
853 // obj is callable
854 JSHandle<JSPromiseReactionsFunction> resolveCallable = factory->CreateJSPromiseReactionsFunction(
855 MethodIndex::BUILTINS_PROMISE_HANDLER_RESOLVE);
856 JSTaggedValue expectResult8= FastRuntimeStub::FastTypeOf(thread, resolveCallable.GetTaggedValue());
857 JSTaggedValue resultVal8 = typeOfPtr(thread->GetGlueAddr(), resolveCallable.GetTaggedValue().GetRawData());
858 EXPECT_EQ(resultVal8, globalConst->GetFunctionString());
859 EXPECT_EQ(resultVal8, expectResult8);
860
861 // obj is heapObject
862 JSHandle<JSObject> object = factory->NewEmptyJSObject();
863 JSTaggedValue expectResult9= FastRuntimeStub::FastTypeOf(thread, object.GetTaggedValue());
864 JSTaggedValue resultVal9 = typeOfPtr(thread->GetGlueAddr(), object.GetTaggedValue().GetRawData());
865 EXPECT_EQ(resultVal9, globalConst->GetObjectString());
866 EXPECT_EQ(resultVal9, expectResult9);
867 }
868
HWTEST_F_L0(StubTest,FastEqualTest)869 HWTEST_F_L0(StubTest, FastEqualTest)
870 {
871 auto module = stubModule.GetModule();
872 auto function = stubModule.GetFunction(CommonStubCSigns::Equal);
873 ecmascript::NativeAreaAllocator allocator;
874 Circuit netOfGates(&allocator);
875 CallSignature callSignature;
876 EqualCallSignature::Initialize(&callSignature);
877 Stub stub(&callSignature, &netOfGates);
878 EqualStubBuilder optimizer(&callSignature, stub.GetEnvironment());
879 stub.SetStubBuilder(&optimizer);
880 stub.GenerateCircuit(stubModule.GetCompilationConfig());
881 netOfGates.PrintAllGates();
882 Scheduler::ControlFlowGraph cfg;
883 Scheduler::Run(&netOfGates, cfg);
884 PrintCircuitByBasicBlock(cfg, netOfGates);
885 LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
886 CallSignature::CallConv::CCallConv);
887 llvmBuilder.Build();
888 LLVMAssembler assembler(module);
889 assembler.Run(*log);
890 auto fn = reinterpret_cast<JSTaggedValue (*)(uintptr_t, int64_t, int64_t)>(
891 assembler.GetFuncPtrFromCompiledModule(function));
892 // test for 1 == 1
893 auto resA = fn(thread->GetGlueAddr(), JSTaggedValue(1).GetRawData(), JSTaggedValue(1).GetRawData());
894 auto expectA = FastRuntimeStub::FastEqual(JSTaggedValue(1), JSTaggedValue(1));
895 EXPECT_EQ(resA, expectA);
896
897 // test for nan == nan
898 double nan = std::numeric_limits<double>::quiet_NaN();
899 auto resB = fn(thread->GetGlueAddr(), JSTaggedValue(nan).GetRawData(), JSTaggedValue(nan).GetRawData());
900 auto expectB = FastRuntimeStub::FastEqual(JSTaggedValue(nan), JSTaggedValue(nan));
901 EXPECT_EQ(resB, expectB);
902
903 // test for undefined == null
904 auto resC = fn(thread->GetGlueAddr(), JSTaggedValue::Undefined().GetRawData(), JSTaggedValue::Null().GetRawData());
905 auto expectC = FastRuntimeStub::FastEqual(JSTaggedValue::Undefined(), JSTaggedValue::Null());
906 EXPECT_EQ(resC, expectC);
907
908 // test for "hello world" == undefined
909 auto *factory = thread->GetEcmaVM()->GetFactory();
910 auto str = factory->NewFromASCII("hello world");
911 auto resD = fn(thread->GetGlueAddr(), str.GetTaggedValue().GetRawData(), JSTaggedValue::Undefined().GetRawData());
912 auto expectD = FastRuntimeStub::FastEqual(str.GetTaggedValue(), JSTaggedValue::Undefined());
913 EXPECT_EQ(resD, expectD);
914
915 // test for true == hole
916 auto resE = fn(thread->GetGlueAddr(), JSTaggedValue::True().GetRawData(), JSTaggedValue::Hole().GetRawData());
917 auto expectE = FastRuntimeStub::FastEqual(JSTaggedValue::True(), JSTaggedValue::Hole());
918 EXPECT_EQ(resE, expectE);
919
920 // test for "hello world" == "hello world"
921 auto resF = fn(thread->GetGlueAddr(), str.GetTaggedValue().GetRawData(), str.GetTaggedValue().GetRawData());
922 auto expectF = FastRuntimeStub::FastEqual(str.GetTaggedValue(), str.GetTaggedValue());
923 EXPECT_EQ(resF, expectF);
924
925 // test for 5.2 == 5.2
926 auto resG = fn(thread->GetGlueAddr(), JSTaggedValue(5.2).GetRawData(), JSTaggedValue(5.2).GetRawData());
927 auto expectG = FastRuntimeStub::FastEqual(JSTaggedValue(5.2), JSTaggedValue(5.2));
928 EXPECT_EQ(resG, expectG);
929
930 // test for false == false
931 auto resH = fn(thread->GetGlueAddr(), JSTaggedValue::False().GetRawData(), JSTaggedValue::False().GetRawData());
932 auto expectH = FastRuntimeStub::FastEqual(JSTaggedValue::False(), JSTaggedValue::False());
933 EXPECT_EQ(resH, expectH);
934
935 // test for obj == obj
936 JSHandle<JSObject> obj1 = factory->NewEmptyJSObject();
937 JSHandle<JSObject> obj2 = factory->NewEmptyJSObject();
938 FastRuntimeStub::SetPropertyByIndex<true>(thread, obj1.GetTaggedValue(), 1, JSTaggedValue(1));
939 FastRuntimeStub::SetPropertyByIndex<true>(thread, obj2.GetTaggedValue(), 1, JSTaggedValue(1));
940 auto resI = fn(thread->GetGlueAddr(), obj1.GetTaggedValue().GetRawData(), obj2.GetTaggedValue().GetRawData());
941 auto expectI = JSTaggedValue(FastRuntimeStub::FastStrictEqual(obj1.GetTaggedValue(), obj2.GetTaggedValue()));
942 EXPECT_EQ(resI, expectI);
943 }
944
945 #ifndef NDEBUG
HWTEST_F_L0(StubTest,JSCallTest)946 HWTEST_F_L0(StubTest, JSCallTest)
947 {
948 auto fooEntry = thread->GetFastStubEntry(CommonStubCSigns::FooAOT);
949 auto footarget = NewAotFunction(2, fooEntry);
950 auto glue = thread->GetGlueAddr();
951 int x = 1;
952 int y = 2;
953 JSTaggedType argV[5] = {
954 footarget.GetRawData(),
955 JSTaggedValue::Undefined().GetRawData(),
956 JSTaggedValue::Undefined().GetRawData(),
957 JSTaggedValue(x).GetRawData(),
958 JSTaggedValue(y).GetRawData(),
959 };
960 auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry);
961
962 auto result = reinterpret_cast<JSFunctionEntryType>(entry)(glue, 2, argV,
963 reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()),
964 static_cast<size_t>(OptimizedEntryFrame::CallType::CALL_FUNC));
965 EXPECT_EQ(result, JSTaggedValue(3.0));
966 }
967
HWTEST_F_L0(StubTest,JSCallTest1)968 HWTEST_F_L0(StubTest, JSCallTest1)
969 {
970 auto foo2Entry = thread->GetFastStubEntry(CommonStubCSigns::Foo2AOT);
971 auto foo2target = NewAotFunction(2, foo2Entry);
972 auto glue = thread->GetGlueAddr();
973 int x = 1;
974 int y = 2;
975 JSTaggedType argV[5] = {
976 foo2target.GetRawData(),
977 JSTaggedValue::Undefined().GetRawData(),
978 JSTaggedValue::Undefined().GetRawData(),
979 JSTaggedValue(x).GetRawData(),
980 JSTaggedValue(y).GetRawData(),
981 };
982 auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry);
983 auto result = reinterpret_cast<JSFunctionEntryType>(entry)(glue, 2, argV,
984 reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()),
985 static_cast<size_t>(OptimizedEntryFrame::CallType::CALL_FUNC));
986 EXPECT_EQ(result, JSTaggedValue(3.0));
987 }
988
HWTEST_F_L0(StubTest,JSCallTest2)989 HWTEST_F_L0(StubTest, JSCallTest2)
990 {
991 auto foo1Entry = thread->GetFastStubEntry(CommonStubCSigns::Foo1AOT);
992 auto foo1target = NewAotFunction(2, foo1Entry);
993 auto glue = thread->GetGlueAddr();
994 int x = 1;
995 int y = 2;
996 JSTaggedType argV[5] = {
997 foo1target.GetRawData(),
998 JSTaggedValue::Undefined().GetRawData(),
999 JSTaggedValue::Undefined().GetRawData(),
1000 JSTaggedValue(x).GetRawData(),
1001 JSTaggedValue(y).GetRawData(),
1002 };
1003
1004 auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry);
1005 auto result = reinterpret_cast<JSFunctionEntryType>(entry)(glue, 2, argV,
1006 reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()),
1007 static_cast<size_t>(OptimizedEntryFrame::CallType::CALL_FUNC));
1008 EXPECT_EQ(result, JSTaggedValue(0x7ff9000000000000UL));
1009 }
1010
HWTEST_F_L0(StubTest,JSCallNativeTest)1011 HWTEST_F_L0(StubTest, JSCallNativeTest)
1012 {
1013 auto fooEntry = thread->GetFastStubEntry(CommonStubCSigns::FooNativeAOT);
1014 auto footarget = NewAotFunction(2, fooEntry);
1015 auto glue = thread->GetGlueAddr();
1016 int x = 1;
1017 int y = 2;
1018 JSTaggedType argV[5] = {
1019 footarget.GetRawData(),
1020 JSTaggedValue::Undefined().GetRawData(),
1021 JSTaggedValue::Undefined().GetRawData(),
1022 JSTaggedValue(x).GetRawData(),
1023 JSTaggedValue(y).GetRawData(),
1024 };
1025 auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry);
1026 auto result = reinterpret_cast<JSFunctionEntryType>(entry)(glue, 2, argV,
1027 reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()),
1028 static_cast<size_t>(OptimizedEntryFrame::CallType::CALL_FUNC));
1029 EXPECT_EQ(result, JSTaggedValue::Undefined());
1030 }
1031
HWTEST_F_L0(StubTest,JSCallBoundTest)1032 HWTEST_F_L0(StubTest, JSCallBoundTest)
1033 {
1034 auto fooEntry = thread->GetFastStubEntry(CommonStubCSigns::FooBoundAOT);
1035 auto footarget = NewAotFunction(2, fooEntry);
1036 auto glue = thread->GetGlueAddr();
1037 int x = 1;
1038 int y = 2;
1039 JSTaggedType argV[5] = {
1040 footarget.GetRawData(),
1041 JSTaggedValue::Undefined().GetRawData(),
1042 JSTaggedValue::Undefined().GetRawData(),
1043 JSTaggedValue(x).GetRawData(),
1044 JSTaggedValue(y).GetRawData(),
1045 };
1046
1047 auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry);
1048 auto result = reinterpret_cast<JSFunctionEntryType>(entry)(glue, 2, argV,
1049 reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()),
1050 static_cast<size_t>(OptimizedEntryFrame::CallType::CALL_FUNC));
1051 EXPECT_EQ(result, JSTaggedValue(38.0));
1052 }
1053
1054 // test for proxy method is undefined
HWTEST_F_L0(StubTest,JSCallTest3)1055 HWTEST_F_L0(StubTest, JSCallTest3)
1056 {
1057 auto fooProxyEntry = thread->GetFastStubEntry(CommonStubCSigns::FooProxyAOT);
1058 auto foo2target = NewAotFunction(2, fooProxyEntry);
1059 auto glue = thread->GetGlueAddr();
1060 int x = 1;
1061 int y = 2;
1062 JSTaggedType argV[6] = {
1063 foo2target.GetRawData(),
1064 JSTaggedValue::Undefined().GetRawData(),
1065 JSTaggedValue::Undefined().GetRawData(),
1066 JSTaggedValue(x).GetRawData(),
1067 JSTaggedValue(y).GetRawData(),
1068 JSTaggedValue::Undefined().GetRawData(),
1069 };
1070 JSThread::GlueData::GetCOStubEntriesOffset(false);
1071 JSThread::GlueData::GetCOStubEntriesOffset(true);
1072 auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry);
1073 auto result = reinterpret_cast<JSFunctionEntryType>(entry)(glue, 3, argV,
1074 reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()),
1075 static_cast<size_t>(OptimizedEntryFrame::CallType::CALL_FUNC));
1076 EXPECT_EQ(result, JSTaggedValue(3.0));
1077 }
1078
1079 // test for proxy method isn't undefined
HWTEST_F_L0(StubTest,JSCallTest4)1080 HWTEST_F_L0(StubTest, JSCallTest4)
1081 {
1082 auto fooProxyEntry = thread->GetFastStubEntry(CommonStubCSigns::FooProxy2AOT);
1083 auto foo2target = NewAotFunction(2, fooProxyEntry);
1084 auto glue = thread->GetGlueAddr();
1085 int x = 1;
1086 int y = 2;
1087 JSTaggedType argV[5] = {
1088 foo2target.GetRawData(),
1089 JSTaggedValue::Undefined().GetRawData(),
1090 JSTaggedValue::Undefined().GetRawData(),
1091 JSTaggedValue(x).GetRawData(),
1092 JSTaggedValue(y).GetRawData(),
1093 };
1094 JSThread::GlueData::GetCOStubEntriesOffset(false);
1095 JSThread::GlueData::GetCOStubEntriesOffset(true);
1096 auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry);
1097 [[maybe_unused]] auto result = reinterpret_cast<JSFunctionEntryType>(entry)(glue, 2, argV,
1098 reinterpret_cast<uintptr_t>(thread->GetCurrentSPFrame()),
1099 static_cast<size_t>(OptimizedEntryFrame::CallType::CALL_FUNC));
1100 }
1101
HWTEST_F_L0(StubTest,RelocateTest)1102 HWTEST_F_L0(StubTest, RelocateTest)
1103 {
1104 auto module = stubModule.GetModule();
1105 auto function = stubModule.GetFunction(CommonStubCSigns::TestAbsoluteAddressRelocation);
1106 ecmascript::NativeAreaAllocator allocator;
1107 Circuit netOfGates(&allocator);
1108 CallSignature callSignature;
1109 TestAbsoluteAddressRelocationCallSignature::Initialize(&callSignature);
1110 Stub stub(&callSignature, &netOfGates);
1111 TestAbsoluteAddressRelocationStubBuilder optimizer(&callSignature, stub.GetEnvironment());
1112 stub.SetStubBuilder(&optimizer);
1113 stub.GenerateCircuit(stubModule.GetCompilationConfig());
1114 netOfGates.PrintAllGates();
1115 bool verRes = Verifier::Run(&netOfGates);
1116 ASSERT_TRUE(verRes);
1117 Scheduler::ControlFlowGraph cfg;
1118 Scheduler::Run(&netOfGates, cfg);
1119 PrintCircuitByBasicBlock(cfg, netOfGates);
1120 LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function, stubModule.GetCompilationConfig(),
1121 CallSignature::CallConv::CCallConv);
1122 llvmBuilder.Build();
1123 char *error = nullptr;
1124 LLVMVerifyModule(module, LLVMAbortProcessAction, &error);
1125 LLVMAssembler assembler(module);
1126 assembler.Run(*log);
1127 uint64_t input = 0x111;
1128 auto *ptr =
1129 reinterpret_cast<JSTaggedValue (*)(uint64_t)>(assembler.GetFuncPtrFromCompiledModule(function));
1130 auto loader = thread->GetEcmaVM()->GetAOTFileManager();
1131 auto dataSecAddr = assembler.GetSectionAddr(ElfSecName::DATA);
1132 auto dataSecSize = assembler.GetSectionSize(ElfSecName::DATA);
1133 std::vector<uint64_t> newData;
1134 newData.push_back(input);
1135 loader->RewriteDataSection(dataSecAddr, dataSecSize,
1136 reinterpret_cast<uintptr_t>(newData.data()), newData.size() * sizeof(uint64_t));
1137 auto res = ptr(input);
1138 uint64_t expect = 1;
1139 EXPECT_EQ(res.GetRawData(), expect);
1140 }
1141 #endif
1142 } // namespace panda::test
1143