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: 33 ReferenceTypePropagationTest() : graph_(CreateGraph()), propagation_(nullptr) { } 34 35 ~ReferenceTypePropagationTest() { } 36 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. 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. 54 ReferenceTypeInfo InvalidType() { 55 return ReferenceTypeInfo::CreateInvalid(); 56 } 57 58 // Helper method to construct the Object type. 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. 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 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 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 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