1 /* 2 * Copyright (C) 2024 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 #ifndef ART_COMPILER_OPTIMIZING_REFERENCE_TYPE_INFO_H_ 18 #define ART_COMPILER_OPTIMIZING_REFERENCE_TYPE_INFO_H_ 19 20 #include <iosfwd> 21 22 #include "base/globals.h" 23 #include "base/logging.h" 24 #include "base/macros.h" 25 #include "base/value_object.h" 26 #include "handle.h" 27 #include "mirror/class-inl.h" 28 29 namespace art HIDDEN { 30 31 class ReferenceTypeInfo : ValueObject { 32 public: 33 using TypeHandle = Handle<mirror::Class>; 34 Create(TypeHandle type_handle,bool is_exact)35 static ReferenceTypeInfo Create(TypeHandle type_handle, bool is_exact) { 36 if (kIsDebugBuild) { 37 DCheckValidTypeInfo(type_handle, is_exact); 38 } 39 return ReferenceTypeInfo(type_handle, is_exact); 40 } 41 Create(TypeHandle type_handle)42 static ReferenceTypeInfo Create(TypeHandle type_handle) REQUIRES_SHARED(Locks::mutator_lock_) { 43 return Create(type_handle, type_handle->CannotBeAssignedFromOtherTypes()); 44 } 45 CreateUnchecked(TypeHandle type_handle,bool is_exact)46 static ReferenceTypeInfo CreateUnchecked(TypeHandle type_handle, bool is_exact) { 47 return ReferenceTypeInfo(type_handle, is_exact); 48 } 49 CreateInvalid()50 static ReferenceTypeInfo CreateInvalid() { return ReferenceTypeInfo(); } 51 IsValidHandle(TypeHandle handle)52 static bool IsValidHandle(TypeHandle handle) { 53 return handle.GetReference() != nullptr; 54 } 55 IsValid()56 bool IsValid() const { 57 return IsValidHandle(type_handle_); 58 } 59 IsExact()60 bool IsExact() const { return is_exact_; } 61 IsObjectClass()62 bool IsObjectClass() const REQUIRES_SHARED(Locks::mutator_lock_) { 63 DCHECK(IsValid()); 64 return GetTypeHandle()->IsObjectClass(); 65 } 66 IsStringClass()67 bool IsStringClass() const REQUIRES_SHARED(Locks::mutator_lock_) { 68 DCHECK(IsValid()); 69 return GetTypeHandle()->IsStringClass(); 70 } 71 IsObjectArray()72 bool IsObjectArray() const REQUIRES_SHARED(Locks::mutator_lock_) { 73 DCHECK(IsValid()); 74 return IsArrayClass() && GetTypeHandle()->GetComponentType()->IsObjectClass(); 75 } 76 IsInterface()77 bool IsInterface() const REQUIRES_SHARED(Locks::mutator_lock_) { 78 DCHECK(IsValid()); 79 return GetTypeHandle()->IsInterface(); 80 } 81 IsArrayClass()82 bool IsArrayClass() const REQUIRES_SHARED(Locks::mutator_lock_) { 83 DCHECK(IsValid()); 84 return GetTypeHandle()->IsArrayClass(); 85 } 86 IsPrimitiveArrayClass()87 bool IsPrimitiveArrayClass() const REQUIRES_SHARED(Locks::mutator_lock_) { 88 DCHECK(IsValid()); 89 return GetTypeHandle()->IsPrimitiveArray(); 90 } 91 IsNonPrimitiveArrayClass()92 bool IsNonPrimitiveArrayClass() const REQUIRES_SHARED(Locks::mutator_lock_) { 93 DCHECK(IsValid()); 94 return IsArrayClass() && !GetTypeHandle()->IsPrimitiveArray(); 95 } 96 CanArrayHold(ReferenceTypeInfo rti)97 bool CanArrayHold(ReferenceTypeInfo rti) const REQUIRES_SHARED(Locks::mutator_lock_) { 98 DCHECK(IsValid()); 99 if (!IsExact()) return false; 100 if (!IsArrayClass()) return false; 101 return GetTypeHandle()->GetComponentType()->IsAssignableFrom(rti.GetTypeHandle().Get()); 102 } 103 CanArrayHoldValuesOf(ReferenceTypeInfo rti)104 bool CanArrayHoldValuesOf(ReferenceTypeInfo rti) const REQUIRES_SHARED(Locks::mutator_lock_) { 105 DCHECK(IsValid()); 106 if (!IsExact()) return false; 107 if (!IsArrayClass()) return false; 108 if (!rti.IsArrayClass()) return false; 109 return GetTypeHandle()->GetComponentType()->IsAssignableFrom( 110 rti.GetTypeHandle()->GetComponentType()); 111 } 112 GetTypeHandle()113 Handle<mirror::Class> GetTypeHandle() const { return type_handle_; } 114 IsSupertypeOf(ReferenceTypeInfo rti)115 bool IsSupertypeOf(ReferenceTypeInfo rti) const REQUIRES_SHARED(Locks::mutator_lock_) { 116 DCHECK(IsValid()); 117 DCHECK(rti.IsValid()); 118 return GetTypeHandle()->IsAssignableFrom(rti.GetTypeHandle().Get()); 119 } 120 121 // Returns true if the type information provide the same amount of details. 122 // Note that it does not mean that the instructions have the same actual type 123 // (because the type can be the result of a merge). IsEqual(ReferenceTypeInfo rti)124 bool IsEqual(ReferenceTypeInfo rti) const REQUIRES_SHARED(Locks::mutator_lock_) { 125 if (!IsValid() && !rti.IsValid()) { 126 // Invalid types are equal. 127 return true; 128 } 129 if (!IsValid() || !rti.IsValid()) { 130 // One is valid, the other not. 131 return false; 132 } 133 return IsExact() == rti.IsExact() && GetTypeHandle().Get() == rti.GetTypeHandle().Get(); 134 } 135 136 private: ReferenceTypeInfo()137 ReferenceTypeInfo() : type_handle_(TypeHandle()), is_exact_(false) {} ReferenceTypeInfo(TypeHandle type_handle,bool is_exact)138 ReferenceTypeInfo(TypeHandle type_handle, bool is_exact) 139 : type_handle_(type_handle), is_exact_(is_exact) { } 140 141 static void DCheckValidTypeInfo(TypeHandle type_handle, bool is_exact); 142 143 // The class of the object. 144 TypeHandle type_handle_; 145 // Whether or not the type is exact or a superclass of the actual type. 146 // Whether or not we have any information about this type. 147 bool is_exact_; 148 }; 149 150 std::ostream& operator<<(std::ostream& os, const ReferenceTypeInfo& rhs); 151 152 } // namespace art 153 154 #endif // ART_COMPILER_OPTIMIZING_REFERENCE_TYPE_INFO_H_ 155