1 /* 2 * Copyright (C) 2013 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_RUNTIME_MIRROR_DEX_CACHE_INL_H_ 18 #define ART_RUNTIME_MIRROR_DEX_CACHE_INL_H_ 19 20 #include "dex_cache.h" 21 22 #include "art_field-inl.h" 23 #include "art_method-inl.h" 24 #include "base/casts.h" 25 #include "base/logging.h" 26 #include "mirror/class.h" 27 #include "runtime.h" 28 29 namespace art { 30 namespace mirror { 31 32 inline uint32_t DexCache::ClassSize(size_t pointer_size) { 33 uint32_t vtable_entries = Object::kVTableLength + 5; 34 return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size); 35 } 36 37 inline String* DexCache::GetResolvedString(uint32_t string_idx) { 38 DCHECK_LT(string_idx, NumStrings()); 39 return GetStrings()[string_idx].Read(); 40 } 41 42 inline void DexCache::SetResolvedString(uint32_t string_idx, String* resolved) { 43 DCHECK_LT(string_idx, NumStrings()); 44 // TODO default transaction support. 45 GetStrings()[string_idx] = GcRoot<String>(resolved); 46 // TODO: Fine-grained marking, so that we don't need to go through all arrays in full. 47 Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(this); 48 } 49 50 inline Class* DexCache::GetResolvedType(uint32_t type_idx) { 51 DCHECK_LT(type_idx, NumResolvedTypes()); 52 return GetResolvedTypes()[type_idx].Read(); 53 } 54 55 inline void DexCache::SetResolvedType(uint32_t type_idx, Class* resolved) { 56 DCHECK_LT(type_idx, NumResolvedTypes()); // NOTE: Unchecked, i.e. not throwing AIOOB. 57 // TODO default transaction support. 58 GetResolvedTypes()[type_idx] = GcRoot<Class>(resolved); 59 // TODO: Fine-grained marking, so that we don't need to go through all arrays in full. 60 Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(this); 61 } 62 63 inline ArtField* DexCache::GetResolvedField(uint32_t field_idx, size_t ptr_size) { 64 DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size); 65 DCHECK_LT(field_idx, NumResolvedFields()); // NOTE: Unchecked, i.e. not throwing AIOOB. 66 ArtField* field = GetElementPtrSize(GetResolvedFields(), field_idx, ptr_size); 67 if (field == nullptr || field->GetDeclaringClass()->IsErroneous()) { 68 return nullptr; 69 } 70 return field; 71 } 72 73 inline void DexCache::SetResolvedField(uint32_t field_idx, ArtField* field, size_t ptr_size) { 74 DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size); 75 DCHECK_LT(field_idx, NumResolvedFields()); // NOTE: Unchecked, i.e. not throwing AIOOB. 76 SetElementPtrSize(GetResolvedFields(), field_idx, field, ptr_size); 77 } 78 79 inline ArtMethod* DexCache::GetResolvedMethod(uint32_t method_idx, size_t ptr_size) { 80 DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size); 81 DCHECK_LT(method_idx, NumResolvedMethods()); // NOTE: Unchecked, i.e. not throwing AIOOB. 82 ArtMethod* method = GetElementPtrSize<ArtMethod*>(GetResolvedMethods(), method_idx, ptr_size); 83 // Hide resolution trampoline methods from the caller 84 if (method != nullptr && method->IsRuntimeMethod()) { 85 DCHECK_EQ(method, Runtime::Current()->GetResolutionMethod()); 86 return nullptr; 87 } 88 return method; 89 } 90 91 inline void DexCache::SetResolvedMethod(uint32_t method_idx, ArtMethod* method, size_t ptr_size) { 92 DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size); 93 DCHECK_LT(method_idx, NumResolvedMethods()); // NOTE: Unchecked, i.e. not throwing AIOOB. 94 SetElementPtrSize(GetResolvedMethods(), method_idx, method, ptr_size); 95 } 96 97 template <typename PtrType> 98 inline PtrType DexCache::GetElementPtrSize(PtrType* ptr_array, size_t idx, size_t ptr_size) { 99 if (ptr_size == 8u) { 100 uint64_t element = reinterpret_cast<const uint64_t*>(ptr_array)[idx]; 101 return reinterpret_cast<PtrType>(dchecked_integral_cast<uintptr_t>(element)); 102 } else { 103 DCHECK_EQ(ptr_size, 4u); 104 uint32_t element = reinterpret_cast<const uint32_t*>(ptr_array)[idx]; 105 return reinterpret_cast<PtrType>(dchecked_integral_cast<uintptr_t>(element)); 106 } 107 } 108 109 template <typename PtrType> 110 inline void DexCache::SetElementPtrSize(PtrType* ptr_array, 111 size_t idx, 112 PtrType ptr, 113 size_t ptr_size) { 114 if (ptr_size == 8u) { 115 reinterpret_cast<uint64_t*>(ptr_array)[idx] = 116 dchecked_integral_cast<uint64_t>(reinterpret_cast<uintptr_t>(ptr)); 117 } else { 118 DCHECK_EQ(ptr_size, 4u); 119 reinterpret_cast<uint32_t*>(ptr_array)[idx] = 120 dchecked_integral_cast<uint32_t>(reinterpret_cast<uintptr_t>(ptr)); 121 } 122 } 123 124 template <bool kVisitNativeRoots, 125 VerifyObjectFlags kVerifyFlags, 126 ReadBarrierOption kReadBarrierOption, 127 typename Visitor> 128 inline void DexCache::VisitReferences(mirror::Class* klass, const Visitor& visitor) { 129 // Visit instance fields first. 130 VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor); 131 // Visit arrays after. 132 if (kVisitNativeRoots) { 133 GcRoot<mirror::String>* strings = GetStrings(); 134 for (size_t i = 0, num_strings = NumStrings(); i != num_strings; ++i) { 135 visitor.VisitRootIfNonNull(strings[i].AddressWithoutBarrier()); 136 } 137 GcRoot<mirror::Class>* resolved_types = GetResolvedTypes(); 138 for (size_t i = 0, num_types = NumResolvedTypes(); i != num_types; ++i) { 139 visitor.VisitRootIfNonNull(resolved_types[i].AddressWithoutBarrier()); 140 } 141 } 142 } 143 144 template <ReadBarrierOption kReadBarrierOption, typename Visitor> 145 inline void DexCache::FixupStrings(GcRoot<mirror::String>* dest, const Visitor& visitor) { 146 GcRoot<mirror::String>* src = GetStrings(); 147 for (size_t i = 0, count = NumStrings(); i < count; ++i) { 148 mirror::String* source = src[i].Read<kReadBarrierOption>(); 149 mirror::String* new_source = visitor(source); 150 dest[i] = GcRoot<mirror::String>(new_source); 151 } 152 } 153 154 template <ReadBarrierOption kReadBarrierOption, typename Visitor> 155 inline void DexCache::FixupResolvedTypes(GcRoot<mirror::Class>* dest, const Visitor& visitor) { 156 GcRoot<mirror::Class>* src = GetResolvedTypes(); 157 for (size_t i = 0, count = NumResolvedTypes(); i < count; ++i) { 158 mirror::Class* source = src[i].Read<kReadBarrierOption>(); 159 mirror::Class* new_source = visitor(source); 160 dest[i] = GcRoot<mirror::Class>(new_source); 161 } 162 } 163 164 } // namespace mirror 165 } // namespace art 166 167 #endif // ART_RUNTIME_MIRROR_DEX_CACHE_INL_H_ 168