• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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