• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "bytecodeopt_peepholes.h"
17 #include "common.h"
18 #include "compiler/optimizer/optimizations/cleanup.h"
19 
20 namespace panda::bytecodeopt::test {
21 
TEST_F(IrBuilderTest,PeepholesTryBlockInstBetween)22 TEST_F(IrBuilderTest, PeepholesTryBlockInstBetween)
23 {
24     auto source = R"(
25     .record E {}
26     .record R {
27         u1 field
28     }
29 
30     .function void R.ctor(R a0) <ctor> {
31         newobj v0, E
32         throw v0
33     }
34 
35     .function u8 main() {
36     try_begin:
37         movi v1, 0x1
38         newobj v0, R
39         movi v1, 0x2
40         call.short R.ctor, v0
41     try_end:
42         ldai 0x0
43         return
44     catch_all:
45         lda v1
46         return
47     .catchall try_begin, try_end, catch_all
48     }
49     )";
50     ASSERT_TRUE(ParseToGraph(source, "main"));
51 
52     EXPECT_FALSE(GetGraph()->RunPass<BytecodeOptPeepholes>());
53 }
54 
TEST_F(IrBuilderTest,PeepholesTryBlockNoInstBetween)55 TEST_F(IrBuilderTest, PeepholesTryBlockNoInstBetween)
56 {
57     auto source = R"(
58     .record E {}
59     .record R {
60         u1 field
61     }
62 
63     .function void R.ctor(R a0) <ctor> {
64         newobj v0, E
65         throw v0
66     }
67 
68     .function u8 main() {
69     try_begin:
70         movi v1, 0x1
71         newobj v0, R
72         call.short R.ctor, v0
73     try_end:
74         ldai 0x0
75         return
76     catch_all:
77         lda v1
78         return
79     .catchall try_begin, try_end, catch_all
80     }
81     )";
82     ASSERT_TRUE(ParseToGraph(source, "main"));
83 
84     EXPECT_TRUE(GetGraph()->RunPass<BytecodeOptPeepholes>());
85 }
86 
87 // TODO(aromanov): enable
TEST_F(CommonTest,DISABLED_NoNullCheck)88 TEST_F(CommonTest, DISABLED_NoNullCheck)
89 {
90     RuntimeInterfaceMock runtime(0);
91     auto graph = CreateEmptyGraph();
92     graph->SetRuntime(&runtime);
93     GRAPH(graph)
94     {
95         using namespace compiler::DataType;
96         CONSTANT(6, 0);
97         BASIC_BLOCK(2, -1)
98         {
99             INST(0, Opcode::SaveState).NoVregs();
100             INST(1, Opcode::LoadAndInitClass).ref().Inputs(0).TypeId(68);
101             INST(2, Opcode::NewObject).ref().Inputs(1, 0).TypeId(68);
102             INST(3, Opcode::SaveState).NoVregs();
103             INST(5, Opcode::CallStatic).v0id().Inputs({{REFERENCE, 2}, {NO_TYPE, 3}});
104             INST(7, Opcode::Return).s32().Inputs(6);
105         }
106     }
107 
108     EXPECT_TRUE(graph->RunPass<BytecodeOptPeepholes>());
109     EXPECT_TRUE(graph->RunPass<compiler::Cleanup>());
110 
111     auto after = CreateEmptyGraph();
112     GRAPH(after)
113     {
114         using namespace compiler::DataType;
115         CONSTANT(6, 0);
116         BASIC_BLOCK(2, -1)
117         {
118             INST(0, Opcode::SaveState).NoVregs();
119             INST(1, Opcode::LoadAndInitClass).ref().Inputs(0).TypeId(68);
120             INST(3, Opcode::SaveState).NoVregs();
121             INST(8, Opcode::InitObject).ref().Inputs({{REFERENCE, 1}, {NO_TYPE, 3}});
122             INST(7, Opcode::Return).s32().Inputs(6);
123         }
124     }
125 
126     EXPECT_TRUE(GraphComparator().Compare(graph, after));
127 }
128 
129 // TODO(aromanov): enable
TEST_F(CommonTest,DISABLED_NotRelatedNullCheck)130 TEST_F(CommonTest, DISABLED_NotRelatedNullCheck)
131 {
132     RuntimeInterfaceMock runtime(1);
133     auto graph = CreateEmptyGraph();
134     graph->SetRuntime(&runtime);
135     GRAPH(graph)
136     {
137         using namespace compiler::DataType;
138         PARAMETER(10, 0).ref();
139         CONSTANT(6, 0);
140         BASIC_BLOCK(2, -1)
141         {
142             INST(0, Opcode::SaveState).NoVregs();
143             INST(1, Opcode::LoadAndInitClass).ref().Inputs(0);
144             INST(2, Opcode::NewObject).ref().Inputs(1, 0);
145             INST(3, Opcode::SaveState).NoVregs();
146             INST(4, Opcode::NullCheck).ref().Inputs(10, 3);
147             INST(5, Opcode::CallStatic).v0id().Inputs({{REFERENCE, 2}, {NO_TYPE, 3}});
148             INST(7, Opcode::Return).s32().Inputs(6);
149         }
150     }
151 
152     EXPECT_FALSE(graph->RunPass<BytecodeOptPeepholes>());
153 }
154 
TEST_F(CommonTest,CallStaticOtherBasicBlock)155 TEST_F(CommonTest, CallStaticOtherBasicBlock)
156 {
157     RuntimeInterfaceMock runtime(1);
158     auto graph = CreateEmptyGraph();
159     graph->SetRuntime(&runtime);
160     GRAPH(graph)
161     {
162         using namespace compiler::DataType;
163         PARAMETER(10, 0).ref();
164         CONSTANT(6, 0);
165         BASIC_BLOCK(2, 3)
166         {
167             INST(0, Opcode::SaveState).NoVregs();
168             INST(1, Opcode::LoadAndInitClass).ref().Inputs(0);
169             INST(2, Opcode::NewObject).ref().Inputs(1, 0);
170             INST(3, Opcode::SaveState).NoVregs();
171         }
172         BASIC_BLOCK(3, -1)
173         {
174             INST(5, Opcode::CallStatic).v0id().Inputs({{REFERENCE, 2}, {NO_TYPE, 3}});
175             INST(7, Opcode::Return).s32().Inputs(6);
176         }
177     }
178 
179     EXPECT_FALSE(graph->RunPass<BytecodeOptPeepholes>());
180 }
181 
182 // TODO(aromanov): enable
TEST_F(CommonTest,DISABLED_NoSaveStateNullCheckAfterNewObject)183 TEST_F(CommonTest, DISABLED_NoSaveStateNullCheckAfterNewObject)
184 {
185     RuntimeInterfaceMock runtime(0);
186     auto graph = CreateEmptyGraph();
187     graph->SetRuntime(&runtime);
188     GRAPH(graph)
189     {
190         using namespace compiler::DataType;
191         BASIC_BLOCK(2, -1)
192         {
193             INST(0, Opcode::SaveState).NoVregs();
194             INST(1, Opcode::LoadAndInitClass).ref().Inputs(0);
195             INST(2, Opcode::NewObject).ref().Inputs(1, 0);
196             CONSTANT(3, 0).s32();
197             INST(4, Opcode::SaveState).NoVregs();
198             INST(5, Opcode::CallStatic).v0id().Inputs({{REFERENCE, 2}, {NO_TYPE, 4}});
199             INST(6, Opcode::ReturnVoid).v0id();
200         }
201     }
202 
203     EXPECT_FALSE(graph->RunPass<BytecodeOptPeepholes>());
204 }
205 
TEST_F(CommonTest,CallConstructorOtherClass)206 TEST_F(CommonTest, CallConstructorOtherClass)
207 {
208     RuntimeInterfaceMock runtime(1, false);
209     auto graph = CreateEmptyGraph();
210     graph->SetRuntime(&runtime);
211     GRAPH(graph)
212     {
213         using namespace compiler::DataType;
214         PARAMETER(10, 0).ref();
215         CONSTANT(6, 0);
216         BASIC_BLOCK(2, -1)
217         {
218             INST(0, Opcode::SaveState).NoVregs();
219             INST(1, Opcode::LoadAndInitClass).ref().Inputs(0);
220             INST(2, Opcode::NewObject).ref().Inputs(1, 0);
221             INST(3, Opcode::SaveState).NoVregs();
222             INST(5, Opcode::CallStatic).v0id().Inputs({{REFERENCE, 2}, {NO_TYPE, 3}});
223             INST(7, Opcode::Return).s32().Inputs(6);
224         }
225     }
226 
227     EXPECT_FALSE(graph->RunPass<BytecodeOptPeepholes>());
228 }
229 
230 }  // namespace panda::bytecodeopt::test
231