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