1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not read this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <gtest/gtest.h>
18 
19 #include "data_type.h"
20 #include "nodes.h"
21 
22 namespace art {
23 
24 // Only runtime types other than void are allowed.
25 static const DataType::Type kTestTypes[] = {
26     DataType::Type::kReference,
27     DataType::Type::kBool,
28     DataType::Type::kInt8,
29     DataType::Type::kUint16,
30     DataType::Type::kInt16,
31     DataType::Type::kInt32,
32     DataType::Type::kInt64,
33     DataType::Type::kFloat32,
34     DataType::Type::kFloat64,
35 };
36 
37 /**
38  * Tests for the SideEffects class.
39  */
40 
41 //
42 // Helper methods.
43 //
44 
testWriteAndReadSanity(SideEffects write,SideEffects read)45 void testWriteAndReadSanity(SideEffects write, SideEffects read) {
46   EXPECT_FALSE(write.DoesNothing());
47   EXPECT_FALSE(read.DoesNothing());
48 
49   EXPECT_TRUE(write.DoesAnyWrite());
50   EXPECT_FALSE(write.DoesAnyRead());
51   EXPECT_FALSE(read.DoesAnyWrite());
52   EXPECT_TRUE(read.DoesAnyRead());
53 
54   // All-dependences.
55   SideEffects all = SideEffects::All();
56   EXPECT_TRUE(all.MayDependOn(write));
57   EXPECT_FALSE(write.MayDependOn(all));
58   EXPECT_FALSE(all.MayDependOn(read));
59   EXPECT_TRUE(read.MayDependOn(all));
60 
61   // None-dependences.
62   SideEffects none = SideEffects::None();
63   EXPECT_FALSE(none.MayDependOn(write));
64   EXPECT_FALSE(write.MayDependOn(none));
65   EXPECT_FALSE(none.MayDependOn(read));
66   EXPECT_FALSE(read.MayDependOn(none));
67 }
68 
testWriteAndReadDependence(SideEffects write,SideEffects read)69 void testWriteAndReadDependence(SideEffects write, SideEffects read) {
70   testWriteAndReadSanity(write, read);
71 
72   // Dependence only in one direction.
73   EXPECT_FALSE(write.MayDependOn(read));
74   EXPECT_TRUE(read.MayDependOn(write));
75 }
76 
testNoWriteAndReadDependence(SideEffects write,SideEffects read)77 void testNoWriteAndReadDependence(SideEffects write, SideEffects read) {
78   testWriteAndReadSanity(write, read);
79 
80   // No dependence in any direction.
81   EXPECT_FALSE(write.MayDependOn(read));
82   EXPECT_FALSE(read.MayDependOn(write));
83 }
84 
85 //
86 // Actual tests.
87 //
88 
TEST(SideEffectsTest,All)89 TEST(SideEffectsTest, All) {
90   SideEffects all = SideEffects::All();
91   EXPECT_TRUE(all.DoesAnyWrite());
92   EXPECT_TRUE(all.DoesAnyRead());
93   EXPECT_FALSE(all.DoesNothing());
94   EXPECT_TRUE(all.DoesAllReadWrite());
95 }
96 
TEST(SideEffectsTest,None)97 TEST(SideEffectsTest, None) {
98   SideEffects none = SideEffects::None();
99   EXPECT_FALSE(none.DoesAnyWrite());
100   EXPECT_FALSE(none.DoesAnyRead());
101   EXPECT_TRUE(none.DoesNothing());
102   EXPECT_FALSE(none.DoesAllReadWrite());
103 }
104 
TEST(SideEffectsTest,DependencesAndNoDependences)105 TEST(SideEffectsTest, DependencesAndNoDependences) {
106   // Apply test to each individual data type.
107   for (DataType::Type type : kTestTypes) {
108     // Same data type and access type: proper write/read dep.
109     testWriteAndReadDependence(
110         SideEffects::FieldWriteOfType(type, false),
111         SideEffects::FieldReadOfType(type, false));
112     testWriteAndReadDependence(
113         SideEffects::ArrayWriteOfType(type),
114         SideEffects::ArrayReadOfType(type));
115     // Same data type but different access type: no write/read dep.
116     testNoWriteAndReadDependence(
117         SideEffects::FieldWriteOfType(type, false),
118         SideEffects::ArrayReadOfType(type));
119     testNoWriteAndReadDependence(
120         SideEffects::ArrayWriteOfType(type),
121         SideEffects::FieldReadOfType(type, false));
122   }
123 }
124 
TEST(SideEffectsTest,NoDependences)125 TEST(SideEffectsTest, NoDependences) {
126   // Different data type, same access type: no write/read dep.
127   testNoWriteAndReadDependence(
128       SideEffects::FieldWriteOfType(DataType::Type::kInt32, false),
129       SideEffects::FieldReadOfType(DataType::Type::kFloat64, false));
130   testNoWriteAndReadDependence(
131       SideEffects::ArrayWriteOfType(DataType::Type::kInt32),
132       SideEffects::ArrayReadOfType(DataType::Type::kFloat64));
133   // Everything different: no write/read dep.
134   testNoWriteAndReadDependence(
135       SideEffects::FieldWriteOfType(DataType::Type::kInt32, false),
136       SideEffects::ArrayReadOfType(DataType::Type::kFloat64));
137   testNoWriteAndReadDependence(
138       SideEffects::ArrayWriteOfType(DataType::Type::kInt32),
139       SideEffects::FieldReadOfType(DataType::Type::kFloat64, false));
140 }
141 
TEST(SideEffectsTest,VolatileDependences)142 TEST(SideEffectsTest, VolatileDependences) {
143   SideEffects volatile_write =
144       SideEffects::FieldWriteOfType(DataType::Type::kInt32, /* is_volatile= */ true);
145   SideEffects any_write =
146       SideEffects::FieldWriteOfType(DataType::Type::kInt32, /* is_volatile= */ false);
147   SideEffects volatile_read =
148       SideEffects::FieldReadOfType(DataType::Type::kInt8, /* is_volatile= */ true);
149   SideEffects any_read =
150       SideEffects::FieldReadOfType(DataType::Type::kInt8, /* is_volatile= */ false);
151 
152   EXPECT_FALSE(volatile_write.MayDependOn(any_read));
153   EXPECT_TRUE(any_read.MayDependOn(volatile_write));
154   EXPECT_TRUE(volatile_write.MayDependOn(any_write));
155   EXPECT_FALSE(any_write.MayDependOn(volatile_write));
156 
157   EXPECT_FALSE(volatile_read.MayDependOn(any_read));
158   EXPECT_TRUE(any_read.MayDependOn(volatile_read));
159   EXPECT_TRUE(volatile_read.MayDependOn(any_write));
160   EXPECT_FALSE(any_write.MayDependOn(volatile_read));
161 }
162 
TEST(SideEffectsTest,SameWidthTypesNoAlias)163 TEST(SideEffectsTest, SameWidthTypesNoAlias) {
164   // Type I/F.
165   testNoWriteAndReadDependence(
166       SideEffects::FieldWriteOfType(DataType::Type::kInt32, /* is_volatile= */ false),
167       SideEffects::FieldReadOfType(DataType::Type::kFloat32, /* is_volatile= */ false));
168   testNoWriteAndReadDependence(
169       SideEffects::ArrayWriteOfType(DataType::Type::kInt32),
170       SideEffects::ArrayReadOfType(DataType::Type::kFloat32));
171   // Type L/D.
172   testNoWriteAndReadDependence(
173       SideEffects::FieldWriteOfType(DataType::Type::kInt64, /* is_volatile= */ false),
174       SideEffects::FieldReadOfType(DataType::Type::kFloat64, /* is_volatile= */ false));
175   testNoWriteAndReadDependence(
176       SideEffects::ArrayWriteOfType(DataType::Type::kInt64),
177       SideEffects::ArrayReadOfType(DataType::Type::kFloat64));
178 }
179 
TEST(SideEffectsTest,AllWritesAndReads)180 TEST(SideEffectsTest, AllWritesAndReads) {
181   SideEffects s = SideEffects::None();
182   // Keep taking the union of different writes and reads.
183   for (DataType::Type type : kTestTypes) {
184     s = s.Union(SideEffects::FieldWriteOfType(type, /* is_volatile= */ false));
185     s = s.Union(SideEffects::ArrayWriteOfType(type));
186     s = s.Union(SideEffects::FieldReadOfType(type, /* is_volatile= */ false));
187     s = s.Union(SideEffects::ArrayReadOfType(type));
188   }
189   EXPECT_TRUE(s.DoesAllReadWrite());
190 }
191 
TEST(SideEffectsTest,GC)192 TEST(SideEffectsTest, GC) {
193   SideEffects can_trigger_gc = SideEffects::CanTriggerGC();
194   SideEffects depends_on_gc = SideEffects::DependsOnGC();
195   SideEffects all_changes = SideEffects::AllChanges();
196   SideEffects all_dependencies = SideEffects::AllDependencies();
197 
198   EXPECT_TRUE(depends_on_gc.MayDependOn(can_trigger_gc));
199   EXPECT_TRUE(depends_on_gc.Union(can_trigger_gc).MayDependOn(can_trigger_gc));
200   EXPECT_FALSE(can_trigger_gc.MayDependOn(depends_on_gc));
201 
202   EXPECT_TRUE(depends_on_gc.MayDependOn(all_changes));
203   EXPECT_TRUE(depends_on_gc.Union(can_trigger_gc).MayDependOn(all_changes));
204   EXPECT_FALSE(can_trigger_gc.MayDependOn(all_changes));
205   EXPECT_FALSE(can_trigger_gc.MayDependOn(can_trigger_gc));
206 
207   EXPECT_TRUE(all_changes.Includes(can_trigger_gc));
208   EXPECT_FALSE(all_changes.Includes(depends_on_gc));
209   EXPECT_TRUE(all_dependencies.Includes(depends_on_gc));
210   EXPECT_FALSE(all_dependencies.Includes(can_trigger_gc));
211 }
212 
TEST(SideEffectsTest,BitStrings)213 TEST(SideEffectsTest, BitStrings) {
214   EXPECT_STREQ(
215       "|||||||",
216       SideEffects::None().ToString().c_str());
217   EXPECT_STREQ(
218       "|GC|DFJISCBZL|DFJISCBZL|GC|DFJISCBZL|DFJISCBZL|",
219       SideEffects::All().ToString().c_str());
220   EXPECT_STREQ(
221       "|||||DFJISCBZL|DFJISCBZL|",
222       SideEffects::AllWrites().ToString().c_str());
223   EXPECT_STREQ(
224       "||DFJISCBZL|DFJISCBZL||||",
225       SideEffects::AllReads().ToString().c_str());
226   EXPECT_STREQ(
227       "||||||L|",
228       SideEffects::FieldWriteOfType(DataType::Type::kReference, false).ToString().c_str());
229   EXPECT_STREQ(
230       "||DFJISCBZL|DFJISCBZL||DFJISCBZL|DFJISCBZL|",
231       SideEffects::FieldWriteOfType(DataType::Type::kReference, true).ToString().c_str());
232   EXPECT_STREQ(
233       "|||||Z||",
234       SideEffects::ArrayWriteOfType(DataType::Type::kBool).ToString().c_str());
235   EXPECT_STREQ(
236       "|||||C||",
237       SideEffects::ArrayWriteOfType(DataType::Type::kUint16).ToString().c_str());
238   EXPECT_STREQ(
239       "|||||S||",
240       SideEffects::ArrayWriteOfType(DataType::Type::kInt16).ToString().c_str());
241   EXPECT_STREQ(
242       "|||B||||",
243       SideEffects::FieldReadOfType(DataType::Type::kInt8, false).ToString().c_str());
244   EXPECT_STREQ(
245       "||D|||||",
246       SideEffects::ArrayReadOfType(DataType::Type::kFloat64).ToString().c_str());
247   EXPECT_STREQ(
248       "||J|||||",
249       SideEffects::ArrayReadOfType(DataType::Type::kInt64).ToString().c_str());
250   EXPECT_STREQ(
251       "||F|||||",
252       SideEffects::ArrayReadOfType(DataType::Type::kFloat32).ToString().c_str());
253   EXPECT_STREQ(
254       "||I|||||",
255       SideEffects::ArrayReadOfType(DataType::Type::kInt32).ToString().c_str());
256   SideEffects s = SideEffects::None();
257   s = s.Union(SideEffects::FieldWriteOfType(DataType::Type::kUint16, /* is_volatile= */ false));
258   s = s.Union(SideEffects::FieldWriteOfType(DataType::Type::kInt64, /* is_volatile= */ false));
259   s = s.Union(SideEffects::ArrayWriteOfType(DataType::Type::kInt16));
260   s = s.Union(SideEffects::FieldReadOfType(DataType::Type::kInt32, /* is_volatile= */ false));
261   s = s.Union(SideEffects::ArrayReadOfType(DataType::Type::kFloat32));
262   s = s.Union(SideEffects::ArrayReadOfType(DataType::Type::kFloat64));
263   EXPECT_STREQ("||DF|I||S|JC|", s.ToString().c_str());
264 }
265 
266 }  // namespace art
267