1 /*
2  * Copyright (C) 2016 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 "reference_type_propagation.h"
18 
19 #include "base/arena_allocator.h"
20 #include "builder.h"
21 #include "nodes.h"
22 #include "object_lock.h"
23 #include "optimizing_unit_test.h"
24 
25 namespace art {
26 
27 /**
28  * Fixture class for unit testing the ReferenceTypePropagation phase. Used to verify the
29  * functionality of methods and situations that are hard to set up with checker tests.
30  */
31 class ReferenceTypePropagationTest : public OptimizingUnitTest {
32  public:
ReferenceTypePropagationTest()33   ReferenceTypePropagationTest() : graph_(CreateGraph()), propagation_(nullptr) { }
34 
~ReferenceTypePropagationTest()35   ~ReferenceTypePropagationTest() { }
36 
SetupPropagation(VariableSizedHandleScope * handles)37   void SetupPropagation(VariableSizedHandleScope* handles) {
38     graph_->InitializeInexactObjectRTI(handles);
39     propagation_ = new (GetAllocator()) ReferenceTypePropagation(graph_,
40                                                                  Handle<mirror::ClassLoader>(),
41                                                                  Handle<mirror::DexCache>(),
42                                                                  handles,
43                                                                  true,
44                                                                  "test_prop");
45   }
46 
47   // Relay method to merge type in reference type propagation.
MergeTypes(const ReferenceTypeInfo & a,const ReferenceTypeInfo & b)48   ReferenceTypeInfo MergeTypes(const ReferenceTypeInfo& a,
49                                const ReferenceTypeInfo& b) REQUIRES_SHARED(Locks::mutator_lock_) {
50     return propagation_->MergeTypes(a, b, &propagation_->handle_cache_);
51   }
52 
53   // Helper method to construct an invalid type.
InvalidType()54   ReferenceTypeInfo InvalidType() {
55     return ReferenceTypeInfo::CreateInvalid();
56   }
57 
58   // Helper method to construct the Object type.
ObjectType(bool is_exact=true)59   ReferenceTypeInfo ObjectType(bool is_exact = true) REQUIRES_SHARED(Locks::mutator_lock_) {
60     return ReferenceTypeInfo::Create(propagation_->handle_cache_.GetObjectClassHandle(), is_exact);
61   }
62 
63   // Helper method to construct the String type.
StringType(bool is_exact=true)64   ReferenceTypeInfo StringType(bool is_exact = true) REQUIRES_SHARED(Locks::mutator_lock_) {
65     return ReferenceTypeInfo::Create(propagation_->handle_cache_.GetStringClassHandle(), is_exact);
66   }
67 
68   // General building fields.
69   HGraph* graph_;
70 
71   ReferenceTypePropagation* propagation_;
72 };
73 
74 //
75 // The actual ReferenceTypePropgation unit tests.
76 //
77 
TEST_F(ReferenceTypePropagationTest,ProperSetup)78 TEST_F(ReferenceTypePropagationTest, ProperSetup) {
79   ScopedObjectAccess soa(Thread::Current());
80   VariableSizedHandleScope handles(soa.Self());
81   SetupPropagation(&handles);
82 
83   EXPECT_TRUE(propagation_ != nullptr);
84   EXPECT_TRUE(graph_->GetInexactObjectRti().IsEqual(ObjectType(false)));
85 }
86 
TEST_F(ReferenceTypePropagationTest,MergeInvalidTypes)87 TEST_F(ReferenceTypePropagationTest, MergeInvalidTypes) {
88   ScopedObjectAccess soa(Thread::Current());
89   VariableSizedHandleScope handles(soa.Self());
90   SetupPropagation(&handles);
91 
92   // Two invalid types.
93   ReferenceTypeInfo t1(MergeTypes(InvalidType(), InvalidType()));
94   EXPECT_FALSE(t1.IsValid());
95   EXPECT_FALSE(t1.IsExact());
96   EXPECT_TRUE(t1.IsEqual(InvalidType()));
97 
98   // Valid type on right.
99   ReferenceTypeInfo t2(MergeTypes(InvalidType(), ObjectType()));
100   EXPECT_TRUE(t2.IsValid());
101   EXPECT_TRUE(t2.IsExact());
102   EXPECT_TRUE(t2.IsEqual(ObjectType()));
103   ReferenceTypeInfo t3(MergeTypes(InvalidType(), StringType()));
104   EXPECT_TRUE(t3.IsValid());
105   EXPECT_TRUE(t3.IsExact());
106   EXPECT_TRUE(t3.IsEqual(StringType()));
107 
108   // Valid type on left.
109   ReferenceTypeInfo t4(MergeTypes(ObjectType(), InvalidType()));
110   EXPECT_TRUE(t4.IsValid());
111   EXPECT_TRUE(t4.IsExact());
112   EXPECT_TRUE(t4.IsEqual(ObjectType()));
113   ReferenceTypeInfo t5(MergeTypes(StringType(), InvalidType()));
114   EXPECT_TRUE(t5.IsValid());
115   EXPECT_TRUE(t5.IsExact());
116   EXPECT_TRUE(t5.IsEqual(StringType()));
117 }
118 
TEST_F(ReferenceTypePropagationTest,MergeValidTypes)119 TEST_F(ReferenceTypePropagationTest, MergeValidTypes) {
120   ScopedObjectAccess soa(Thread::Current());
121   VariableSizedHandleScope handles(soa.Self());
122   SetupPropagation(&handles);
123 
124   // Same types.
125   ReferenceTypeInfo t1(MergeTypes(ObjectType(), ObjectType()));
126   EXPECT_TRUE(t1.IsValid());
127   EXPECT_TRUE(t1.IsExact());
128   EXPECT_TRUE(t1.IsEqual(ObjectType()));
129   ReferenceTypeInfo t2(MergeTypes(StringType(), StringType()));
130   EXPECT_TRUE(t2.IsValid());
131   EXPECT_TRUE(t2.IsExact());
132   EXPECT_TRUE(t2.IsEqual(StringType()));
133 
134   // Left is super class of right.
135   ReferenceTypeInfo t3(MergeTypes(ObjectType(), StringType()));
136   EXPECT_TRUE(t3.IsValid());
137   EXPECT_FALSE(t3.IsExact());
138   EXPECT_TRUE(t3.IsEqual(ObjectType(false)));
139 
140   // Right is super class of left.
141   ReferenceTypeInfo t4(MergeTypes(StringType(), ObjectType()));
142   EXPECT_TRUE(t4.IsValid());
143   EXPECT_FALSE(t4.IsExact());
144   EXPECT_TRUE(t4.IsEqual(ObjectType(false)));
145 
146   // Same types, but one or both are inexact.
147   ReferenceTypeInfo t5(MergeTypes(ObjectType(false), ObjectType()));
148   EXPECT_TRUE(t5.IsValid());
149   EXPECT_FALSE(t5.IsExact());
150   EXPECT_TRUE(t5.IsEqual(ObjectType(false)));
151   ReferenceTypeInfo t6(MergeTypes(ObjectType(), ObjectType(false)));
152   EXPECT_TRUE(t6.IsValid());
153   EXPECT_FALSE(t6.IsExact());
154   EXPECT_TRUE(t6.IsEqual(ObjectType(false)));
155   ReferenceTypeInfo t7(MergeTypes(ObjectType(false), ObjectType(false)));
156   EXPECT_TRUE(t7.IsValid());
157   EXPECT_FALSE(t7.IsExact());
158   EXPECT_TRUE(t7.IsEqual(ObjectType(false)));
159 }
160 
161 }  // namespace art
162