xref: /aosp_15_r20/art/runtime/verifier/reg_type_test.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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