Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/include/llvm/ADT/AllocatorList.h
Line
Count
Source
1
//===- llvm/ADT/AllocatorList.h - Custom allocator list ---------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#ifndef LLVM_ADT_ALLOCATORLIST_H
10
#define LLVM_ADT_ALLOCATORLIST_H
11
12
#include "llvm/ADT/ilist_node.h"
13
#include "llvm/ADT/iterator.h"
14
#include "llvm/ADT/simple_ilist.h"
15
#include "llvm/Support/Allocator.h"
16
#include <algorithm>
17
#include <cassert>
18
#include <cstddef>
19
#include <iterator>
20
#include <type_traits>
21
#include <utility>
22
23
namespace llvm {
24
25
/// A linked-list with a custom, local allocator.
26
///
27
/// Expose a std::list-like interface that owns and uses a custom LLVM-style
28
/// allocator (e.g., BumpPtrAllocator), leveraging \a simple_ilist for the
29
/// implementation details.
30
///
31
/// Because this list owns the allocator, calling \a splice() with a different
32
/// list isn't generally safe.  As such, \a splice has been left out of the
33
/// interface entirely.
34
template <class T, class AllocatorT> class AllocatorList : AllocatorT {
35
  struct Node : ilist_node<Node> {
36
    Node(Node &&) = delete;
37
    Node(const Node &) = delete;
38
    Node &operator=(Node &&) = delete;
39
    Node &operator=(const Node &) = delete;
40
41
26
    Node(T &&V) : V(std::move(V)) {}
42
1.50M
    Node(const T &V) : V(V) {}
43
    template <class... Ts> Node(Ts &&... Vs) : V(std::forward<Ts>(Vs)...) {}
44
    T V;
45
  };
46
47
  using list_type = simple_ilist<Node>;
48
49
  list_type List;
50
51
3.59M
  AllocatorT &getAlloc() { return *this; }
52
  const AllocatorT &getAlloc() const { return *this; }
53
54
1.50M
  template <class... ArgTs> Node *create(ArgTs &&... Args) {
55
1.50M
    return new (getAlloc()) Node(std::forward<ArgTs>(Args)...);
56
1.50M
  }
llvm::AllocatorList<llvm::yaml::Token, llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul> >::Node* llvm::AllocatorList<llvm::yaml::Token, llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul> >::create<llvm::yaml::Token>(llvm::yaml::Token&&)
Line
Count
Source
54
26
  template <class... ArgTs> Node *create(ArgTs &&... Args) {
55
26
    return new (getAlloc()) Node(std::forward<ArgTs>(Args)...);
56
26
  }
llvm::AllocatorList<llvm::yaml::Token, llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul> >::Node* llvm::AllocatorList<llvm::yaml::Token, llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul> >::create<llvm::yaml::Token const&>(llvm::yaml::Token const&&&)
Line
Count
Source
54
1.50M
  template <class... ArgTs> Node *create(ArgTs &&... Args) {
55
1.50M
    return new (getAlloc()) Node(std::forward<ArgTs>(Args)...);
56
1.50M
  }
57
58
  struct Cloner {
59
    AllocatorList &AL;
60
61
    Cloner(AllocatorList &AL) : AL(AL) {}
62
63
    Node *operator()(const Node &N) const { return AL.create(N.V); }
64
  };
65
66
  struct Disposer {
67
    AllocatorList &AL;
68
69
1.50M
    Disposer(AllocatorList &AL) : AL(AL) {}
70
71
1.50M
    void operator()(Node *N) const {
72
1.50M
      N->~Node();
73
1.50M
      AL.getAlloc().Deallocate(N);
74
1.50M
    }
75
  };
76
77
public:
78
  using value_type = T;
79
  using pointer = T *;
80
  using reference = T &;
81
  using const_pointer = const T *;
82
  using const_reference = const T &;
83
  using size_type = typename list_type::size_type;
84
  using difference_type = typename list_type::difference_type;
85
86
private:
87
  template <class ValueT, class IteratorBase>
88
  class IteratorImpl
89
      : public iterator_adaptor_base<IteratorImpl<ValueT, IteratorBase>,
90
                                     IteratorBase,
91
                                     std::bidirectional_iterator_tag, ValueT> {
92
    template <class OtherValueT, class OtherIteratorBase>
93
    friend class IteratorImpl;
94
    friend AllocatorList;
95
96
    using base_type =
97
        iterator_adaptor_base<IteratorImpl<ValueT, IteratorBase>, IteratorBase,
98
                              std::bidirectional_iterator_tag, ValueT>;
99
100
  public:
101
    using value_type = ValueT;
102
    using pointer = ValueT *;
103
    using reference = ValueT &;
104
105
6.27M
    IteratorImpl() = default;
106
    IteratorImpl(const IteratorImpl &) = default;
107
    IteratorImpl &operator=(const IteratorImpl &) = default;
108
109
9.23M
    explicit IteratorImpl(const IteratorBase &I) : base_type(I) {}
110
111
    template <class OtherValueT, class OtherIteratorBase>
112
    IteratorImpl(const IteratorImpl<OtherValueT, OtherIteratorBase> &X,
113
                 typename std::enable_if<std::is_convertible<
114
                     OtherIteratorBase, IteratorBase>::value>::type * = nullptr)
115
        : base_type(X.wrapped()) {}
116
117
    ~IteratorImpl() = default;
118
119
283k
    reference operator*() const { return base_type::wrapped()->V; }
120
283k
    pointer operator->() const { return &operator*(); }
121
122
2.08M
    friend bool operator==(const IteratorImpl &L, const IteratorImpl &R) {
123
2.08M
      return L.wrapped() == R.wrapped();
124
2.08M
    }
125
625k
    friend bool operator!=(const IteratorImpl &L, const IteratorImpl &R) {
126
625k
      return !(L == R);
127
625k
    }
128
  };
129
130
public:
131
  using iterator = IteratorImpl<T, typename list_type::iterator>;
132
  using reverse_iterator =
133
      IteratorImpl<T, typename list_type::reverse_iterator>;
134
  using const_iterator =
135
      IteratorImpl<const T, typename list_type::const_iterator>;
136
  using const_reverse_iterator =
137
      IteratorImpl<const T, typename list_type::const_reverse_iterator>;
138
139
4.90k
  AllocatorList() = default;
140
  AllocatorList(AllocatorList &&X)
141
      : AllocatorT(std::move(X.getAlloc())), List(std::move(X.List)) {}
142
143
  AllocatorList(const AllocatorList &X) {
144
    List.cloneFrom(X.List, Cloner(*this), Disposer(*this));
145
  }
146
147
  AllocatorList &operator=(AllocatorList &&X) {
148
    clear(); // Dispose of current nodes explicitly.
149
    List = std::move(X.List);
150
    getAlloc() = std::move(X.getAlloc());
151
    return *this;
152
  }
153
154
  AllocatorList &operator=(const AllocatorList &X) {
155
    List.cloneFrom(X.List, Cloner(*this), Disposer(*this));
156
    return *this;
157
  }
158
159
4.79k
  ~AllocatorList() { clear(); }
160
161
  void swap(AllocatorList &RHS) {
162
    List.swap(RHS.List);
163
    std::swap(getAlloc(), RHS.getAlloc());
164
  }
165
166
8.36M
  bool empty() { return List.empty(); }
167
  size_t size() { return List.size(); }
168
169
5.65M
  iterator begin() { return iterator(List.begin()); }
170
2.08M
  iterator end() { return iterator(List.end()); }
171
  const_iterator begin() const { return const_iterator(List.begin()); }
172
  const_iterator end() const { return const_iterator(List.end()); }
173
  reverse_iterator rbegin() { return reverse_iterator(List.rbegin()); }
174
  reverse_iterator rend() { return reverse_iterator(List.rend()); }
175
  const_reverse_iterator rbegin() const {
176
    return const_reverse_iterator(List.rbegin());
177
  }
178
  const_reverse_iterator rend() const {
179
    return const_reverse_iterator(List.rend());
180
  }
181
182
  T &back() { return List.back().V; }
183
4.85M
  T &front() { return List.front().V; }
184
  const T &back() const { return List.back().V; }
185
  const T &front() const { return List.front().V; }
186
187
  template <class... Ts> iterator emplace(iterator I, Ts &&... Vs) {
188
    return iterator(List.insert(I.wrapped(), *create(std::forward<Ts>(Vs)...)));
189
  }
190
191
26
  iterator insert(iterator I, T &&V) {
192
26
    return iterator(List.insert(I.wrapped(), *create(std::move(V))));
193
26
  }
194
1.50M
  iterator insert(iterator I, const T &V) {
195
1.50M
    return iterator(List.insert(I.wrapped(), *create(V)));
196
1.50M
  }
197
198
  template <class Iterator>
199
  void insert(iterator I, Iterator First, Iterator Last) {
200
    for (; First != Last; ++First)
201
      List.insert(I.wrapped(), *create(*First));
202
  }
203
204
  iterator erase(iterator I) {
205
    return iterator(List.eraseAndDispose(I.wrapped(), Disposer(*this)));
206
  }
207
208
  iterator erase(iterator First, iterator Last) {
209
    return iterator(
210
        List.eraseAndDispose(First.wrapped(), Last.wrapped(), Disposer(*this)));
211
  }
212
213
4.82k
  void clear() { List.clearAndDispose(Disposer(*this)); }
214
  void pop_back() { List.eraseAndDispose(--List.end(), Disposer(*this)); }
215
1.49M
  void pop_front() { List.eraseAndDispose(List.begin(), Disposer(*this)); }
216
26
  void push_back(T &&V) { insert(end(), std::move(V)); }
217
  void push_front(T &&V) { insert(begin(), std::move(V)); }
218
1.16M
  void push_back(const T &V) { insert(end(), V); }
219
  void push_front(const T &V) { insert(begin(), V); }
220
  template <class... Ts> void emplace_back(Ts &&... Vs) {
221
    emplace(end(), std::forward<Ts>(Vs)...);
222
  }
223
  template <class... Ts> void emplace_front(Ts &&... Vs) {
224
    emplace(begin(), std::forward<Ts>(Vs)...);
225
  }
226
227
  /// Reset the underlying allocator.
228
  ///
229
  /// \pre \c empty()
230
589k
  void resetAlloc() {
231
589k
    assert(empty() && "Cannot reset allocator if not empty");
232
589k
    getAlloc().Reset();
233
589k
  }
234
};
235
236
template <class T> using BumpPtrList = AllocatorList<T, BumpPtrAllocator>;
237
238
} // end namespace llvm
239
240
#endif // LLVM_ADT_ALLOCATORLIST_H