1 /* 2 * Copyright (C) 2017 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_DEX_REFERENCE_COLLECTION_H_ 18 #define ART_RUNTIME_DEX_REFERENCE_COLLECTION_H_ 19 20 #include <map> 21 #include <vector> 22 23 #include "base/macros.h" 24 25 namespace art { 26 27 class DexFile; 28 29 // Collection of dex references that is more memory efficient than a vector of <dex, index> pairs. 30 // Also allows quick lookups of all of the references for a single dex. 31 template <class IndexType, template<typename Type> class Allocator> 32 class DexReferenceCollection { 33 public: 34 using VectorAllocator = Allocator<IndexType>; 35 using IndexVector = std::vector<IndexType, VectorAllocator>; 36 using MapAllocator = Allocator<std::pair<const DexFile*, IndexVector>>; 37 using DexFileMap = std::map< 38 const DexFile*, 39 IndexVector, 40 std::less<const DexFile*>, 41 Allocator<std::pair<const DexFile* const, IndexVector>>>; 42 43 DexReferenceCollection(const MapAllocator& map_allocator = MapAllocator(), 44 const VectorAllocator& vector_allocator = VectorAllocator()) map_(map_allocator)45 : map_(map_allocator), 46 vector_allocator_(vector_allocator) {} 47 AddReference(const DexFile * dex,IndexType index)48 void AddReference(const DexFile* dex, IndexType index) { 49 GetOrInsertVector(dex)->push_back(index); 50 } 51 GetMap()52 DexFileMap& GetMap() { 53 return map_; 54 } 55 NumReferences()56 size_t NumReferences() const { 57 size_t ret = 0; 58 for (auto&& pair : map_) { 59 ret += pair.second.size(); 60 } 61 return ret; 62 } 63 64 private: 65 DexFileMap map_; 66 const DexFile* current_dex_file_ = nullptr; 67 IndexVector* current_vector_ = nullptr; 68 VectorAllocator vector_allocator_; 69 GetOrInsertVector(const DexFile * dex)70 ALWAYS_INLINE IndexVector* GetOrInsertVector(const DexFile* dex) { 71 // Optimize for adding to same vector in succession, the cached dex file and vector aims to 72 // prevent map lookups. 73 if (UNLIKELY(current_dex_file_ != dex)) { 74 // There is an assumption that constructing an empty vector wont do any allocations. If this 75 // incorrect, this might leak for the arena case. 76 current_vector_ = &map_.emplace(dex, IndexVector(vector_allocator_)).first->second; 77 current_dex_file_ = dex; 78 } 79 return current_vector_; 80 } 81 }; 82 83 } // namespace art 84 85 #endif // ART_RUNTIME_DEX_REFERENCE_COLLECTION_H_ 86