Home | History | Annotate | Download | only in runtime
      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 "base/macros.h"
     21 
     22 #include <vector>
     23 #include <map>
     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())
     45       : map_(map_allocator),
     46         vector_allocator_(vector_allocator) {}
     47 
     48   void AddReference(const DexFile* dex, IndexType index) {
     49     GetOrInsertVector(dex)->push_back(index);
     50   }
     51 
     52   DexFileMap& GetMap() {
     53     return map_;
     54   }
     55 
     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 
     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