1 /*
2 * Copyright (C) 2012 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 "reg_type.h"
18
19 #include <set>
20
21 #include "base/bit_vector.h"
22 #include "base/casts.h"
23 #include "base/scoped_arena_allocator.h"
24 #include "common_runtime_test.h"
25 #include "compiler_callbacks.h"
26 #include "dex/test_dex_file_builder.h"
27 #include "reg_type-inl.h"
28 #include "reg_type_cache-inl.h"
29 #include "reg_type_test_utils.h"
30 #include "scoped_thread_state_change-inl.h"
31 #include "thread-current-inl.h"
32
33 namespace art HIDDEN {
34 namespace verifier {
35
36 class RegTypeTest : public CommonRuntimeTest {
37 protected:
RegTypeTest()38 RegTypeTest() {
39 use_boot_image_ = true; // Make the Runtime creation cheaper.
40 }
41
SetUp()42 void SetUp() override {
43 CommonRuntimeTest::SetUp();
44
45 // Build a fake `DexFile` with some descriptors.
46 static const char* const descriptors[] = {
47 // References.
48 "Ljava/lang/Object;", "Ljava/lang/String;", "LNonExistent;",
49 // Primitives and `void`.
50 "Z", "B", "C", "S", "I", "J", "F", "D", "V"
51 };
52 TestDexFileBuilder builder;
53 for (const char* descriptor : descriptors) {
54 builder.AddType(descriptor);
55 }
56 dex_file_ = builder.Build("arbitrary-location");
57 }
58
59 static constexpr size_t kNumConstTypes = RegType::Kind::kNull - RegType::Kind::kZero + 1;
60
GetConstRegTypes(const RegTypeCache & cache)61 std::array<const RegType*, kNumConstTypes> GetConstRegTypes(const RegTypeCache& cache)
62 REQUIRES_SHARED(Locks::mutator_lock_) {
63 return {
64 &cache.Zero(),
65 &cache.BooleanConstant(),
66 &cache.PositiveByteConstant(),
67 &cache.PositiveShortConstant(),
68 &cache.CharConstant(),
69 &cache.ByteConstant(),
70 &cache.ShortConstant(),
71 &cache.IntegerConstant(),
72 &cache.ConstantLo(),
73 &cache.ConstantHi(),
74 &cache.Null(),
75 };
76 };
77
78 std::unique_ptr<const DexFile> dex_file_;
79 };
80
TEST_F(RegTypeTest,Constants)81 TEST_F(RegTypeTest, Constants) {
82 // Tests creating constant types.
83 ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
84 ScopedObjectAccess soa(Thread::Current());
85 ScopedNullHandle<mirror::ClassLoader> loader;
86 RegTypeCache cache(soa.Self(), class_linker_, arena_pool, loader, dex_file_.get());
87 std::array<const RegType*, kNumConstTypes> const_reg_types = GetConstRegTypes(cache);
88
89 for (size_t i = 0; i != kNumConstTypes; ++i) {
90 EXPECT_TRUE(const_reg_types[i]->IsConstantTypes());
91 }
92
93 for (size_t i = 0; i != kNumConstTypes; ++i) {
94 for (size_t j = 0; j != kNumConstTypes; ++j) {
95 EXPECT_EQ(i == j, const_reg_types[i]->Equals(*(const_reg_types[j]))) << i << " " << j;
96 }
97 }
98 }
99
TEST_F(RegTypeTest,Pairs)100 TEST_F(RegTypeTest, Pairs) {
101 ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
102 ScopedObjectAccess soa(Thread::Current());
103 ScopedNullHandle<mirror::ClassLoader> loader;
104 RegTypeCache cache(soa.Self(), class_linker_, arena_pool, loader, dex_file_.get());
105 int64_t val = static_cast<int32_t>(1234);
106 const RegType& const_lo = cache.ConstantLo();
107 const RegType& const_hi = cache.ConstantHi();
108 const RegType& long_lo = cache.LongLo();
109 const RegType& long_hi = cache.LongHi();
110 const RegType& int_const = cache.IntegerConstant();
111 // Check the expectations for types.
112 EXPECT_TRUE(const_lo.IsLowHalf());
113 EXPECT_FALSE(const_hi.IsLowHalf());
114 EXPECT_FALSE(const_lo.IsHighHalf());
115 EXPECT_TRUE(const_hi.IsHighHalf());
116 EXPECT_TRUE(const_lo.IsLongTypes());
117 EXPECT_FALSE(const_hi.IsLongTypes());
118 EXPECT_FALSE(const_lo.IsLongHighTypes());
119 EXPECT_TRUE(const_hi.IsLongHighTypes());
120 EXPECT_TRUE(long_lo.IsLowHalf());
121 EXPECT_FALSE(long_hi.IsLowHalf());
122 EXPECT_FALSE(long_lo.IsHighHalf());
123 EXPECT_TRUE(long_hi.IsHighHalf());
124 EXPECT_TRUE(long_lo.IsLongTypes());
125 EXPECT_FALSE(long_hi.IsLongTypes());
126 EXPECT_FALSE(long_lo.IsLongHighTypes());
127 EXPECT_TRUE(long_hi.IsLongHighTypes());
128 // Check Pairing.
129 EXPECT_FALSE(const_lo.CheckWidePair(const_lo));
130 EXPECT_TRUE(const_lo.CheckWidePair(const_hi));
131 EXPECT_FALSE(const_lo.CheckWidePair(long_lo));
132 EXPECT_FALSE(const_lo.CheckWidePair(long_hi));
133 EXPECT_FALSE(const_lo.CheckWidePair(int_const));
134 EXPECT_FALSE(const_hi.CheckWidePair(const_lo));
135 EXPECT_FALSE(const_hi.CheckWidePair(const_hi));
136 EXPECT_FALSE(const_hi.CheckWidePair(long_lo));
137 EXPECT_FALSE(const_hi.CheckWidePair(long_hi));
138 EXPECT_FALSE(const_hi.CheckWidePair(int_const));
139 EXPECT_FALSE(long_lo.CheckWidePair(const_lo));
140 EXPECT_FALSE(long_lo.CheckWidePair(const_hi));
141 EXPECT_FALSE(long_lo.CheckWidePair(long_lo));
142 EXPECT_TRUE(long_lo.CheckWidePair(long_hi));
143 EXPECT_FALSE(long_lo.CheckWidePair(int_const));
144 EXPECT_FALSE(long_hi.CheckWidePair(const_lo));
145 EXPECT_FALSE(long_hi.CheckWidePair(const_hi));
146 EXPECT_FALSE(long_hi.CheckWidePair(long_lo));
147 EXPECT_FALSE(long_hi.CheckWidePair(long_hi));
148 EXPECT_FALSE(long_hi.CheckWidePair(int_const));
149 // Test Merging.
150 EXPECT_TRUE((long_lo.Merge(const_lo, &cache, /* verifier= */ nullptr)).IsLongTypes());
151 EXPECT_TRUE((long_hi.Merge(const_hi, &cache, /* verifier= */ nullptr)).IsLongHighTypes());
152 }
153
TEST_F(RegTypeTest,Primitives)154 TEST_F(RegTypeTest, Primitives) {
155 ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
156 ScopedObjectAccess soa(Thread::Current());
157 ScopedNullHandle<mirror::ClassLoader> loader;
158 RegTypeCache cache(soa.Self(), class_linker_, arena_pool, loader, dex_file_.get());
159
160 const RegType& bool_reg_type = cache.Boolean();
161 EXPECT_FALSE(bool_reg_type.IsUndefined());
162 EXPECT_FALSE(bool_reg_type.IsConflict());
163 EXPECT_FALSE(bool_reg_type.IsConstantTypes());
164 EXPECT_TRUE(bool_reg_type.IsBoolean());
165 EXPECT_FALSE(bool_reg_type.IsByte());
166 EXPECT_FALSE(bool_reg_type.IsChar());
167 EXPECT_FALSE(bool_reg_type.IsShort());
168 EXPECT_FALSE(bool_reg_type.IsInteger());
169 EXPECT_FALSE(bool_reg_type.IsLongLo());
170 EXPECT_FALSE(bool_reg_type.IsFloat());
171 EXPECT_FALSE(bool_reg_type.IsDoubleLo());
172 EXPECT_FALSE(bool_reg_type.IsReference());
173 EXPECT_FALSE(bool_reg_type.IsLowHalf());
174 EXPECT_FALSE(bool_reg_type.IsHighHalf());
175 EXPECT_FALSE(bool_reg_type.IsLongOrDoubleTypes());
176 EXPECT_FALSE(bool_reg_type.IsReferenceTypes());
177 EXPECT_TRUE(bool_reg_type.IsCategory1Types());
178 EXPECT_FALSE(bool_reg_type.IsCategory2Types());
179 EXPECT_TRUE(bool_reg_type.IsBooleanTypes());
180 EXPECT_TRUE(bool_reg_type.IsByteTypes());
181 EXPECT_TRUE(bool_reg_type.IsShortTypes());
182 EXPECT_TRUE(bool_reg_type.IsCharTypes());
183 EXPECT_TRUE(bool_reg_type.IsIntegralTypes());
184 EXPECT_FALSE(bool_reg_type.IsFloatTypes());
185 EXPECT_FALSE(bool_reg_type.IsLongTypes());
186 EXPECT_FALSE(bool_reg_type.IsDoubleTypes());
187 EXPECT_TRUE(bool_reg_type.IsArrayIndexTypes());
188 EXPECT_FALSE(bool_reg_type.IsNonZeroReferenceTypes());
189 EXPECT_FALSE(bool_reg_type.HasClass());
190
191 const RegType& byte_reg_type = cache.Byte();
192 EXPECT_FALSE(byte_reg_type.IsUndefined());
193 EXPECT_FALSE(byte_reg_type.IsConflict());
194 EXPECT_FALSE(bool_reg_type.IsConstantTypes());
195 EXPECT_FALSE(byte_reg_type.IsBoolean());
196 EXPECT_TRUE(byte_reg_type.IsByte());
197 EXPECT_FALSE(byte_reg_type.IsChar());
198 EXPECT_FALSE(byte_reg_type.IsShort());
199 EXPECT_FALSE(byte_reg_type.IsInteger());
200 EXPECT_FALSE(byte_reg_type.IsLongLo());
201 EXPECT_FALSE(byte_reg_type.IsFloat());
202 EXPECT_FALSE(byte_reg_type.IsDoubleLo());
203 EXPECT_FALSE(byte_reg_type.IsReference());
204 EXPECT_FALSE(byte_reg_type.IsLowHalf());
205 EXPECT_FALSE(byte_reg_type.IsHighHalf());
206 EXPECT_FALSE(byte_reg_type.IsLongOrDoubleTypes());
207 EXPECT_FALSE(byte_reg_type.IsReferenceTypes());
208 EXPECT_TRUE(byte_reg_type.IsCategory1Types());
209 EXPECT_FALSE(byte_reg_type.IsCategory2Types());
210 EXPECT_FALSE(byte_reg_type.IsBooleanTypes());
211 EXPECT_TRUE(byte_reg_type.IsByteTypes());
212 EXPECT_TRUE(byte_reg_type.IsShortTypes());
213 EXPECT_FALSE(byte_reg_type.IsCharTypes());
214 EXPECT_TRUE(byte_reg_type.IsIntegralTypes());
215 EXPECT_FALSE(byte_reg_type.IsFloatTypes());
216 EXPECT_FALSE(byte_reg_type.IsLongTypes());
217 EXPECT_FALSE(byte_reg_type.IsDoubleTypes());
218 EXPECT_TRUE(byte_reg_type.IsArrayIndexTypes());
219 EXPECT_FALSE(byte_reg_type.IsNonZeroReferenceTypes());
220 EXPECT_FALSE(byte_reg_type.HasClass());
221
222 const RegType& char_reg_type = cache.Char();
223 EXPECT_FALSE(char_reg_type.IsUndefined());
224 EXPECT_FALSE(char_reg_type.IsConflict());
225 EXPECT_FALSE(bool_reg_type.IsConstantTypes());
226 EXPECT_FALSE(char_reg_type.IsBoolean());
227 EXPECT_FALSE(char_reg_type.IsByte());
228 EXPECT_TRUE(char_reg_type.IsChar());
229 EXPECT_FALSE(char_reg_type.IsShort());
230 EXPECT_FALSE(char_reg_type.IsInteger());
231 EXPECT_FALSE(char_reg_type.IsLongLo());
232 EXPECT_FALSE(char_reg_type.IsFloat());
233 EXPECT_FALSE(char_reg_type.IsDoubleLo());
234 EXPECT_FALSE(char_reg_type.IsReference());
235 EXPECT_FALSE(char_reg_type.IsLowHalf());
236 EXPECT_FALSE(char_reg_type.IsHighHalf());
237 EXPECT_FALSE(char_reg_type.IsLongOrDoubleTypes());
238 EXPECT_FALSE(char_reg_type.IsReferenceTypes());
239 EXPECT_TRUE(char_reg_type.IsCategory1Types());
240 EXPECT_FALSE(char_reg_type.IsCategory2Types());
241 EXPECT_FALSE(char_reg_type.IsBooleanTypes());
242 EXPECT_FALSE(char_reg_type.IsByteTypes());
243 EXPECT_FALSE(char_reg_type.IsShortTypes());
244 EXPECT_TRUE(char_reg_type.IsCharTypes());
245 EXPECT_TRUE(char_reg_type.IsIntegralTypes());
246 EXPECT_FALSE(char_reg_type.IsFloatTypes());
247 EXPECT_FALSE(char_reg_type.IsLongTypes());
248 EXPECT_FALSE(char_reg_type.IsDoubleTypes());
249 EXPECT_TRUE(char_reg_type.IsArrayIndexTypes());
250 EXPECT_FALSE(char_reg_type.IsNonZeroReferenceTypes());
251 EXPECT_FALSE(char_reg_type.HasClass());
252
253 const RegType& short_reg_type = cache.Short();
254 EXPECT_FALSE(short_reg_type.IsUndefined());
255 EXPECT_FALSE(short_reg_type.IsConflict());
256 EXPECT_FALSE(bool_reg_type.IsConstantTypes());
257 EXPECT_FALSE(short_reg_type.IsBoolean());
258 EXPECT_FALSE(short_reg_type.IsByte());
259 EXPECT_FALSE(short_reg_type.IsChar());
260 EXPECT_TRUE(short_reg_type.IsShort());
261 EXPECT_FALSE(short_reg_type.IsInteger());
262 EXPECT_FALSE(short_reg_type.IsLongLo());
263 EXPECT_FALSE(short_reg_type.IsFloat());
264 EXPECT_FALSE(short_reg_type.IsDoubleLo());
265 EXPECT_FALSE(short_reg_type.IsReference());
266 EXPECT_FALSE(short_reg_type.IsLowHalf());
267 EXPECT_FALSE(short_reg_type.IsHighHalf());
268 EXPECT_FALSE(short_reg_type.IsLongOrDoubleTypes());
269 EXPECT_FALSE(short_reg_type.IsReferenceTypes());
270 EXPECT_TRUE(short_reg_type.IsCategory1Types());
271 EXPECT_FALSE(short_reg_type.IsCategory2Types());
272 EXPECT_FALSE(short_reg_type.IsBooleanTypes());
273 EXPECT_FALSE(short_reg_type.IsByteTypes());
274 EXPECT_TRUE(short_reg_type.IsShortTypes());
275 EXPECT_FALSE(short_reg_type.IsCharTypes());
276 EXPECT_TRUE(short_reg_type.IsIntegralTypes());
277 EXPECT_FALSE(short_reg_type.IsFloatTypes());
278 EXPECT_FALSE(short_reg_type.IsLongTypes());
279 EXPECT_FALSE(short_reg_type.IsDoubleTypes());
280 EXPECT_TRUE(short_reg_type.IsArrayIndexTypes());
281 EXPECT_FALSE(short_reg_type.IsNonZeroReferenceTypes());
282 EXPECT_FALSE(short_reg_type.HasClass());
283
284 const RegType& int_reg_type = cache.Integer();
285 EXPECT_FALSE(int_reg_type.IsUndefined());
286 EXPECT_FALSE(int_reg_type.IsConflict());
287 EXPECT_FALSE(bool_reg_type.IsConstantTypes());
288 EXPECT_FALSE(int_reg_type.IsBoolean());
289 EXPECT_FALSE(int_reg_type.IsByte());
290 EXPECT_FALSE(int_reg_type.IsChar());
291 EXPECT_FALSE(int_reg_type.IsShort());
292 EXPECT_TRUE(int_reg_type.IsInteger());
293 EXPECT_FALSE(int_reg_type.IsLongLo());
294 EXPECT_FALSE(int_reg_type.IsFloat());
295 EXPECT_FALSE(int_reg_type.IsDoubleLo());
296 EXPECT_FALSE(int_reg_type.IsReference());
297 EXPECT_FALSE(int_reg_type.IsLowHalf());
298 EXPECT_FALSE(int_reg_type.IsHighHalf());
299 EXPECT_FALSE(int_reg_type.IsLongOrDoubleTypes());
300 EXPECT_FALSE(int_reg_type.IsReferenceTypes());
301 EXPECT_TRUE(int_reg_type.IsCategory1Types());
302 EXPECT_FALSE(int_reg_type.IsCategory2Types());
303 EXPECT_FALSE(int_reg_type.IsBooleanTypes());
304 EXPECT_FALSE(int_reg_type.IsByteTypes());
305 EXPECT_FALSE(int_reg_type.IsShortTypes());
306 EXPECT_FALSE(int_reg_type.IsCharTypes());
307 EXPECT_TRUE(int_reg_type.IsIntegralTypes());
308 EXPECT_FALSE(int_reg_type.IsFloatTypes());
309 EXPECT_FALSE(int_reg_type.IsLongTypes());
310 EXPECT_FALSE(int_reg_type.IsDoubleTypes());
311 EXPECT_TRUE(int_reg_type.IsArrayIndexTypes());
312 EXPECT_FALSE(int_reg_type.IsNonZeroReferenceTypes());
313 EXPECT_FALSE(int_reg_type.HasClass());
314
315 const RegType& long_reg_type = cache.LongLo();
316 EXPECT_FALSE(long_reg_type.IsUndefined());
317 EXPECT_FALSE(long_reg_type.IsConflict());
318 EXPECT_FALSE(bool_reg_type.IsConstantTypes());
319 EXPECT_FALSE(long_reg_type.IsBoolean());
320 EXPECT_FALSE(long_reg_type.IsByte());
321 EXPECT_FALSE(long_reg_type.IsChar());
322 EXPECT_FALSE(long_reg_type.IsShort());
323 EXPECT_FALSE(long_reg_type.IsInteger());
324 EXPECT_TRUE(long_reg_type.IsLongLo());
325 EXPECT_FALSE(long_reg_type.IsFloat());
326 EXPECT_FALSE(long_reg_type.IsDoubleLo());
327 EXPECT_FALSE(long_reg_type.IsReference());
328 EXPECT_TRUE(long_reg_type.IsLowHalf());
329 EXPECT_FALSE(long_reg_type.IsHighHalf());
330 EXPECT_TRUE(long_reg_type.IsLongOrDoubleTypes());
331 EXPECT_FALSE(long_reg_type.IsReferenceTypes());
332 EXPECT_FALSE(long_reg_type.IsCategory1Types());
333 EXPECT_TRUE(long_reg_type.IsCategory2Types());
334 EXPECT_FALSE(long_reg_type.IsBooleanTypes());
335 EXPECT_FALSE(long_reg_type.IsByteTypes());
336 EXPECT_FALSE(long_reg_type.IsShortTypes());
337 EXPECT_FALSE(long_reg_type.IsCharTypes());
338 EXPECT_FALSE(long_reg_type.IsIntegralTypes());
339 EXPECT_FALSE(long_reg_type.IsFloatTypes());
340 EXPECT_TRUE(long_reg_type.IsLongTypes());
341 EXPECT_FALSE(long_reg_type.IsDoubleTypes());
342 EXPECT_FALSE(long_reg_type.IsArrayIndexTypes());
343 EXPECT_FALSE(long_reg_type.IsNonZeroReferenceTypes());
344 EXPECT_FALSE(long_reg_type.HasClass());
345
346 const RegType& float_reg_type = cache.Float();
347 EXPECT_FALSE(float_reg_type.IsUndefined());
348 EXPECT_FALSE(float_reg_type.IsConflict());
349 EXPECT_FALSE(bool_reg_type.IsConstantTypes());
350 EXPECT_FALSE(float_reg_type.IsBoolean());
351 EXPECT_FALSE(float_reg_type.IsByte());
352 EXPECT_FALSE(float_reg_type.IsChar());
353 EXPECT_FALSE(float_reg_type.IsShort());
354 EXPECT_FALSE(float_reg_type.IsInteger());
355 EXPECT_FALSE(float_reg_type.IsLongLo());
356 EXPECT_TRUE(float_reg_type.IsFloat());
357 EXPECT_FALSE(float_reg_type.IsDoubleLo());
358 EXPECT_FALSE(float_reg_type.IsReference());
359 EXPECT_FALSE(float_reg_type.IsLowHalf());
360 EXPECT_FALSE(float_reg_type.IsHighHalf());
361 EXPECT_FALSE(float_reg_type.IsLongOrDoubleTypes());
362 EXPECT_FALSE(float_reg_type.IsReferenceTypes());
363 EXPECT_TRUE(float_reg_type.IsCategory1Types());
364 EXPECT_FALSE(float_reg_type.IsCategory2Types());
365 EXPECT_FALSE(float_reg_type.IsBooleanTypes());
366 EXPECT_FALSE(float_reg_type.IsByteTypes());
367 EXPECT_FALSE(float_reg_type.IsShortTypes());
368 EXPECT_FALSE(float_reg_type.IsCharTypes());
369 EXPECT_FALSE(float_reg_type.IsIntegralTypes());
370 EXPECT_TRUE(float_reg_type.IsFloatTypes());
371 EXPECT_FALSE(float_reg_type.IsLongTypes());
372 EXPECT_FALSE(float_reg_type.IsDoubleTypes());
373 EXPECT_FALSE(float_reg_type.IsArrayIndexTypes());
374 EXPECT_FALSE(float_reg_type.IsNonZeroReferenceTypes());
375 EXPECT_FALSE(float_reg_type.HasClass());
376
377 const RegType& double_reg_type = cache.DoubleLo();
378 EXPECT_FALSE(double_reg_type.IsUndefined());
379 EXPECT_FALSE(double_reg_type.IsConflict());
380 EXPECT_FALSE(bool_reg_type.IsConstantTypes());
381 EXPECT_FALSE(double_reg_type.IsBoolean());
382 EXPECT_FALSE(double_reg_type.IsByte());
383 EXPECT_FALSE(double_reg_type.IsChar());
384 EXPECT_FALSE(double_reg_type.IsShort());
385 EXPECT_FALSE(double_reg_type.IsInteger());
386 EXPECT_FALSE(double_reg_type.IsLongLo());
387 EXPECT_FALSE(double_reg_type.IsFloat());
388 EXPECT_TRUE(double_reg_type.IsDoubleLo());
389 EXPECT_FALSE(double_reg_type.IsReference());
390 EXPECT_TRUE(double_reg_type.IsLowHalf());
391 EXPECT_FALSE(double_reg_type.IsHighHalf());
392 EXPECT_TRUE(double_reg_type.IsLongOrDoubleTypes());
393 EXPECT_FALSE(double_reg_type.IsReferenceTypes());
394 EXPECT_FALSE(double_reg_type.IsCategory1Types());
395 EXPECT_TRUE(double_reg_type.IsCategory2Types());
396 EXPECT_FALSE(double_reg_type.IsBooleanTypes());
397 EXPECT_FALSE(double_reg_type.IsByteTypes());
398 EXPECT_FALSE(double_reg_type.IsShortTypes());
399 EXPECT_FALSE(double_reg_type.IsCharTypes());
400 EXPECT_FALSE(double_reg_type.IsIntegralTypes());
401 EXPECT_FALSE(double_reg_type.IsFloatTypes());
402 EXPECT_FALSE(double_reg_type.IsLongTypes());
403 EXPECT_TRUE(double_reg_type.IsDoubleTypes());
404 EXPECT_FALSE(double_reg_type.IsArrayIndexTypes());
405 EXPECT_FALSE(double_reg_type.IsNonZeroReferenceTypes());
406 EXPECT_FALSE(double_reg_type.HasClass());
407 }
408
409 class RegTypeReferenceTest : public RegTypeTest {};
410
TEST_F(RegTypeReferenceTest,UnresolvedType)411 TEST_F(RegTypeReferenceTest, UnresolvedType) {
412 // Tests creating unresolved types. Miss for the first time asking the cache and
413 // a hit second time.
414 ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
415 ScopedObjectAccess soa(Thread::Current());
416 ScopedNullHandle<mirror::ClassLoader> loader;
417 RegTypeCache cache(soa.Self(), class_linker_, arena_pool, loader, dex_file_.get());
418 const RegType& ref_type_0 = cache.FromDescriptor("Ljava/lang/DoesNotExist;");
419 EXPECT_TRUE(ref_type_0.IsUnresolvedReference());
420 EXPECT_TRUE(ref_type_0.IsNonZeroReferenceTypes());
421
422 const RegType& ref_type_1 = cache.FromDescriptor("Ljava/lang/DoesNotExist;");
423 EXPECT_TRUE(ref_type_0.Equals(ref_type_1));
424 }
425
TEST_F(RegTypeReferenceTest,UnresolvedUnintializedType)426 TEST_F(RegTypeReferenceTest, UnresolvedUnintializedType) {
427 // Tests creating types uninitialized types from unresolved types.
428 ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
429 ScopedObjectAccess soa(Thread::Current());
430 ScopedNullHandle<mirror::ClassLoader> loader;
431 RegTypeCache cache(soa.Self(), class_linker_, arena_pool, loader, dex_file_.get());
432 const RegType& ref_type_0 = cache.FromDescriptor("Ljava/lang/DoesNotExist;");
433 EXPECT_TRUE(ref_type_0.IsUnresolvedReference());
434 const RegType& ref_type = cache.FromDescriptor("Ljava/lang/DoesNotExist;");
435 EXPECT_TRUE(ref_type_0.Equals(ref_type));
436 // Create an uninitialized type of this unresolved type.
437 const RegType& unresolved_uninitialized = cache.Uninitialized(ref_type);
438 EXPECT_TRUE(unresolved_uninitialized.IsUnresolvedUninitializedReference());
439 EXPECT_TRUE(unresolved_uninitialized.IsUninitializedTypes());
440 EXPECT_TRUE(unresolved_uninitialized.IsNonZeroReferenceTypes());
441 // Create an another uninitialized type of this unresolved type.
442 const RegType& unresolved_uninitialized_2 = cache.Uninitialized(ref_type);
443 EXPECT_TRUE(unresolved_uninitialized.Equals(unresolved_uninitialized_2));
444 }
445
TEST_F(RegTypeReferenceTest,Dump)446 TEST_F(RegTypeReferenceTest, Dump) {
447 // Tests types for proper Dump messages.
448 ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
449 ScopedObjectAccess soa(Thread::Current());
450 ScopedNullHandle<mirror::ClassLoader> loader;
451 RegTypeCache cache(soa.Self(), class_linker_, arena_pool, loader, dex_file_.get());
452 const RegType& unresolved_ref = cache.FromDescriptor("Ljava/lang/DoesNotExist;");
453 const RegType& unresolved_ref_another = cache.FromDescriptor("Ljava/lang/DoesNotExistEither;");
454 const RegType& resolved_ref = cache.JavaLangString();
455 const RegType& resolved_uninitialized = cache.Uninitialized(resolved_ref);
456 const RegType& unresolved_uninitialized = cache.Uninitialized(unresolved_ref);
457 const RegType& unresolved_merged = cache.FromUnresolvedMerge(
458 unresolved_ref, unresolved_ref_another, /* verifier= */ nullptr);
459
460 std::string expected = "Unresolved Reference: java.lang.DoesNotExist";
461 EXPECT_EQ(expected, unresolved_ref.Dump());
462 expected = "Reference: java.lang.String";
463 EXPECT_EQ(expected, resolved_ref.Dump());
464 expected ="Uninitialized Reference: java.lang.String";
465 EXPECT_EQ(expected, resolved_uninitialized .Dump());
466 expected = "Unresolved And Uninitialized Reference: java.lang.DoesNotExist";
467 EXPECT_EQ(expected, unresolved_uninitialized.Dump());
468 expected = "UnresolvedMergedReferences(Zero/null | Unresolved Reference: java.lang.DoesNotExist, Unresolved Reference: java.lang.DoesNotExistEither)";
469 EXPECT_EQ(expected, unresolved_merged.Dump());
470 }
471
TEST_F(RegTypeReferenceTest,JavalangString)472 TEST_F(RegTypeReferenceTest, JavalangString) {
473 // Add a class to the cache then look for the same class and make sure it is a
474 // Hit the second time. Then check for the same effect when using
475 // The JavaLangObject method instead of FromDescriptor. String class is final.
476 ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
477 ScopedObjectAccess soa(Thread::Current());
478 ScopedNullHandle<mirror::ClassLoader> loader;
479 RegTypeCache cache(soa.Self(), class_linker_, arena_pool, loader, dex_file_.get());
480 const RegType& ref_type = cache.JavaLangString();
481 const RegType& ref_type_2 = cache.JavaLangString();
482 const RegType& ref_type_3 = cache.FromDescriptor("Ljava/lang/String;");
483
484 EXPECT_TRUE(ref_type.Equals(ref_type_2));
485 EXPECT_TRUE(ref_type_2.Equals(ref_type_3));
486 EXPECT_TRUE(ref_type.IsReference());
487
488 // Create an uninitialized type out of this:
489 const RegType& ref_type_uninitialized = cache.Uninitialized(ref_type);
490 EXPECT_TRUE(ref_type_uninitialized.IsUninitializedReference());
491 EXPECT_FALSE(ref_type_uninitialized.IsUnresolvedUninitializedReference());
492 }
493
TEST_F(RegTypeReferenceTest,JavalangObject)494 TEST_F(RegTypeReferenceTest, JavalangObject) {
495 // Add a class to the cache then look for the same class and make sure it is a
496 // Hit the second time. Then I am checking for the same effect when using
497 // The JavaLangObject method instead of FromDescriptor. Object Class in not final.
498 ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
499 ScopedObjectAccess soa(Thread::Current());
500 ScopedNullHandle<mirror::ClassLoader> loader;
501 RegTypeCache cache(soa.Self(), class_linker_, arena_pool, loader, dex_file_.get());
502 const RegType& ref_type = cache.JavaLangObject();
503 const RegType& ref_type_2 = cache.JavaLangObject();
504 const RegType& ref_type_3 = cache.FromDescriptor("Ljava/lang/Object;");
505
506 EXPECT_TRUE(ref_type.Equals(ref_type_2));
507 EXPECT_TRUE(ref_type_3.Equals(ref_type_2));
508 EXPECT_EQ(ref_type.GetId(), ref_type_3.GetId());
509 }
510
TEST_F(RegTypeReferenceTest,Merging)511 TEST_F(RegTypeReferenceTest, Merging) {
512 // Tests merging logic
513 // String and object , LUB is object.
514 ScopedObjectAccess soa(Thread::Current());
515 ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
516 ScopedNullHandle<mirror::ClassLoader> loader;
517 RegTypeCache cache_new(soa.Self(), class_linker_, arena_pool, loader, dex_file_.get());
518 const RegType& string = cache_new.JavaLangString();
519 const RegType& Object = cache_new.JavaLangObject();
520 EXPECT_TRUE(string.Merge(Object, &cache_new, /* verifier= */ nullptr).IsJavaLangObject());
521 // Merge two unresolved types.
522 const RegType& ref_type_0 = cache_new.FromDescriptor("Ljava/lang/DoesNotExist;");
523 EXPECT_TRUE(ref_type_0.IsUnresolvedReference());
524 const RegType& ref_type_1 = cache_new.FromDescriptor("Ljava/lang/DoesNotExistToo;");
525 EXPECT_FALSE(ref_type_0.Equals(ref_type_1));
526
527 const RegType& merged = ref_type_1.Merge(ref_type_0, &cache_new, /* verifier= */ nullptr);
528 EXPECT_TRUE(merged.IsUnresolvedMergedReference());
529 RegType& merged_nonconst = const_cast<RegType&>(merged);
530
531 const BitVector& unresolved_parts =
532 down_cast<UnresolvedMergedReferenceType*>(&merged_nonconst)->GetUnresolvedTypes();
533 EXPECT_TRUE(unresolved_parts.IsBitSet(ref_type_0.GetId()));
534 EXPECT_TRUE(unresolved_parts.IsBitSet(ref_type_1.GetId()));
535 }
536
TEST_F(RegTypeTest,MergingFloat)537 TEST_F(RegTypeTest, MergingFloat) {
538 // Testing merging logic with float and float constants.
539 ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
540 ScopedObjectAccess soa(Thread::Current());
541 ScopedNullHandle<mirror::ClassLoader> loader;
542 RegTypeCache cache(soa.Self(), class_linker_, arena_pool, loader, dex_file_.get());
543 std::array<const RegType*, kNumConstTypes> const_reg_types = GetConstRegTypes(cache);
544
545 const RegType& float_type = cache.Float();
546 for (const RegType* const_type : const_reg_types) {
547 // float MERGE cst => float.
548 const RegType& merged = float_type.Merge(*const_type, &cache, /* verifier= */ nullptr);
549 if (const_type->IsConstant()) {
550 EXPECT_TRUE(merged.IsFloat()) << RegTypeWrapper(*const_type);
551 } else {
552 DCHECK(const_type->IsConstantLo() || const_type->IsConstantHi() || const_type->IsNull());
553 EXPECT_TRUE(merged.IsConflict()) << RegTypeWrapper(*const_type);
554 }
555 }
556 for (const RegType* const_type : const_reg_types) {
557 // cst MERGE float => float.
558 const RegType& merged = const_type->Merge(float_type, &cache, /* verifier= */ nullptr);
559 if (const_type->IsConstant()) {
560 EXPECT_TRUE(merged.IsFloat()) << RegTypeWrapper(*const_type);
561 } else {
562 DCHECK(const_type->IsConstantLo() || const_type->IsConstantHi() || const_type->IsNull());
563 EXPECT_TRUE(merged.IsConflict()) << RegTypeWrapper(*const_type);
564 }
565 }
566 }
567
TEST_F(RegTypeTest,MergingLong)568 TEST_F(RegTypeTest, MergingLong) {
569 // Testing merging logic with long and long constants.
570 ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
571 ScopedObjectAccess soa(Thread::Current());
572 ScopedNullHandle<mirror::ClassLoader> loader;
573 RegTypeCache cache(soa.Self(), class_linker_, arena_pool, loader, dex_file_.get());
574 std::array<const RegType*, kNumConstTypes> const_reg_types = GetConstRegTypes(cache);
575
576 const RegType& long_lo_type = cache.LongLo();
577 const RegType& long_hi_type = cache.LongHi();
578 for (const RegType* const_type : const_reg_types) {
579 // lo MERGE cst lo => lo.
580 const RegType& merged = long_lo_type.Merge(*const_type, &cache, /* verifier= */ nullptr);
581 if (const_type->IsConstantLo()) {
582 EXPECT_TRUE(merged.IsLongLo()) << RegTypeWrapper(*const_type);
583 } else {
584 EXPECT_TRUE(merged.IsConflict()) << RegTypeWrapper(*const_type);
585 }
586 }
587 for (const RegType* const_type : const_reg_types) {
588 // cst lo MERGE lo => lo.
589 const RegType& merged = const_type->Merge(long_lo_type, &cache, /* verifier= */ nullptr);
590 if (const_type->IsConstantLo()) {
591 EXPECT_TRUE(merged.IsLongLo()) << RegTypeWrapper(*const_type);
592 } else {
593 EXPECT_TRUE(merged.IsConflict()) << RegTypeWrapper(*const_type);
594 }
595 }
596 for (const RegType* const_type : const_reg_types) {
597 // hi MERGE cst hi => hi.
598 const RegType& merged = long_hi_type.Merge(*const_type, &cache, /* verifier= */ nullptr);
599 if (const_type->IsConstantHi()) {
600 EXPECT_TRUE(merged.IsLongHi()) << RegTypeWrapper(*const_type);
601 } else {
602 EXPECT_TRUE(merged.IsConflict()) << RegTypeWrapper(*const_type);
603 }
604 }
605 for (const RegType* const_type : const_reg_types) {
606 // cst hi MERGE hi => hi.
607 const RegType& merged = const_type->Merge(long_hi_type, &cache, /* verifier= */ nullptr);
608 if (const_type->IsConstantHi()) {
609 EXPECT_TRUE(merged.IsLongHi()) << RegTypeWrapper(*const_type);
610 } else {
611 EXPECT_TRUE(merged.IsConflict()) << RegTypeWrapper(*const_type);
612 }
613 }
614 }
615
TEST_F(RegTypeTest,MergingDouble)616 TEST_F(RegTypeTest, MergingDouble) {
617 // Testing merging logic with double and double constants.
618 ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
619 ScopedObjectAccess soa(Thread::Current());
620 ScopedNullHandle<mirror::ClassLoader> loader;
621 RegTypeCache cache(soa.Self(), class_linker_, arena_pool, loader, dex_file_.get());
622 std::array<const RegType*, kNumConstTypes> const_reg_types = GetConstRegTypes(cache);
623
624 const RegType& double_lo_type = cache.DoubleLo();
625 const RegType& double_hi_type = cache.DoubleHi();
626 for (const RegType* const_type : const_reg_types) {
627 // lo MERGE cst lo => lo.
628 const RegType& merged = double_lo_type.Merge(*const_type, &cache, /* verifier= */ nullptr);
629 if (const_type->IsConstantLo()) {
630 EXPECT_TRUE(merged.IsDoubleLo()) << RegTypeWrapper(*const_type);
631 } else {
632 EXPECT_TRUE(merged.IsConflict()) << RegTypeWrapper(*const_type);
633 }
634 }
635 for (const RegType* const_type : const_reg_types) {
636 // cst lo MERGE lo => lo.
637 const RegType& merged = const_type->Merge(double_lo_type, &cache, /* verifier= */ nullptr);
638 if (const_type->IsConstantLo()) {
639 EXPECT_TRUE(merged.IsDoubleLo()) << RegTypeWrapper(*const_type);
640 } else {
641 EXPECT_TRUE(merged.IsConflict()) << RegTypeWrapper(*const_type);
642 }
643 }
644 for (const RegType* const_type : const_reg_types) {
645 // hi MERGE cst hi => hi.
646 const RegType& merged = double_hi_type.Merge(*const_type, &cache, /* verifier= */ nullptr);
647 if (const_type->IsConstantHi()) {
648 EXPECT_TRUE(merged.IsDoubleHi()) << RegTypeWrapper(*const_type);
649 } else {
650 EXPECT_TRUE(merged.IsConflict()) << RegTypeWrapper(*const_type);
651 }
652 }
653 for (const RegType* const_type : const_reg_types) {
654 // cst hi MERGE hi => hi.
655 const RegType& merged = const_type->Merge(double_hi_type, &cache, /* verifier= */ nullptr);
656 if (const_type->IsConstantHi()) {
657 EXPECT_TRUE(merged.IsDoubleHi()) << RegTypeWrapper(*const_type);
658 } else {
659 EXPECT_TRUE(merged.IsConflict()) << RegTypeWrapper(*const_type);
660 }
661 }
662 }
663
664 // Without a running MethodVerifier, the class-bearing register types may become stale as the GC
665 // will not visit them. It is easiest to disable moving GC.
666 //
667 // For some of the tests we need (or want) a working RegTypeCache that can load classes. So it is
668 // not generally possible to disable GC using ScopedGCCriticalSection (as it blocks GC and
669 // suspension completely).
670 struct ScopedDisableMovingGC {
ScopedDisableMovingGCart::verifier::ScopedDisableMovingGC671 explicit ScopedDisableMovingGC(Thread* t) : self(t) {
672 Runtime::Current()->GetHeap()->IncrementDisableMovingGC(self);
673 }
~ScopedDisableMovingGCart::verifier::ScopedDisableMovingGC674 ~ScopedDisableMovingGC() {
675 Runtime::Current()->GetHeap()->DecrementDisableMovingGC(self);
676 }
677
678 Thread* self;
679 };
680
TEST_F(RegTypeTest,MergeSemiLatticeRef)681 TEST_F(RegTypeTest, MergeSemiLatticeRef) {
682 // (Incomplete) semilattice:
683 //
684 // Excluded for now: * category-2 types
685 // * interfaces
686 // * all of category-1 primitive types, including constants.
687 // This is to demonstrate/codify the reference side, mostly.
688 //
689 // Note: It is not a real semilattice because int = float makes this wonky. :-(
690 //
691 // Conflict
692 // |
693 // #---------#--------------------------#-----------------------------#
694 // | | |
695 // | | Object
696 // | | |
697 // int uninit types #---------------#--------#------------------#---------#
698 // | | | | | |
699 // | unresolved-merge-types | Object[] char[] byte[]
700 // | | | | | | | |
701 // | unresolved-types | #------Number #---------# | |
702 // | | | | | | | |
703 // | | #--------Integer Number[] Number[][] | |
704 // | | | | | | |
705 // | #---------------#--------#---------#--------#---------#
706 // | |
707 // | null
708 // | |
709 // #--------------------------#----------------------------#
710 // |
711 // 0
712
713 ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
714 ScopedObjectAccess soa(Thread::Current());
715
716 ScopedDisableMovingGC no_gc(soa.Self());
717
718 ScopedNullHandle<mirror::ClassLoader> loader;
719 RegTypeCache cache(soa.Self(), class_linker_, arena_pool, loader, dex_file_.get());
720
721 const RegType& conflict = cache.Conflict();
722 const RegType& zero = cache.Zero();
723 const RegType& null = cache.Null();
724 const RegType& int_type = cache.Integer();
725
726 const RegType& obj = cache.JavaLangObject();
727 const RegType& obj_arr = cache.FromDescriptor("[Ljava/lang/Object;");
728 ASSERT_FALSE(obj_arr.IsUnresolvedReference());
729
730 const RegType& unresolved_a = cache.FromDescriptor("Ldoes/not/resolve/A;");
731 ASSERT_TRUE(unresolved_a.IsUnresolvedReference());
732 const RegType& unresolved_b = cache.FromDescriptor("Ldoes/not/resolve/B;");
733 ASSERT_TRUE(unresolved_b.IsUnresolvedReference());
734 const RegType& unresolved_ab = cache.FromUnresolvedMerge(unresolved_a, unresolved_b, nullptr);
735 ASSERT_TRUE(unresolved_ab.IsUnresolvedMergedReference());
736
737 const RegType& uninit_this = cache.UninitializedThisArgument(obj);
738 const RegType& uninit_obj = cache.Uninitialized(obj);
739
740 const RegType& uninit_unres_this = cache.UninitializedThisArgument(unresolved_a);
741 const RegType& uninit_unres_a = cache.Uninitialized(unresolved_a);
742 const RegType& uninit_unres_b = cache.Uninitialized(unresolved_b);
743
744 const RegType& number = cache.FromDescriptor("Ljava/lang/Number;");
745 ASSERT_FALSE(number.IsUnresolvedReference());
746 const RegType& integer = cache.FromDescriptor("Ljava/lang/Integer;");
747 ASSERT_FALSE(integer.IsUnresolvedReference());
748
749 const RegType& uninit_number = cache.Uninitialized(number);
750 const RegType& uninit_integer = cache.Uninitialized(integer);
751
752 const RegType& number_arr = cache.FromDescriptor("[Ljava/lang/Number;");
753 ASSERT_FALSE(number_arr.IsUnresolvedReference());
754 const RegType& integer_arr = cache.FromDescriptor("[Ljava/lang/Integer;");
755 ASSERT_FALSE(integer_arr.IsUnresolvedReference());
756
757 const RegType& number_arr_arr = cache.FromDescriptor("[[Ljava/lang/Number;");
758 ASSERT_FALSE(number_arr_arr.IsUnresolvedReference());
759
760 const RegType& char_arr = cache.FromDescriptor("[C");
761 ASSERT_FALSE(char_arr.IsUnresolvedReference());
762 const RegType& byte_arr = cache.FromDescriptor("[B");
763 ASSERT_FALSE(byte_arr.IsUnresolvedReference());
764
765 const RegType& unresolved_a_num = cache.FromUnresolvedMerge(unresolved_a, number, nullptr);
766 ASSERT_TRUE(unresolved_a_num.IsUnresolvedMergedReference());
767 const RegType& unresolved_b_num = cache.FromUnresolvedMerge(unresolved_b, number, nullptr);
768 ASSERT_TRUE(unresolved_b_num.IsUnresolvedMergedReference());
769 const RegType& unresolved_ab_num = cache.FromUnresolvedMerge(unresolved_ab, number, nullptr);
770 ASSERT_TRUE(unresolved_ab_num.IsUnresolvedMergedReference());
771
772 const RegType& unresolved_a_int = cache.FromUnresolvedMerge(unresolved_a, integer, nullptr);
773 ASSERT_TRUE(unresolved_a_int.IsUnresolvedMergedReference());
774 const RegType& unresolved_b_int = cache.FromUnresolvedMerge(unresolved_b, integer, nullptr);
775 ASSERT_TRUE(unresolved_b_int.IsUnresolvedMergedReference());
776 const RegType& unresolved_ab_int = cache.FromUnresolvedMerge(unresolved_ab, integer, nullptr);
777 ASSERT_TRUE(unresolved_ab_int.IsUnresolvedMergedReference());
778 std::vector<const RegType*> uninitialized_types = {
779 &uninit_this, &uninit_obj, &uninit_number, &uninit_integer
780 };
781 std::vector<const RegType*> unresolved_types = {
782 &unresolved_a,
783 &unresolved_b,
784 &unresolved_ab,
785 &unresolved_a_num,
786 &unresolved_b_num,
787 &unresolved_ab_num,
788 &unresolved_a_int,
789 &unresolved_b_int,
790 &unresolved_ab_int
791 };
792 std::vector<const RegType*> uninit_unresolved_types = {
793 &uninit_unres_this, &uninit_unres_a, &uninit_unres_b
794 };
795 std::vector<const RegType*> plain_nonobj_classes = { &number, &integer };
796 std::vector<const RegType*> plain_nonobj_arr_classes = {
797 &number_arr,
798 &number_arr_arr,
799 &integer_arr,
800 &char_arr,
801 };
802 // std::vector<const RegType*> others = { &conflict, &zero, &null, &obj, &int_type };
803
804 std::vector<const RegType*> all_minus_uninit_conflict;
805 all_minus_uninit_conflict.insert(all_minus_uninit_conflict.end(),
806 unresolved_types.begin(),
807 unresolved_types.end());
808 all_minus_uninit_conflict.insert(all_minus_uninit_conflict.end(),
809 plain_nonobj_classes.begin(),
810 plain_nonobj_classes.end());
811 all_minus_uninit_conflict.insert(all_minus_uninit_conflict.end(),
812 plain_nonobj_arr_classes.begin(),
813 plain_nonobj_arr_classes.end());
814 all_minus_uninit_conflict.push_back(&zero);
815 all_minus_uninit_conflict.push_back(&null);
816 all_minus_uninit_conflict.push_back(&obj);
817
818 std::vector<const RegType*> all_minus_uninit;
819 all_minus_uninit.insert(all_minus_uninit.end(),
820 all_minus_uninit_conflict.begin(),
821 all_minus_uninit_conflict.end());
822 all_minus_uninit.push_back(&conflict);
823
824
825 std::vector<const RegType*> all;
826 all.insert(all.end(), uninitialized_types.begin(), uninitialized_types.end());
827 all.insert(all.end(), uninit_unresolved_types.begin(), uninit_unresolved_types.end());
828 all.insert(all.end(), all_minus_uninit.begin(), all_minus_uninit.end());
829 all.push_back(&int_type);
830
831 auto check = [&](const RegType& in1, const RegType& in2, const RegType& expected_out)
832 REQUIRES_SHARED(Locks::mutator_lock_) {
833 const RegType& merge_result = in1.SafeMerge(in2, &cache, nullptr);
834 EXPECT_EQ(&expected_out, &merge_result)
835 << in1.Dump() << " x " << in2.Dump() << " = " << merge_result.Dump()
836 << " != " << expected_out.Dump();
837 };
838
839 // Identity.
840 {
841 for (auto r : all) {
842 check(*r, *r, *r);
843 }
844 }
845
846 // Define a covering relation through a list of Edges. We'll then derive LUBs from this and
847 // create checks for every pair of types.
848
849 struct Edge {
850 const RegType& from;
851 const RegType& to;
852
853 Edge(const RegType& from_, const RegType& to_) : from(from_), to(to_) {}
854 };
855 std::vector<Edge> edges;
856 #define ADD_EDGE(from, to) edges.emplace_back((from), (to))
857
858 // To Conflict.
859 {
860 for (auto r : uninitialized_types) {
861 ADD_EDGE(*r, conflict);
862 }
863 for (auto r : uninit_unresolved_types) {
864 ADD_EDGE(*r, conflict);
865 }
866 ADD_EDGE(obj, conflict);
867 ADD_EDGE(int_type, conflict);
868 }
869
870 ADD_EDGE(zero, null);
871
872 // Unresolved.
873 {
874 ADD_EDGE(null, unresolved_a);
875 ADD_EDGE(null, unresolved_b);
876 ADD_EDGE(unresolved_a, unresolved_ab);
877 ADD_EDGE(unresolved_b, unresolved_ab);
878
879 ADD_EDGE(number, unresolved_a_num);
880 ADD_EDGE(unresolved_a, unresolved_a_num);
881 ADD_EDGE(number, unresolved_b_num);
882 ADD_EDGE(unresolved_b, unresolved_b_num);
883 ADD_EDGE(number, unresolved_ab_num);
884 ADD_EDGE(unresolved_a_num, unresolved_ab_num);
885 ADD_EDGE(unresolved_b_num, unresolved_ab_num);
886 ADD_EDGE(unresolved_ab, unresolved_ab_num);
887
888 ADD_EDGE(integer, unresolved_a_int);
889 ADD_EDGE(unresolved_a, unresolved_a_int);
890 ADD_EDGE(integer, unresolved_b_int);
891 ADD_EDGE(unresolved_b, unresolved_b_int);
892 ADD_EDGE(integer, unresolved_ab_int);
893 ADD_EDGE(unresolved_a_int, unresolved_ab_int);
894 ADD_EDGE(unresolved_b_int, unresolved_ab_int);
895 ADD_EDGE(unresolved_ab, unresolved_ab_int);
896
897 ADD_EDGE(unresolved_a_int, unresolved_a_num);
898 ADD_EDGE(unresolved_b_int, unresolved_b_num);
899 ADD_EDGE(unresolved_ab_int, unresolved_ab_num);
900
901 ADD_EDGE(unresolved_ab_num, obj);
902 }
903
904 // Classes.
905 {
906 ADD_EDGE(null, integer);
907 ADD_EDGE(integer, number);
908 ADD_EDGE(number, obj);
909 }
910
911 // Arrays.
912 {
913 ADD_EDGE(integer_arr, number_arr);
914 ADD_EDGE(number_arr, obj_arr);
915 ADD_EDGE(obj_arr, obj);
916 ADD_EDGE(number_arr_arr, obj_arr);
917
918 ADD_EDGE(char_arr, obj);
919 ADD_EDGE(byte_arr, obj);
920
921 ADD_EDGE(null, integer_arr);
922 ADD_EDGE(null, number_arr_arr);
923 ADD_EDGE(null, char_arr);
924 ADD_EDGE(null, byte_arr);
925 }
926
927 // Primitive.
928 {
929 ADD_EDGE(zero, int_type);
930 }
931 #undef ADD_EDGE
932
933 // Create merge triples by using the covering relation established by edges to derive the
934 // expected merge for any pair of types.
935
936 // Expect merge(in1, in2) == out.
937 struct MergeExpectation {
938 const RegType& in1;
939 const RegType& in2;
940 const RegType& out;
941
942 MergeExpectation(const RegType& in1_, const RegType& in2_, const RegType& out_)
943 : in1(in1_), in2(in2_), out(out_) {}
944 };
945 std::vector<MergeExpectation> expectations;
946
947 for (auto r1 : all) {
948 for (auto r2 : all) {
949 if (r1 == r2) {
950 continue;
951 }
952
953 // Very simple algorithm here that is usually used with adjacency lists. Our graph is
954 // small, it didn't make sense to have lists per node. Thus, the regular guarantees
955 // of O(n + |e|) don't apply, but that is acceptable.
956 //
957 // To compute r1 lub r2 = merge(r1, r2):
958 // 1) Generate the reachable set of r1, name it grey.
959 // 2) Mark all grey reachable nodes of r2 as black.
960 // 3) Find black nodes with no in-edges from other black nodes.
961 // 4) If |3)| == 1, that's the lub.
962
963 // Generic BFS of the graph induced by edges, starting at start. new_node will be called
964 // with any discovered node, in order.
965 auto bfs = [&](auto new_node, const RegType* start) {
966 std::unordered_set<const RegType*> seen;
967 std::queue<const RegType*> work_list;
968 work_list.push(start);
969 while (!work_list.empty()) {
970 const RegType* cur = work_list.front();
971 work_list.pop();
972 auto it = seen.find(cur);
973 if (it != seen.end()) {
974 continue;
975 }
976 seen.insert(cur);
977 new_node(cur);
978
979 for (const Edge& edge : edges) {
980 if (&edge.from == cur) {
981 work_list.push(&edge.to);
982 }
983 }
984 }
985 };
986
987 std::unordered_set<const RegType*> grey;
988 auto compute_grey = [&](const RegType* cur) {
989 grey.insert(cur); // Mark discovered node as grey.
990 };
991 bfs(compute_grey, r1);
992
993 std::set<const RegType*> black;
994 auto compute_black = [&](const RegType* cur) {
995 // Mark discovered grey node as black.
996 if (grey.find(cur) != grey.end()) {
997 black.insert(cur);
998 }
999 };
1000 bfs(compute_black, r2);
1001
1002 std::set<const RegType*> no_in_edge(black); // Copy of black, remove nodes with in-edges.
1003 for (auto r : black) {
1004 for (Edge& e : edges) {
1005 if (&e.from == r) {
1006 no_in_edge.erase(&e.to); // It doesn't matter whether "to" is black or not, just
1007 // attempt to remove it.
1008 }
1009 }
1010 }
1011
1012 // Helper to print sets when something went wrong.
1013 auto print_set = [](auto& container) REQUIRES_SHARED(Locks::mutator_lock_) {
1014 std::string result;
1015 for (auto r : container) {
1016 result.append(" + ");
1017 result.append(r->Dump());
1018 }
1019 return result;
1020 };
1021 ASSERT_EQ(no_in_edge.size(), 1u) << r1->Dump() << " u " << r2->Dump()
1022 << " grey=" << print_set(grey)
1023 << " black=" << print_set(black)
1024 << " no-in-edge=" << print_set(no_in_edge);
1025 expectations.emplace_back(*r1, *r2, **no_in_edge.begin());
1026 }
1027 }
1028
1029 // Evaluate merge expectations. The merge is expected to be commutative.
1030
1031 for (auto& triple : expectations) {
1032 check(triple.in1, triple.in2, triple.out);
1033 check(triple.in2, triple.in1, triple.out);
1034 }
1035 }
1036
1037 class RegTypeOOMTest : public RegTypeTest {
1038 protected:
SetUpRuntimeOptions(RuntimeOptions * options)1039 void SetUpRuntimeOptions(RuntimeOptions *options) override {
1040 SetUpRuntimeOptionsForFillHeap(options);
1041
1042 // We must not appear to be a compiler, or we'll abort on the host.
1043 callbacks_.reset();
1044 }
1045 };
1046
TEST_F(RegTypeOOMTest,ClassJoinOOM)1047 TEST_F(RegTypeOOMTest, ClassJoinOOM) {
1048 // TODO: Figure out why FillHeap isn't good enough under CMS.
1049 TEST_DISABLED_WITHOUT_BAKER_READ_BARRIERS();
1050
1051 // Tests that we don't abort with OOMs.
1052
1053 ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
1054 ScopedObjectAccess soa(Thread::Current());
1055
1056 ScopedDisableMovingGC no_gc(soa.Self());
1057
1058 // We merge nested array of primitive wrappers. These have a join type of an array of Number of
1059 // the same depth. We start with depth five, as we want at least two newly created classes to
1060 // test recursion (it's just more likely that nobody uses such deep arrays in runtime bringup).
1061 constexpr const char* kIntArrayFive = "[[[[[Ljava/lang/Integer;";
1062 constexpr const char* kFloatArrayFive = "[[[[[Ljava/lang/Float;";
1063 constexpr const char* kNumberArrayFour = "[[[[Ljava/lang/Number;";
1064 constexpr const char* kNumberArrayFive = "[[[[[Ljava/lang/Number;";
1065
1066 ScopedNullHandle<mirror::ClassLoader> loader;
1067 RegTypeCache cache(soa.Self(), class_linker_, arena_pool, loader, dex_file_.get());
1068 const RegType& int_array_array = cache.FromDescriptor(kIntArrayFive);
1069 ASSERT_TRUE(int_array_array.HasClass());
1070 const RegType& float_array_array = cache.FromDescriptor(kFloatArrayFive);
1071 ASSERT_TRUE(float_array_array.HasClass());
1072
1073 // Check assumptions: the joined classes don't exist, yet.
1074 ASSERT_TRUE(class_linker_->LookupClass(soa.Self(), kNumberArrayFour, nullptr) == nullptr);
1075 ASSERT_TRUE(class_linker_->LookupClass(soa.Self(), kNumberArrayFive, nullptr) == nullptr);
1076
1077 // Fill the heap.
1078 VariableSizedHandleScope hs(soa.Self());
1079 FillHeap(soa.Self(), class_linker_, &hs);
1080
1081 const RegType& join_type = int_array_array.Merge(float_array_array, &cache, nullptr);
1082 ASSERT_TRUE(join_type.IsUnresolvedReference());
1083 }
1084
1085 class RegTypeClassJoinTest : public RegTypeTest {
1086 protected:
TestClassJoin(const char * in1,const char * in2,const char * out)1087 void TestClassJoin(const char* in1, const char* in2, const char* out) {
1088 ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
1089
1090 ScopedObjectAccess soa(Thread::Current());
1091 jobject jclass_loader = LoadDex("Interfaces");
1092 StackHandleScope<4> hs(soa.Self());
1093 Handle<mirror::ClassLoader> class_loader(
1094 hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
1095
1096 Handle<mirror::Class> c1 = hs.NewHandle(FindClass(in1, class_loader));
1097 Handle<mirror::Class> c2 = hs.NewHandle(FindClass(in2, class_loader));
1098 ASSERT_TRUE(c1 != nullptr);
1099 ASSERT_TRUE(c2 != nullptr);
1100 const DexFile* dex_file = &c1->GetDexFile();
1101 ASSERT_EQ(dex_file, &c2->GetDexFile());
1102
1103 ScopedDisableMovingGC no_gc(soa.Self());
1104
1105 RegTypeCache cache(soa.Self(), class_linker_, arena_pool, class_loader, dex_file);
1106 const RegType& c1_reg_type = cache.FromClass(c1.Get());
1107 if (!c1_reg_type.IsJavaLangObject()) {
1108 ASSERT_TRUE(c1_reg_type.HasClass());
1109 ASSERT_TRUE(c1_reg_type.GetClass() == c1.Get());
1110 }
1111 const RegType& c2_reg_type = cache.FromClass(c2.Get());
1112 if (!c2_reg_type.IsJavaLangObject()) {
1113 ASSERT_TRUE(c2_reg_type.HasClass());
1114 ASSERT_TRUE(c2_reg_type.GetClass() == c2.Get());
1115 }
1116
1117 const RegType& join_type = c1_reg_type.Merge(c2_reg_type, &cache, nullptr);
1118 EXPECT_TRUE(join_type.IsJavaLangObject() || join_type.HasClass());
1119 EXPECT_EQ(join_type.GetDescriptor(), std::string_view(out));
1120 }
1121 };
1122
TEST_F(RegTypeClassJoinTest,ClassJoinInterfaces)1123 TEST_F(RegTypeClassJoinTest, ClassJoinInterfaces) {
1124 TestClassJoin("LInterfaces$K;", "LInterfaces$L;", "LInterfaces$J;");
1125 }
1126
TEST_F(RegTypeClassJoinTest,ClassJoinInterfaceClass)1127 TEST_F(RegTypeClassJoinTest, ClassJoinInterfaceClass) {
1128 TestClassJoin("LInterfaces$B;", "LInterfaces$L;", "LInterfaces$J;");
1129 }
1130
TEST_F(RegTypeClassJoinTest,ClassJoinClassClass)1131 TEST_F(RegTypeClassJoinTest, ClassJoinClassClass) {
1132 // This test codifies that we prefer the class hierarchy over interfaces. It's a mostly
1133 // arbitrary choice, optimally we'd have set types and could handle multi-inheritance precisely.
1134 TestClassJoin("LInterfaces$A;", "LInterfaces$B;", "Ljava/lang/Object;");
1135 }
1136
TEST_F(RegTypeClassJoinTest,LookupByTypeIndex)1137 TEST_F(RegTypeClassJoinTest, LookupByTypeIndex) {
1138 ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
1139 ScopedObjectAccess soa(Thread::Current());
1140 ScopedNullHandle<mirror::ClassLoader> loader;
1141 RegTypeCache cache(soa.Self(), class_linker_, arena_pool, loader, dex_file_.get());
1142
1143 auto get_type_index = [&](std::string_view descriptor) {
1144 const dex::TypeId* type_id = dex_file_->FindTypeId(descriptor);
1145 CHECK(type_id != nullptr);
1146 return dex_file_->GetIndexForTypeId(*type_id);
1147 };
1148
1149 ASSERT_EQ(&cache.Boolean(), &cache.FromTypeIndex(get_type_index("Z")));
1150 ASSERT_EQ(&cache.Byte(), &cache.FromTypeIndex(get_type_index("B")));
1151 ASSERT_EQ(&cache.Char(), &cache.FromTypeIndex(get_type_index("C")));
1152 ASSERT_EQ(&cache.Short(), &cache.FromTypeIndex(get_type_index("S")));
1153 ASSERT_EQ(&cache.Integer(), &cache.FromTypeIndex(get_type_index("I")));
1154 ASSERT_EQ(&cache.LongLo(), &cache.FromTypeIndex(get_type_index("J")));
1155 ASSERT_EQ(&cache.Float(), &cache.FromTypeIndex(get_type_index("F")));
1156 ASSERT_EQ(&cache.DoubleLo(), &cache.FromTypeIndex(get_type_index("D")));
1157 ASSERT_EQ(&cache.Conflict(), &cache.FromTypeIndex(get_type_index("V")));
1158 }
1159
1160 } // namespace verifier
1161 } // namespace art
1162