blob: 047771f4a5f2d4323f1b2339a09e46e8a319e455 [file] [log] [blame]
Mathieu Chartierfaf83202017-06-08 10:35:20 -07001/*
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
Mathieu Chartierfaf83202017-06-08 10:35:20 -070020#include <map>
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070021#include <vector>
22
23#include "base/macros.h"
Mathieu Chartierfaf83202017-06-08 10:35:20 -070024
25namespace art {
26
27class 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.
31template <class IndexType, template<typename Type> class Allocator>
32class 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_;
Mathieu Chartierfaf83202017-06-08 10:35:20 -070066 const DexFile* current_dex_file_ = nullptr;
67 IndexVector* current_vector_ = nullptr;
68 VectorAllocator vector_allocator_;
69
70 ALWAYS_INLINE IndexVector* GetOrInsertVector(const DexFile* dex) {
Mathieu Chartierdb40eac2017-06-09 18:34:11 -070071 // Optimize for adding to same vector in succession, the cached dex file and vector aims to
72 // prevent map lookups.
Mathieu Chartierfaf83202017-06-08 10:35:20 -070073 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_