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