blob: 24187777f6edc0a4870999d8975c215665db8624 [file] [log] [blame]
xueliang.zhongc239a2b2017-04-27 15:31:37 +01001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use 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 "load_store_analysis.h"
18#include "nodes.h"
19#include "optimizing_unit_test.h"
20
21#include "gtest/gtest.h"
22
23namespace art {
24
25class LoadStoreAnalysisTest : public CommonCompilerTest {
26 public:
27 LoadStoreAnalysisTest() : pool_(), allocator_(&pool_) {
28 graph_ = CreateGraph(&allocator_);
29 }
30
31 ArenaPool pool_;
32 ArenaAllocator allocator_;
33 HGraph* graph_;
34};
35
36TEST_F(LoadStoreAnalysisTest, ArrayHeapLocations) {
37 HBasicBlock* entry = new (&allocator_) HBasicBlock(graph_);
38 graph_->AddBlock(entry);
39 graph_->SetEntryBlock(entry);
40
41 // entry:
42 // array ParameterValue
43 // index ParameterValue
44 // c1 IntConstant
45 // c2 IntConstant
46 // c3 IntConstant
47 // array_get1 ArrayGet [array, c1]
48 // array_get2 ArrayGet [array, c2]
49 // array_set1 ArraySet [array, c1, c3]
50 // array_set2 ArraySet [array, index, c3]
51 HInstruction* array = new (&allocator_) HParameterValue(
52 graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot);
53 HInstruction* index = new (&allocator_) HParameterValue(
54 graph_->GetDexFile(), dex::TypeIndex(1), 1, Primitive::kPrimInt);
55 HInstruction* c1 = graph_->GetIntConstant(1);
56 HInstruction* c2 = graph_->GetIntConstant(2);
57 HInstruction* c3 = graph_->GetIntConstant(3);
58 HInstruction* array_get1 = new (&allocator_) HArrayGet(array, c1, Primitive::kPrimInt, 0);
59 HInstruction* array_get2 = new (&allocator_) HArrayGet(array, c2, Primitive::kPrimInt, 0);
60 HInstruction* array_set1 = new (&allocator_) HArraySet(array, c1, c3, Primitive::kPrimInt, 0);
61 HInstruction* array_set2 = new (&allocator_) HArraySet(array, index, c3, Primitive::kPrimInt, 0);
62 entry->AddInstruction(array);
63 entry->AddInstruction(index);
64 entry->AddInstruction(array_get1);
65 entry->AddInstruction(array_get2);
66 entry->AddInstruction(array_set1);
67 entry->AddInstruction(array_set2);
68
69 // Test HeapLocationCollector initialization.
70 // Should be no heap locations, no operations on the heap.
71 HeapLocationCollector heap_location_collector(graph_);
72 ASSERT_EQ(heap_location_collector.GetNumberOfHeapLocations(), 0U);
73 ASSERT_FALSE(heap_location_collector.HasHeapStores());
74
75 // Test that after visiting the graph_, it must see following heap locations
76 // array[c1], array[c2], array[index]; and it should see heap stores.
77 heap_location_collector.VisitBasicBlock(entry);
78 ASSERT_EQ(heap_location_collector.GetNumberOfHeapLocations(), 3U);
79 ASSERT_TRUE(heap_location_collector.HasHeapStores());
80
81 // Test queries on HeapLocationCollector's ref info and index records.
82 ReferenceInfo* ref = heap_location_collector.FindReferenceInfoOf(array);
83 size_t field_off = HeapLocation::kInvalidFieldOffset;
84 size_t class_def = HeapLocation::kDeclaringClassDefIndexForArrays;
85 size_t loc1 = heap_location_collector.FindHeapLocationIndex(ref, field_off, c1, class_def);
86 size_t loc2 = heap_location_collector.FindHeapLocationIndex(ref, field_off, c2, class_def);
87 size_t loc3 = heap_location_collector.FindHeapLocationIndex(ref, field_off, index, class_def);
88 // must find this reference info for array in HeapLocationCollector.
89 ASSERT_TRUE(ref != nullptr);
90 // must find these heap locations;
91 // and array[1], array[2], array[3] should be different heap locations.
92 ASSERT_TRUE(loc1 != HeapLocationCollector::kHeapLocationNotFound);
93 ASSERT_TRUE(loc2 != HeapLocationCollector::kHeapLocationNotFound);
94 ASSERT_TRUE(loc3 != HeapLocationCollector::kHeapLocationNotFound);
95 ASSERT_TRUE(loc1 != loc2);
96 ASSERT_TRUE(loc2 != loc3);
97 ASSERT_TRUE(loc1 != loc3);
98
99 // Test alias relationships after building aliasing matrix.
100 // array[1] and array[2] clearly should not alias;
101 // array[index] should alias with the others, because index is an unknow value.
102 heap_location_collector.BuildAliasingMatrix();
103 ASSERT_FALSE(heap_location_collector.MayAlias(loc1, loc2));
104 ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc3));
105 ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc3));
106}
107
108TEST_F(LoadStoreAnalysisTest, FieldHeapLocations) {
109 HBasicBlock* entry = new (&allocator_) HBasicBlock(graph_);
110 graph_->AddBlock(entry);
111 graph_->SetEntryBlock(entry);
112
113 // entry:
114 // object ParameterValue
115 // c1 IntConstant
116 // set_field10 InstanceFieldSet [object, c1, 10]
117 // get_field10 InstanceFieldGet [object, 10]
118 // get_field20 InstanceFieldGet [object, 20]
119
120 HInstruction* c1 = graph_->GetIntConstant(1);
121 HInstruction* object = new (&allocator_) HParameterValue(graph_->GetDexFile(),
122 dex::TypeIndex(0),
123 0,
124 Primitive::kPrimNot);
125 HInstanceFieldSet* set_field10 = new (&allocator_) HInstanceFieldSet(object,
126 c1,
127 nullptr,
128 Primitive::kPrimInt,
129 MemberOffset(10),
130 false,
131 kUnknownFieldIndex,
132 kUnknownClassDefIndex,
133 graph_->GetDexFile(),
134 0);
135 HInstanceFieldGet* get_field10 = new (&allocator_) HInstanceFieldGet(object,
136 nullptr,
137 Primitive::kPrimInt,
138 MemberOffset(10),
139 false,
140 kUnknownFieldIndex,
141 kUnknownClassDefIndex,
142 graph_->GetDexFile(),
143 0);
144 HInstanceFieldGet* get_field20 = new (&allocator_) HInstanceFieldGet(object,
145 nullptr,
146 Primitive::kPrimInt,
147 MemberOffset(20),
148 false,
149 kUnknownFieldIndex,
150 kUnknownClassDefIndex,
151 graph_->GetDexFile(),
152 0);
153 entry->AddInstruction(object);
154 entry->AddInstruction(set_field10);
155 entry->AddInstruction(get_field10);
156 entry->AddInstruction(get_field20);
157
158 // Test HeapLocationCollector initialization.
159 // Should be no heap locations, no operations on the heap.
160 HeapLocationCollector heap_location_collector(graph_);
161 ASSERT_EQ(heap_location_collector.GetNumberOfHeapLocations(), 0U);
162 ASSERT_FALSE(heap_location_collector.HasHeapStores());
163
164 // Test that after visiting the graph, it must see following heap locations
165 // object.field10, object.field20 and it should see heap stores.
166 heap_location_collector.VisitBasicBlock(entry);
167 ASSERT_EQ(heap_location_collector.GetNumberOfHeapLocations(), 2U);
168 ASSERT_TRUE(heap_location_collector.HasHeapStores());
169
170 // Test queries on HeapLocationCollector's ref info and index records.
171 ReferenceInfo* ref = heap_location_collector.FindReferenceInfoOf(object);
172 size_t loc1 = heap_location_collector.FindHeapLocationIndex(
173 ref, 10, nullptr, kUnknownClassDefIndex);
174 size_t loc2 = heap_location_collector.FindHeapLocationIndex(
175 ref, 20, nullptr, kUnknownClassDefIndex);
176 // must find references info for object and in HeapLocationCollector.
177 ASSERT_TRUE(ref != nullptr);
178 // must find these heap locations.
179 ASSERT_TRUE(loc1 != HeapLocationCollector::kHeapLocationNotFound);
180 ASSERT_TRUE(loc2 != HeapLocationCollector::kHeapLocationNotFound);
181 // different fields of same object.
182 ASSERT_TRUE(loc1 != loc2);
183 // accesses to different fields of the same object should not alias.
184 ASSERT_FALSE(heap_location_collector.MayAlias(loc1, loc2));
185}
186
187} // namespace art