/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ART_RUNTIME_DEX_REFERENCE_COLLECTION_H_ #define ART_RUNTIME_DEX_REFERENCE_COLLECTION_H_ #include #include #include "base/macros.h" namespace art { class DexFile; // Collection of dex references that is more memory efficient than a vector of pairs. // Also allows quick lookups of all of the references for a single dex. template class Allocator> class DexReferenceCollection { public: using VectorAllocator = Allocator; using IndexVector = std::vector; using MapAllocator = Allocator>; using DexFileMap = std::map< const DexFile*, IndexVector, std::less, Allocator>>; DexReferenceCollection(const MapAllocator& map_allocator = MapAllocator(), const VectorAllocator& vector_allocator = VectorAllocator()) : map_(map_allocator), vector_allocator_(vector_allocator) {} void AddReference(const DexFile* dex, IndexType index) { GetOrInsertVector(dex)->push_back(index); } DexFileMap& GetMap() { return map_; } size_t NumReferences() const { size_t ret = 0; for (auto&& pair : map_) { ret += pair.second.size(); } return ret; } private: DexFileMap map_; const DexFile* current_dex_file_ = nullptr; IndexVector* current_vector_ = nullptr; VectorAllocator vector_allocator_; ALWAYS_INLINE IndexVector* GetOrInsertVector(const DexFile* dex) { // Optimize for adding to same vector in succession, the cached dex file and vector aims to // prevent map lookups. if (UNLIKELY(current_dex_file_ != dex)) { // There is an assumption that constructing an empty vector wont do any allocations. If this // incorrect, this might leak for the arena case. current_vector_ = &map_.emplace(dex, IndexVector(vector_allocator_)).first->second; current_dex_file_ = dex; } return current_vector_; } }; } // namespace art #endif // ART_RUNTIME_DEX_REFERENCE_COLLECTION_H_