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 #include "nodes.h"
19 #include "primitive.h"
20
21 namespace art {
22
23 /**
24 * Tests for the SideEffects class.
25 */
26
27 //
28 // Helper methods.
29 //
30
testWriteAndReadSanity(SideEffects write,SideEffects read)31 void testWriteAndReadSanity(SideEffects write, SideEffects read) {
32 EXPECT_FALSE(write.DoesNothing());
33 EXPECT_FALSE(read.DoesNothing());
34
35 EXPECT_TRUE(write.DoesAnyWrite());
36 EXPECT_FALSE(write.DoesAnyRead());
37 EXPECT_FALSE(read.DoesAnyWrite());
38 EXPECT_TRUE(read.DoesAnyRead());
39
40 // All-dependences.
41 SideEffects all = SideEffects::All();
42 EXPECT_TRUE(all.MayDependOn(write));
43 EXPECT_FALSE(write.MayDependOn(all));
44 EXPECT_FALSE(all.MayDependOn(read));
45 EXPECT_TRUE(read.MayDependOn(all));
46
47 // None-dependences.
48 SideEffects none = SideEffects::None();
49 EXPECT_FALSE(none.MayDependOn(write));
50 EXPECT_FALSE(write.MayDependOn(none));
51 EXPECT_FALSE(none.MayDependOn(read));
52 EXPECT_FALSE(read.MayDependOn(none));
53 }
54
testWriteAndReadDependence(SideEffects write,SideEffects read)55 void testWriteAndReadDependence(SideEffects write, SideEffects read) {
56 testWriteAndReadSanity(write, read);
57
58 // Dependence only in one direction.
59 EXPECT_FALSE(write.MayDependOn(read));
60 EXPECT_TRUE(read.MayDependOn(write));
61 }
62
testNoWriteAndReadDependence(SideEffects write,SideEffects read)63 void testNoWriteAndReadDependence(SideEffects write, SideEffects read) {
64 testWriteAndReadSanity(write, read);
65
66 // No dependence in any direction.
67 EXPECT_FALSE(write.MayDependOn(read));
68 EXPECT_FALSE(read.MayDependOn(write));
69 }
70
71 //
72 // Actual tests.
73 //
74
TEST(SideEffectsTest,All)75 TEST(SideEffectsTest, All) {
76 SideEffects all = SideEffects::All();
77 EXPECT_TRUE(all.DoesAnyWrite());
78 EXPECT_TRUE(all.DoesAnyRead());
79 EXPECT_FALSE(all.DoesNothing());
80 EXPECT_TRUE(all.DoesAllReadWrite());
81 }
82
TEST(SideEffectsTest,None)83 TEST(SideEffectsTest, None) {
84 SideEffects none = SideEffects::None();
85 EXPECT_FALSE(none.DoesAnyWrite());
86 EXPECT_FALSE(none.DoesAnyRead());
87 EXPECT_TRUE(none.DoesNothing());
88 EXPECT_FALSE(none.DoesAllReadWrite());
89 }
90
TEST(SideEffectsTest,DependencesAndNoDependences)91 TEST(SideEffectsTest, DependencesAndNoDependences) {
92 // Apply test to each individual primitive type.
93 for (Primitive::Type type = Primitive::kPrimNot;
94 type < Primitive::kPrimVoid;
95 type = Primitive::Type(type + 1)) {
96 // Same primitive type and access type: proper write/read dep.
97 testWriteAndReadDependence(
98 SideEffects::FieldWriteOfType(type, false),
99 SideEffects::FieldReadOfType(type, false));
100 testWriteAndReadDependence(
101 SideEffects::ArrayWriteOfType(type),
102 SideEffects::ArrayReadOfType(type));
103 // Same primitive type but different access type: no write/read dep.
104 testNoWriteAndReadDependence(
105 SideEffects::FieldWriteOfType(type, false),
106 SideEffects::ArrayReadOfType(type));
107 testNoWriteAndReadDependence(
108 SideEffects::ArrayWriteOfType(type),
109 SideEffects::FieldReadOfType(type, false));
110 }
111 }
112
TEST(SideEffectsTest,NoDependences)113 TEST(SideEffectsTest, NoDependences) {
114 // Different primitive type, same access type: no write/read dep.
115 testNoWriteAndReadDependence(
116 SideEffects::FieldWriteOfType(Primitive::kPrimInt, false),
117 SideEffects::FieldReadOfType(Primitive::kPrimDouble, false));
118 testNoWriteAndReadDependence(
119 SideEffects::ArrayWriteOfType(Primitive::kPrimInt),
120 SideEffects::ArrayReadOfType(Primitive::kPrimDouble));
121 // Everything different: no write/read dep.
122 testNoWriteAndReadDependence(
123 SideEffects::FieldWriteOfType(Primitive::kPrimInt, false),
124 SideEffects::ArrayReadOfType(Primitive::kPrimDouble));
125 testNoWriteAndReadDependence(
126 SideEffects::ArrayWriteOfType(Primitive::kPrimInt),
127 SideEffects::FieldReadOfType(Primitive::kPrimDouble, false));
128 }
129
TEST(SideEffectsTest,VolatileDependences)130 TEST(SideEffectsTest, VolatileDependences) {
131 SideEffects volatile_write =
132 SideEffects::FieldWriteOfType(Primitive::kPrimInt, /* is_volatile */ true);
133 SideEffects any_write =
134 SideEffects::FieldWriteOfType(Primitive::kPrimInt, /* is_volatile */ false);
135 SideEffects volatile_read =
136 SideEffects::FieldReadOfType(Primitive::kPrimByte, /* is_volatile */ true);
137 SideEffects any_read =
138 SideEffects::FieldReadOfType(Primitive::kPrimByte, /* is_volatile */ false);
139
140 EXPECT_FALSE(volatile_write.MayDependOn(any_read));
141 EXPECT_TRUE(any_read.MayDependOn(volatile_write));
142 EXPECT_TRUE(volatile_write.MayDependOn(any_write));
143 EXPECT_FALSE(any_write.MayDependOn(volatile_write));
144
145 EXPECT_FALSE(volatile_read.MayDependOn(any_read));
146 EXPECT_TRUE(any_read.MayDependOn(volatile_read));
147 EXPECT_TRUE(volatile_read.MayDependOn(any_write));
148 EXPECT_FALSE(any_write.MayDependOn(volatile_read));
149 }
150
TEST(SideEffectsTest,SameWidthTypes)151 TEST(SideEffectsTest, SameWidthTypes) {
152 // Type I/F.
153 testWriteAndReadDependence(
154 SideEffects::FieldWriteOfType(Primitive::kPrimInt, /* is_volatile */ false),
155 SideEffects::FieldReadOfType(Primitive::kPrimFloat, /* is_volatile */ false));
156 testWriteAndReadDependence(
157 SideEffects::ArrayWriteOfType(Primitive::kPrimInt),
158 SideEffects::ArrayReadOfType(Primitive::kPrimFloat));
159 // Type L/D.
160 testWriteAndReadDependence(
161 SideEffects::FieldWriteOfType(Primitive::kPrimLong, /* is_volatile */ false),
162 SideEffects::FieldReadOfType(Primitive::kPrimDouble, /* is_volatile */ false));
163 testWriteAndReadDependence(
164 SideEffects::ArrayWriteOfType(Primitive::kPrimLong),
165 SideEffects::ArrayReadOfType(Primitive::kPrimDouble));
166 }
167
TEST(SideEffectsTest,AllWritesAndReads)168 TEST(SideEffectsTest, AllWritesAndReads) {
169 SideEffects s = SideEffects::None();
170 // Keep taking the union of different writes and reads.
171 for (Primitive::Type type = Primitive::kPrimNot;
172 type < Primitive::kPrimVoid;
173 type = Primitive::Type(type + 1)) {
174 s = s.Union(SideEffects::FieldWriteOfType(type, /* is_volatile */ false));
175 s = s.Union(SideEffects::ArrayWriteOfType(type));
176 s = s.Union(SideEffects::FieldReadOfType(type, /* is_volatile */ false));
177 s = s.Union(SideEffects::ArrayReadOfType(type));
178 }
179 EXPECT_TRUE(s.DoesAllReadWrite());
180 }
181
TEST(SideEffectsTest,GC)182 TEST(SideEffectsTest, GC) {
183 SideEffects can_trigger_gc = SideEffects::CanTriggerGC();
184 SideEffects depends_on_gc = SideEffects::DependsOnGC();
185 SideEffects all_changes = SideEffects::AllChanges();
186 SideEffects all_dependencies = SideEffects::AllDependencies();
187
188 EXPECT_TRUE(depends_on_gc.MayDependOn(can_trigger_gc));
189 EXPECT_TRUE(depends_on_gc.Union(can_trigger_gc).MayDependOn(can_trigger_gc));
190 EXPECT_FALSE(can_trigger_gc.MayDependOn(depends_on_gc));
191
192 EXPECT_TRUE(depends_on_gc.MayDependOn(all_changes));
193 EXPECT_TRUE(depends_on_gc.Union(can_trigger_gc).MayDependOn(all_changes));
194 EXPECT_FALSE(can_trigger_gc.MayDependOn(all_changes));
195
196 EXPECT_TRUE(all_changes.Includes(can_trigger_gc));
197 EXPECT_FALSE(all_changes.Includes(depends_on_gc));
198 EXPECT_TRUE(all_dependencies.Includes(depends_on_gc));
199 EXPECT_FALSE(all_dependencies.Includes(can_trigger_gc));
200 }
201
TEST(SideEffectsTest,BitStrings)202 TEST(SideEffectsTest, BitStrings) {
203 EXPECT_STREQ(
204 "|||||||",
205 SideEffects::None().ToString().c_str());
206 EXPECT_STREQ(
207 "|GC|DFJISCBZL|DFJISCBZL|GC|DFJISCBZL|DFJISCBZL|",
208 SideEffects::All().ToString().c_str());
209 EXPECT_STREQ(
210 "|||||DFJISCBZL|DFJISCBZL|",
211 SideEffects::AllWrites().ToString().c_str());
212 EXPECT_STREQ(
213 "||DFJISCBZL|DFJISCBZL||||",
214 SideEffects::AllReads().ToString().c_str());
215 EXPECT_STREQ(
216 "||||||L|",
217 SideEffects::FieldWriteOfType(Primitive::kPrimNot, false).ToString().c_str());
218 EXPECT_STREQ(
219 "|||||Z||",
220 SideEffects::ArrayWriteOfType(Primitive::kPrimBoolean).ToString().c_str());
221 EXPECT_STREQ(
222 "|||B||||",
223 SideEffects::FieldReadOfType(Primitive::kPrimByte, false).ToString().c_str());
224 EXPECT_STREQ(
225 "||DJ|||||", // note: DJ alias
226 SideEffects::ArrayReadOfType(Primitive::kPrimDouble).ToString().c_str());
227 SideEffects s = SideEffects::None();
228 s = s.Union(SideEffects::FieldWriteOfType(Primitive::kPrimChar, /* is_volatile */ false));
229 s = s.Union(SideEffects::FieldWriteOfType(Primitive::kPrimLong, /* is_volatile */ false));
230 s = s.Union(SideEffects::ArrayWriteOfType(Primitive::kPrimShort));
231 s = s.Union(SideEffects::FieldReadOfType(Primitive::kPrimInt, /* is_volatile */ false));
232 s = s.Union(SideEffects::ArrayReadOfType(Primitive::kPrimFloat));
233 s = s.Union(SideEffects::ArrayReadOfType(Primitive::kPrimDouble));
234 EXPECT_STREQ(
235 "||DFJI|FI||S|DJC|", // note: DJ/FI alias.
236 s.ToString().c_str());
237 }
238
239 } // namespace art
240