• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <gtest/gtest.h>
17 
18 #include "assembler/assembly-emitter.h"
19 #include "assembler/assembly-parser.h"
20 #include "bytecode_optimizer/optimize_bytecode.h"
21 #include "runtime/include/class_linker.h"
22 #include "runtime/include/runtime.h"
23 #include "mangling.h"
24 
25 namespace ark::bytecodeopt::test {
26 
27 class BytecodeOptPeepholes : public testing::Test {
28 public:
BytecodeOptPeepholes()29     BytecodeOptPeepholes()
30     {
31         RuntimeOptions options;
32         // NOLINTNEXTLINE(readability-magic-numbers)
33         options.SetHeapSizeLimit(128_MB);
34         options.SetShouldLoadBootPandaFiles(false);
35         options.SetShouldInitializeIntrinsics(false);
36         Logger::InitializeDummyLogging();
37 
38         Runtime::Create(options);
39         thread_ = ark::MTManagedThread::GetCurrent();
40         thread_->ManagedCodeBegin();
41     }
42 
~BytecodeOptPeepholes()43     ~BytecodeOptPeepholes() override
44     {
45         thread_->ManagedCodeEnd();
46         Runtime::Destroy();
47     }
48 
49     NO_COPY_SEMANTIC(BytecodeOptPeepholes);
50     NO_MOVE_SEMANTIC(BytecodeOptPeepholes);
51 
52 protected:
53     // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes)
54     ark::MTManagedThread *thread_;
55 };
56 
57 // CC-OFFNXT(huge_method[C++], G.FUN.01-CPP) solid logic
TEST_F(BytecodeOptPeepholes,TryBlock)58 TEST_F(BytecodeOptPeepholes, TryBlock)
59 {
60     pandasm::Parser p;
61 
62     auto source = R"(
63     .record E {}
64     .record R {
65         u1 field
66     }
67 
68     .function void R.ctor(R a0) <ctor> {
69         newobj v0, E
70         throw v0
71     }
72 
73     .function u8 try_catch() {
74     try_begin:
75         movi v1, 0x1
76         newobj v0, R
77         movi v1, 0x2
78         call.short R.ctor, v0
79     try_end:
80         ldai 0x0
81         return
82     catch_all:
83         lda v1
84         return
85     .catchall try_begin, try_end, catch_all
86     }
87     )";
88 
89     auto res = p.Parse(source);
90     auto &program = res.Value();
91     pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps;
92     std::string fileName = "bc_peepholes";
93     auto piece = pandasm::AsmEmitter::Emit(fileName, program, nullptr, &maps);
94     ASSERT_NE(piece, false);
95 
96     EXPECT_TRUE(OptimizeBytecode(&program, &maps, fileName, false, true));
97 
98     // Check if there is initobj instruction in the bytecode
99     bool containsInitobj = false;
100     const auto sigTryCatch = pandasm::GetFunctionSignatureFromName("try_catch", {});
101     for (const auto &inst : program.functionStaticTable.at(sigTryCatch).ins) {
102         if (inst.opcode == pandasm::Opcode::INITOBJ) {
103             containsInitobj = true;
104         }
105     }
106     EXPECT_FALSE(containsInitobj);
107 
108     auto pf = pandasm::AsmEmitter::Emit(program);
109     ASSERT_NE(pf, nullptr);
110 
111     ClassLinker *classLinker = Runtime::GetCurrent()->GetClassLinker();
112     classLinker->AddPandaFile(std::move(pf));
113     auto *extension = classLinker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY);
114     PandaString descriptor;
115 
116     auto *klass = extension->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("_GLOBAL"), &descriptor));
117     ASSERT_NE(klass, nullptr);
118 
119     Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("try_catch"));
120     ASSERT_NE(method, nullptr);
121 
122     std::vector<Value> args;
123     args.emplace_back(Value(1U));
124     Value v = method->Invoke(ManagedThread::GetCurrent(), args.data());
125     EXPECT_EQ(v.GetAsLong(), 0x2U);
126 }
127 
128 }  // namespace ark::bytecodeopt::test
129