• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2024 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 
TEST_F(BytecodeOptPeepholes,TryBlock)57 TEST_F(BytecodeOptPeepholes, TryBlock)
58 {
59     pandasm::Parser p;
60 
61     auto source = R"(
62     .record E {}
63     .record R {
64         u1 field
65     }
66 
67     .function void R.ctor(R a0) <ctor> {
68         newobj v0, E
69         throw v0
70     }
71 
72     .function u8 try_catch() {
73     try_begin:
74         movi v1, 0x1
75         newobj v0, R
76         movi v1, 0x2
77         call.short R.ctor, v0
78     try_end:
79         ldai 0x0
80         return
81     catch_all:
82         lda v1
83         return
84     .catchall try_begin, try_end, catch_all
85     }
86     )";
87 
88     auto res = p.Parse(source);
89     auto &program = res.Value();
90     pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps;
91     std::string fileName = "bc_peepholes";
92     auto piece = pandasm::AsmEmitter::Emit(fileName, program, nullptr, &maps);
93     ASSERT_NE(piece, false);
94 
95     EXPECT_TRUE(OptimizeBytecode(&program, &maps, fileName, false, true));
96 
97     // Check if there is initobj instruction in the bytecode
98     bool containsInitobj = false;
99     const auto sigTryCatch = pandasm::GetFunctionSignatureFromName("try_catch", {});
100     for (const auto &inst : program.functionTable.at(sigTryCatch).ins) {
101         if (inst.opcode == pandasm::Opcode::INITOBJ) {
102             containsInitobj = true;
103         }
104     }
105     EXPECT_FALSE(containsInitobj);
106 
107     auto pf = pandasm::AsmEmitter::Emit(program);
108     ASSERT_NE(pf, nullptr);
109 
110     ClassLinker *classLinker = Runtime::GetCurrent()->GetClassLinker();
111     classLinker->AddPandaFile(std::move(pf));
112     auto *extension = classLinker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY);
113     PandaString descriptor;
114 
115     auto *klass = extension->GetClass(ClassHelper::GetDescriptor(utf::CStringAsMutf8("_GLOBAL"), &descriptor));
116     ASSERT_NE(klass, nullptr);
117 
118     Method *method = klass->GetDirectMethod(utf::CStringAsMutf8("try_catch"));
119     ASSERT_NE(method, nullptr);
120 
121     std::vector<Value> args;
122     args.emplace_back(Value(1U));
123     Value v = method->Invoke(ManagedThread::GetCurrent(), args.data());
124     EXPECT_EQ(v.GetAsLong(), 0x2U);
125 }
126 
127 }  // namespace ark::bytecodeopt::test
128