cpp

Coverage Report

Created: 2022-09-21 22:22

/home/andy/git/oilshell/oil/mycpp/gc_list.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef LIST_TYPES_H
2
#define LIST_TYPES_H
3
4
#include <algorithm>  // sort() is templated
5
6
#include "mycpp/comparators.h"
7
8
class ValueError;
9
10
// Type that is layout-compatible with List (unit tests assert this).  Two
11
// purposes:
12
// - To make globals of "plain old data" at compile-time, not at startup time.
13
//   This can't be done with subclasses of Obj.
14
// - To avoid invalid-offsetof warnings when computing GC masks.
15
16
template <typename T, int N>
17
class GlobalList {
18
 public:
19
  OBJ_HEADER()
20
  int len_;
21
  int capacity_;
22
  GlobalSlab<T, N>* slab_;
23
};
24
25
// A list has one Slab pointer which we need to follow.
26
508
constexpr uint16_t maskof_List() {
27
508
  return maskbit(offsetof(GlobalList<int COMMA 1>, slab_));
28
508
}
29
30
template <typename T>
31
class List : public Obj {
32
  // TODO: Move methods that don't allocate or resize: out of gc_heap?
33
  // - allocate: append(), extend()
34
  // - resize: pop(), clear()
35
  // - neither: reverse(), sort() -- these are more like functions.  Except
36
  //   sort() is a templated method that depends on type param T.
37
  // - neither: index(), slice()
38
39
  // 8 / 4 = 2 items, or 8 / 8 = 1 item
40
  static const int kCapacityAdjust = kSlabHeaderSize / sizeof(T);
41
  static_assert(kSlabHeaderSize % sizeof(T) == 0,
42
                "Slab header size should be multiple of item size");
43
44
 public:
45
508
  List() : Obj(Tag::FixedSize, maskof_List(), sizeof(List<T>)) {
46
    // Ensured by heap zeroing.  It's never directly on the stack.
47
508
    assert(len_ == 0);
48
0
    assert(capacity_ == 0);
49
0
    assert(slab_ == nullptr);
50
508
  }
_ZN4ListIP3StrEC2Ev
Line
Count
Source
45
102
  List() : Obj(Tag::FixedSize, maskof_List(), sizeof(List<T>)) {
46
    // Ensured by heap zeroing.  It's never directly on the stack.
47
102
    assert(len_ == 0);
48
0
    assert(capacity_ == 0);
49
0
    assert(slab_ == nullptr);
50
102
  }
_ZN4ListIiEC2Ev
Line
Count
Source
45
330
  List() : Obj(Tag::FixedSize, maskof_List(), sizeof(List<T>)) {
46
    // Ensured by heap zeroing.  It's never directly on the stack.
47
330
    assert(len_ == 0);
48
0
    assert(capacity_ == 0);
49
0
    assert(slab_ == nullptr);
50
330
  }
_ZN4ListIbEC2Ev
Line
Count
Source
45
3
  List() : Obj(Tag::FixedSize, maskof_List(), sizeof(List<T>)) {
46
    // Ensured by heap zeroing.  It's never directly on the stack.
47
3
    assert(len_ == 0);
48
0
    assert(capacity_ == 0);
49
0
    assert(slab_ == nullptr);
50
3
  }
_ZN4ListIdEC2Ev
Line
Count
Source
45
2
  List() : Obj(Tag::FixedSize, maskof_List(), sizeof(List<T>)) {
46
    // Ensured by heap zeroing.  It's never directly on the stack.
47
2
    assert(len_ == 0);
48
0
    assert(capacity_ == 0);
49
0
    assert(slab_ == nullptr);
50
2
  }
_ZN4ListIP6Tuple2IP3StriEEC2Ev
Line
Count
Source
45
1
  List() : Obj(Tag::FixedSize, maskof_List(), sizeof(List<T>)) {
46
    // Ensured by heap zeroing.  It's never directly on the stack.
47
1
    assert(len_ == 0);
48
0
    assert(capacity_ == 0);
49
0
    assert(slab_ == nullptr);
50
1
  }
_ZN4ListIP6Tuple2IiP3StrEEC2Ev
Line
Count
Source
45
2
  List() : Obj(Tag::FixedSize, maskof_List(), sizeof(List<T>)) {
46
    // Ensured by heap zeroing.  It's never directly on the stack.
47
2
    assert(len_ == 0);
48
0
    assert(capacity_ == 0);
49
0
    assert(slab_ == nullptr);
50
2
  }
_ZN4ListIPN10hnode_asdl5fieldEEC2Ev
Line
Count
Source
45
34
  List() : Obj(Tag::FixedSize, maskof_List(), sizeof(List<T>)) {
46
    // Ensured by heap zeroing.  It's never directly on the stack.
47
34
    assert(len_ == 0);
48
0
    assert(capacity_ == 0);
49
0
    assert(slab_ == nullptr);
50
34
  }
_ZN4ListIPN10hnode_asdl7hnode_tEEC2Ev
Line
Count
Source
45
34
  List() : Obj(Tag::FixedSize, maskof_List(), sizeof(List<T>)) {
46
    // Ensured by heap zeroing.  It's never directly on the stack.
47
34
    assert(len_ == 0);
48
0
    assert(capacity_ == 0);
49
0
    assert(slab_ == nullptr);
50
34
  }
51
52
  // Implements L[i]
53
  T index_(int i);
54
55
  // returns index of the element
56
  int index(T element);
57
58
  // Implements L[i] = item
59
  // Note: Unlike Dict::set(), we don't need to specialize List::set() on T for
60
  // StackRoots because it doesn't allocate.
61
  void set(int i, T item);
62
63
  // L[begin:]
64
  List* slice(int begin);
65
66
  // L[begin:end]
67
  // TODO: Can this be optimized?
68
  List* slice(int begin, int end);
69
70
  // Should we have a separate API that doesn't return it?
71
  // https://stackoverflow.com/questions/12600330/pop-back-return-value
72
  T pop();
73
74
  // Used in osh/word_parse.py to remove from front
75
  // TODO: Don't accept an arbitrary index?
76
  T pop(int i);
77
78
  void clear();
79
80
  // Used in osh/string_ops.py
81
  void reverse();
82
83
  // Templated function
84
  void sort();
85
86
  // Ensure that there's space for a number of items
87
  void reserve(int n);
88
89
  // Append a single element to this list.  Must be specialized List<int> vs
90
  // List<Str*>.
91
  //
92
  // NOTE(Jesse): The 'must be a specialized List<int> vs List<Str*>' part of
93
  // the comment above is correct, however the entirety of the codebase
94
  // completely ignores it.  See @template_specialization_append_pointer for
95
  // more details and the solution.
96
  //
97
  void append(T item);
98
99
  // Extend this list with multiple elements.
100
  void extend(List<T>* other);
101
102
  int len_;       // number of entries
103
  int capacity_;  // max entries before resizing
104
105
  // The container may be resized, so this field isn't in-line.
106
  Slab<T>* slab_;
107
108
  DISALLOW_COPY_AND_ASSIGN(List)
109
};
110
111
// "Constructors" as free functions since we can't allocate within a
112
// constructor.  Allocation may cause garbage collection, which interferes with
113
// placement new.
114
115
template <typename T>
116
324
List<T>* NewList() {
117
324
  return Alloc<List<T>>();
118
324
}
_Z7NewListIiEP4ListIT_Ev
Line
Count
Source
116
307
List<T>* NewList() {
117
307
  return Alloc<List<T>>();
118
307
}
_Z7NewListIP3StrEP4ListIT_Ev
Line
Count
Source
116
17
List<T>* NewList() {
117
17
  return Alloc<List<T>>();
118
17
}
Unexecuted instantiation: _Z7NewListIPN10hnode_asdl5fieldEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN10hnode_asdl7hnode_tEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN12runtime_asdl10assign_argEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN12runtime_asdl12part_value_tEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN12runtime_asdl7value_tEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl13compound_wordEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl11word_part_tEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl9command_tEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl6word_tEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl5redirEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl8env_pairEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl11assign_pairEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl6if_armEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl8case_armEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl9name_typeEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl12place_expr_tEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl5paramEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl11type_expr_tEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl7variantEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl12class_item_tEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl11import_nameEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl12UntypedParamEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl10TypedParamEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl5TokenEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl5speckEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl6expr_tEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl13comprehensionEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl20class_literal_term_tEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl17char_class_term_tEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl4re_tEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl9named_argEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIPN11syntax_asdl11string_lineEEP4ListIT_Ev
Unexecuted instantiation: _Z7NewListIP6Tuple2IiP3StrEEP4ListIT_Ev
119
120
// Literal ['foo', 'bar']
121
template <typename T>
122
48
List<T>* NewList(std::initializer_list<T> init) {
123
48
  auto self = Alloc<List<T>>();
124
48
  StackRoots _roots({&self});
125
126
48
  int n = init.size();
127
48
  self->reserve(n);
128
129
48
  int i = 0;
130
107
  for (auto item : init) {
131
107
    self->set(i, item);
132
107
    ++i;
133
107
  }
134
48
  self->len_ = n;
135
48
  return self;
136
48
}
_Z7NewListIP3StrEP4ListIT_ESt16initializer_listIS3_E
Line
Count
Source
122
27
List<T>* NewList(std::initializer_list<T> init) {
123
27
  auto self = Alloc<List<T>>();
124
27
  StackRoots _roots({&self});
125
126
27
  int n = init.size();
127
27
  self->reserve(n);
128
129
27
  int i = 0;
130
45
  for (auto item : init) {
131
45
    self->set(i, item);
132
45
    ++i;
133
45
  }
134
27
  self->len_ = n;
135
27
  return self;
136
27
}
_Z7NewListIiEP4ListIT_ESt16initializer_listIS1_E
Line
Count
Source
122
16
List<T>* NewList(std::initializer_list<T> init) {
123
16
  auto self = Alloc<List<T>>();
124
16
  StackRoots _roots({&self});
125
126
16
  int n = init.size();
127
16
  self->reserve(n);
128
129
16
  int i = 0;
130
50
  for (auto item : init) {
131
50
    self->set(i, item);
132
50
    ++i;
133
50
  }
134
16
  self->len_ = n;
135
16
  return self;
136
16
}
_Z7NewListIdEP4ListIT_ESt16initializer_listIS1_E
Line
Count
Source
122
2
List<T>* NewList(std::initializer_list<T> init) {
123
2
  auto self = Alloc<List<T>>();
124
2
  StackRoots _roots({&self});
125
126
2
  int n = init.size();
127
2
  self->reserve(n);
128
129
2
  int i = 0;
130
6
  for (auto item : init) {
131
6
    self->set(i, item);
132
6
    ++i;
133
6
  }
134
2
  self->len_ = n;
135
2
  return self;
136
2
}
_Z7NewListIP6Tuple2IP3StriEEP4ListIT_ESt16initializer_listIS6_E
Line
Count
Source
122
1
List<T>* NewList(std::initializer_list<T> init) {
123
1
  auto self = Alloc<List<T>>();
124
1
  StackRoots _roots({&self});
125
126
1
  int n = init.size();
127
1
  self->reserve(n);
128
129
1
  int i = 0;
130
2
  for (auto item : init) {
131
2
    self->set(i, item);
132
2
    ++i;
133
2
  }
134
1
  self->len_ = n;
135
1
  return self;
136
1
}
_Z7NewListIP6Tuple2IiP3StrEEP4ListIT_ESt16initializer_listIS6_E
Line
Count
Source
122
1
List<T>* NewList(std::initializer_list<T> init) {
123
1
  auto self = Alloc<List<T>>();
124
1
  StackRoots _roots({&self});
125
126
1
  int n = init.size();
127
1
  self->reserve(n);
128
129
1
  int i = 0;
130
2
  for (auto item : init) {
131
2
    self->set(i, item);
132
2
    ++i;
133
2
  }
134
1
  self->len_ = n;
135
1
  return self;
136
1
}
_Z7NewListIbEP4ListIT_ESt16initializer_listIS1_E
Line
Count
Source
122
1
List<T>* NewList(std::initializer_list<T> init) {
123
1
  auto self = Alloc<List<T>>();
124
1
  StackRoots _roots({&self});
125
126
1
  int n = init.size();
127
1
  self->reserve(n);
128
129
1
  int i = 0;
130
2
  for (auto item : init) {
131
2
    self->set(i, item);
132
2
    ++i;
133
2
  }
134
1
  self->len_ = n;
135
1
  return self;
136
1
}
137
138
// ['foo'] * 3
139
template <typename T>
140
7
List<T>* NewList(T item, int times) {
141
7
  auto self = Alloc<List<T>>();
142
7
  StackRoots _roots({&self});
143
144
7
  self->reserve(times);
145
7
  self->len_ = times;
146
28
  for (int i = 0; i < times; ++i) {
147
21
    self->set(i, item);
148
21
  }
149
7
  return self;
150
7
}
_Z7NewListIP3StrEP4ListIT_ES3_i
Line
Count
Source
140
3
List<T>* NewList(T item, int times) {
141
3
  auto self = Alloc<List<T>>();
142
3
  StackRoots _roots({&self});
143
144
3
  self->reserve(times);
145
3
  self->len_ = times;
146
12
  for (int i = 0; i < times; ++i) {
147
9
    self->set(i, item);
148
9
  }
149
3
  return self;
150
3
}
_Z7NewListIbEP4ListIT_ES1_i
Line
Count
Source
140
2
List<T>* NewList(T item, int times) {
141
2
  auto self = Alloc<List<T>>();
142
2
  StackRoots _roots({&self});
143
144
2
  self->reserve(times);
145
2
  self->len_ = times;
146
8
  for (int i = 0; i < times; ++i) {
147
6
    self->set(i, item);
148
6
  }
149
2
  return self;
150
2
}
_Z7NewListIiEP4ListIT_ES1_i
Line
Count
Source
140
2
List<T>* NewList(T item, int times) {
141
2
  auto self = Alloc<List<T>>();
142
2
  StackRoots _roots({&self});
143
144
2
  self->reserve(times);
145
2
  self->len_ = times;
146
8
  for (int i = 0; i < times; ++i) {
147
6
    self->set(i, item);
148
6
  }
149
2
  return self;
150
2
}
151
152
// e.g. List<int>
153
template <typename T>
154
2.52k
void list_append(List<T>* self, T item) {
155
2.52k
  StackRoots _roots({&self});
156
157
2.52k
  self->reserve(self->len_ + 1);
158
2.52k
  self->set(self->len_, item);
159
2.52k
  ++self->len_;
160
2.52k
}
161
162
// e.g. List<Str*>
163
template <typename T>
164
318
void list_append(List<T*>* self, T* item) {
165
318
  StackRoots _roots({&self, &item});
166
167
318
  self->reserve(self->len_ + 1);
168
318
  self->set(self->len_, item);
169
318
  ++self->len_;
170
318
}
_Z11list_appendI3StrEvP4ListIPT_ES3_
Line
Count
Source
164
257
void list_append(List<T*>* self, T* item) {
165
257
  StackRoots _roots({&self, &item});
166
167
257
  self->reserve(self->len_ + 1);
168
257
  self->set(self->len_, item);
169
257
  ++self->len_;
170
257
}
Unexecuted instantiation: _Z11list_appendI6Tuple2IP3StriEEvP4ListIPT_ES6_
_Z11list_appendIN10hnode_asdl5fieldEEvP4ListIPT_ES4_
Line
Count
Source
164
60
void list_append(List<T*>* self, T* item) {
165
60
  StackRoots _roots({&self, &item});
166
167
60
  self->reserve(self->len_ + 1);
168
60
  self->set(self->len_, item);
169
60
  ++self->len_;
170
60
}
_Z11list_appendI6Tuple2IiP3StrEEvP4ListIPT_ES6_
Line
Count
Source
164
1
void list_append(List<T*>* self, T* item) {
165
1
  StackRoots _roots({&self, &item});
166
167
1
  self->reserve(self->len_ + 1);
168
1
  self->set(self->len_, item);
169
1
  ++self->len_;
170
1
}
171
172
template <typename T>
173
2.84k
void List<T>::append(T item) {
174
2.84k
  list_append(this, item);
175
2.84k
}
_ZN4ListIiE6appendEi
Line
Count
Source
173
2.52k
void List<T>::append(T item) {
174
2.52k
  list_append(this, item);
175
2.52k
}
_ZN4ListIP3StrE6appendES1_
Line
Count
Source
173
257
void List<T>::append(T item) {
174
257
  list_append(this, item);
175
257
}
Unexecuted instantiation: _ZN4ListIP6Tuple2IP3StriEE6appendES4_
_ZN4ListIPN10hnode_asdl5fieldEE6appendES2_
Line
Count
Source
173
60
void List<T>::append(T item) {
174
60
  list_append(this, item);
175
60
}
_ZN4ListIP6Tuple2IiP3StrEE6appendES4_
Line
Count
Source
173
1
void List<T>::append(T item) {
174
1
  list_append(this, item);
175
1
}
176
177
template <typename T>
178
2.09k
int len(const List<T>* L) {
179
2.09k
  return L->len_;
180
2.09k
}
_Z3lenIiEiPK4ListIT_E
Line
Count
Source
178
1.95k
int len(const List<T>* L) {
179
1.95k
  return L->len_;
180
1.95k
}
_Z3lenIbEiPK4ListIT_E
Line
Count
Source
178
2
int len(const List<T>* L) {
179
2
  return L->len_;
180
2
}
_Z3lenIdEiPK4ListIT_E
Line
Count
Source
178
4
int len(const List<T>* L) {
179
4
  return L->len_;
180
4
}
_Z3lenIP3StrEiPK4ListIT_E
Line
Count
Source
178
140
int len(const List<T>* L) {
179
140
  return L->len_;
180
140
}
_Z3lenIP6Tuple2IiP3StrEEiPK4ListIT_E
Line
Count
Source
178
1
int len(const List<T>* L) {
179
1
  return L->len_;
180
1
}
181
182
template <typename T>
183
List<T>* list_repeat(T item, int times);
184
185
template <typename T>
186
inline bool list_contains(List<T>* haystack, T needle);
187
188
18
inline int int_cmp(int a, int b) {
189
18
  if (a == b) {
190
4
    return 0;
191
4
  }
192
14
  return a < b ? -1 : 1;
193
18
}
194
195
inline int str_cmp(Str* a, Str* b);
196
inline bool _cmp(Str* a, Str* b);
197
198
// NOTE(Jesse): Move to gc_dict_impl once I get there
199
template <typename K, typename V>
200
class Dict;
201
202
template <typename V>
203
List<Str*>* sorted(Dict<Str*, V>* d);
204
205
/* template <typename T> */
206
/* void List<T>::sort(); */
207
208
// L[begin:]
209
template <typename T>
210
305
List<T>* List<T>::slice(int begin) {
211
305
  if (begin < 0) {
212
0
    begin = len_ + begin;
213
0
  }
214
215
305
  assert(begin >= 0);
216
217
0
  auto self = this;
218
305
  List<T>* result = nullptr;
219
305
  StackRoots _roots({&self, &result});
220
221
305
  result = NewList<T>();
222
223
1.51k
  for (int i = begin; i < self->len_; i++) {
224
1.21k
    result->append(self->slab_->items_[i]);
225
1.21k
  }
226
227
305
  return result;
228
305
}
_ZN4ListIiE5sliceEi
Line
Count
Source
210
302
List<T>* List<T>::slice(int begin) {
211
302
  if (begin < 0) {
212
0
    begin = len_ + begin;
213
0
  }
214
215
302
  assert(begin >= 0);
216
217
0
  auto self = this;
218
302
  List<T>* result = nullptr;
219
302
  StackRoots _roots({&self, &result});
220
221
302
  result = NewList<T>();
222
223
1.50k
  for (int i = begin; i < self->len_; i++) {
224
1.20k
    result->append(self->slab_->items_[i]);
225
1.20k
  }
226
227
302
  return result;
228
302
}
_ZN4ListIP3StrE5sliceEi
Line
Count
Source
210
3
List<T>* List<T>::slice(int begin) {
211
3
  if (begin < 0) {
212
0
    begin = len_ + begin;
213
0
  }
214
215
3
  assert(begin >= 0);
216
217
0
  auto self = this;
218
3
  List<T>* result = nullptr;
219
3
  StackRoots _roots({&self, &result});
220
221
3
  result = NewList<T>();
222
223
9
  for (int i = begin; i < self->len_; i++) {
224
6
    result->append(self->slab_->items_[i]);
225
6
  }
226
227
3
  return result;
228
3
}
229
230
// L[begin:end]
231
// TODO: Can this be optimized?
232
template <typename T>
233
2
List<T>* List<T>::slice(int begin, int end) {
234
2
  if (begin < 0) {
235
1
    begin = len_ + begin;
236
1
  }
237
2
  if (end < 0) {
238
2
    end = len_ + end;
239
2
  }
240
241
2
  assert(end <= len_);
242
0
  assert(begin >= 0);
243
0
  assert(end >= 0);
244
245
0
  auto self = this;
246
2
  List<T>* result = nullptr;
247
2
  StackRoots _roots({&self, &result});
248
249
2
  result = NewList<T>();
250
6
  for (int i = begin; i < end; i++) {
251
4
    result->append(self->slab_->items_[i]);
252
4
  }
253
254
2
  return result;
255
2
}
256
257
// Ensure that there's space for a number of items
258
template <typename T>
259
2.90k
void List<T>::reserve(int n) {
260
  // log("reserve capacity = %d, n = %d", capacity_, n);
261
2.90k
  auto self = this;
262
2.90k
  StackRoots _roots({&self});
263
264
  // Don't do anything if there's already enough space.
265
2.90k
  if (self->capacity_ >= n) return;
266
267
  // Example: The user asks for space for 7 integers.  Account for the
268
  // header, and say we need 9 to determine the obj length.  9 is
269
  // rounded up to 16, for a 64-byte obj.  Then we actually have space
270
  // for 14 items.
271
479
  self->capacity_ = RoundUp(n + kCapacityAdjust) - kCapacityAdjust;
272
479
  auto new_slab = NewSlab<T>(self->capacity_);
273
274
479
  if (self->len_ > 0) {
275
    // log("Copying %d bytes", len_ * sizeof(T));
276
13
    memcpy(new_slab->items_, self->slab_->items_, self->len_ * sizeof(T));
277
13
  }
278
479
  self->slab_ = new_slab;
279
479
}
_ZN4ListIP3StrE7reserveEi
Line
Count
Source
259
287
void List<T>::reserve(int n) {
260
  // log("reserve capacity = %d, n = %d", capacity_, n);
261
287
  auto self = this;
262
287
  StackRoots _roots({&self});
263
264
  // Don't do anything if there's already enough space.
265
287
  if (self->capacity_ >= n) return;
266
267
  // Example: The user asks for space for 7 integers.  Account for the
268
  // header, and say we need 9 to determine the obj length.  9 is
269
  // rounded up to 16, for a 64-byte obj.  Then we actually have space
270
  // for 14 items.
271
101
  self->capacity_ = RoundUp(n + kCapacityAdjust) - kCapacityAdjust;
272
101
  auto new_slab = NewSlab<T>(self->capacity_);
273
274
101
  if (self->len_ > 0) {
275
    // log("Copying %d bytes", len_ * sizeof(T));
276
5
    memcpy(new_slab->items_, self->slab_->items_, self->len_ * sizeof(T));
277
5
  }
278
101
  self->slab_ = new_slab;
279
101
}
_ZN4ListIiE7reserveEi
Line
Count
Source
259
2.54k
void List<T>::reserve(int n) {
260
  // log("reserve capacity = %d, n = %d", capacity_, n);
261
2.54k
  auto self = this;
262
2.54k
  StackRoots _roots({&self});
263
264
  // Don't do anything if there's already enough space.
265
2.54k
  if (self->capacity_ >= n) return;
266
267
  // Example: The user asks for space for 7 integers.  Account for the
268
  // header, and say we need 9 to determine the obj length.  9 is
269
  // rounded up to 16, for a 64-byte obj.  Then we actually have space
270
  // for 14 items.
271
336
  self->capacity_ = RoundUp(n + kCapacityAdjust) - kCapacityAdjust;
272
336
  auto new_slab = NewSlab<T>(self->capacity_);
273
274
336
  if (self->len_ > 0) {
275
    // log("Copying %d bytes", len_ * sizeof(T));
276
8
    memcpy(new_slab->items_, self->slab_->items_, self->len_ * sizeof(T));
277
8
  }
278
336
  self->slab_ = new_slab;
279
336
}
_ZN4ListIbE7reserveEi
Line
Count
Source
259
3
void List<T>::reserve(int n) {
260
  // log("reserve capacity = %d, n = %d", capacity_, n);
261
3
  auto self = this;
262
3
  StackRoots _roots({&self});
263
264
  // Don't do anything if there's already enough space.
265
3
  if (self->capacity_ >= n) return;
266
267
  // Example: The user asks for space for 7 integers.  Account for the
268
  // header, and say we need 9 to determine the obj length.  9 is
269
  // rounded up to 16, for a 64-byte obj.  Then we actually have space
270
  // for 14 items.
271
3
  self->capacity_ = RoundUp(n + kCapacityAdjust) - kCapacityAdjust;
272
3
  auto new_slab = NewSlab<T>(self->capacity_);
273
274
3
  if (self->len_ > 0) {
275
    // log("Copying %d bytes", len_ * sizeof(T));
276
0
    memcpy(new_slab->items_, self->slab_->items_, self->len_ * sizeof(T));
277
0
  }
278
3
  self->slab_ = new_slab;
279
3
}
_ZN4ListIdE7reserveEi
Line
Count
Source
259
2
void List<T>::reserve(int n) {
260
  // log("reserve capacity = %d, n = %d", capacity_, n);
261
2
  auto self = this;
262
2
  StackRoots _roots({&self});
263
264
  // Don't do anything if there's already enough space.
265
2
  if (self->capacity_ >= n) return;
266
267
  // Example: The user asks for space for 7 integers.  Account for the
268
  // header, and say we need 9 to determine the obj length.  9 is
269
  // rounded up to 16, for a 64-byte obj.  Then we actually have space
270
  // for 14 items.
271
2
  self->capacity_ = RoundUp(n + kCapacityAdjust) - kCapacityAdjust;
272
2
  auto new_slab = NewSlab<T>(self->capacity_);
273
274
2
  if (self->len_ > 0) {
275
    // log("Copying %d bytes", len_ * sizeof(T));
276
0
    memcpy(new_slab->items_, self->slab_->items_, self->len_ * sizeof(T));
277
0
  }
278
2
  self->slab_ = new_slab;
279
2
}
_ZN4ListIP6Tuple2IP3StriEE7reserveEi
Line
Count
Source
259
1
void List<T>::reserve(int n) {
260
  // log("reserve capacity = %d, n = %d", capacity_, n);
261
1
  auto self = this;
262
1
  StackRoots _roots({&self});
263
264
  // Don't do anything if there's already enough space.
265
1
  if (self->capacity_ >= n) return;
266
267
  // Example: The user asks for space for 7 integers.  Account for the
268
  // header, and say we need 9 to determine the obj length.  9 is
269
  // rounded up to 16, for a 64-byte obj.  Then we actually have space
270
  // for 14 items.
271
1
  self->capacity_ = RoundUp(n + kCapacityAdjust) - kCapacityAdjust;
272
1
  auto new_slab = NewSlab<T>(self->capacity_);
273
274
1
  if (self->len_ > 0) {
275
    // log("Copying %d bytes", len_ * sizeof(T));
276
0
    memcpy(new_slab->items_, self->slab_->items_, self->len_ * sizeof(T));
277
0
  }
278
1
  self->slab_ = new_slab;
279
1
}
_ZN4ListIP6Tuple2IiP3StrEE7reserveEi
Line
Count
Source
259
2
void List<T>::reserve(int n) {
260
  // log("reserve capacity = %d, n = %d", capacity_, n);
261
2
  auto self = this;
262
2
  StackRoots _roots({&self});
263
264
  // Don't do anything if there's already enough space.
265
2
  if (self->capacity_ >= n) return;
266
267
  // Example: The user asks for space for 7 integers.  Account for the
268
  // header, and say we need 9 to determine the obj length.  9 is
269
  // rounded up to 16, for a 64-byte obj.  Then we actually have space
270
  // for 14 items.
271
2
  self->capacity_ = RoundUp(n + kCapacityAdjust) - kCapacityAdjust;
272
2
  auto new_slab = NewSlab<T>(self->capacity_);
273
274
2
  if (self->len_ > 0) {
275
    // log("Copying %d bytes", len_ * sizeof(T));
276
0
    memcpy(new_slab->items_, self->slab_->items_, self->len_ * sizeof(T));
277
0
  }
278
2
  self->slab_ = new_slab;
279
2
}
_ZN4ListIPN10hnode_asdl5fieldEE7reserveEi
Line
Count
Source
259
60
void List<T>::reserve(int n) {
260
  // log("reserve capacity = %d, n = %d", capacity_, n);
261
60
  auto self = this;
262
60
  StackRoots _roots({&self});
263
264
  // Don't do anything if there's already enough space.
265
60
  if (self->capacity_ >= n) return;
266
267
  // Example: The user asks for space for 7 integers.  Account for the
268
  // header, and say we need 9 to determine the obj length.  9 is
269
  // rounded up to 16, for a 64-byte obj.  Then we actually have space
270
  // for 14 items.
271
34
  self->capacity_ = RoundUp(n + kCapacityAdjust) - kCapacityAdjust;
272
34
  auto new_slab = NewSlab<T>(self->capacity_);
273
274
34
  if (self->len_ > 0) {
275
    // log("Copying %d bytes", len_ * sizeof(T));
276
0
    memcpy(new_slab->items_, self->slab_->items_, self->len_ * sizeof(T));
277
0
  }
278
34
  self->slab_ = new_slab;
279
34
}
280
281
// Implements L[i] = item
282
// Note: Unlike Dict::set(), we don't need to specialize List::set() on T for
283
// StackRoots because it doesn't allocate.
284
template <typename T>
285
2.98k
void List<T>::set(int i, T item) {
286
2.98k
  if (i < 0) {
287
0
    i = len_ + i;
288
0
  }
289
290
2.98k
  assert(i >= 0);
291
0
  assert(i < capacity_);
292
293
0
  slab_->items_[i] = item;
294
2.98k
}
_ZN4ListIP3StrE3setEiS1_
Line
Count
Source
285
314
void List<T>::set(int i, T item) {
286
314
  if (i < 0) {
287
0
    i = len_ + i;
288
0
  }
289
290
314
  assert(i >= 0);
291
0
  assert(i < capacity_);
292
293
0
  slab_->items_[i] = item;
294
314
}
_ZN4ListIiE3setEii
Line
Count
Source
285
2.59k
void List<T>::set(int i, T item) {
286
2.59k
  if (i < 0) {
287
0
    i = len_ + i;
288
0
  }
289
290
2.59k
  assert(i >= 0);
291
0
  assert(i < capacity_);
292
293
0
  slab_->items_[i] = item;
294
2.59k
}
_ZN4ListIbE3setEib
Line
Count
Source
285
8
void List<T>::set(int i, T item) {
286
8
  if (i < 0) {
287
0
    i = len_ + i;
288
0
  }
289
290
8
  assert(i >= 0);
291
0
  assert(i < capacity_);
292
293
0
  slab_->items_[i] = item;
294
8
}
_ZN4ListIdE3setEid
Line
Count
Source
285
6
void List<T>::set(int i, T item) {
286
6
  if (i < 0) {
287
0
    i = len_ + i;
288
0
  }
289
290
6
  assert(i >= 0);
291
0
  assert(i < capacity_);
292
293
0
  slab_->items_[i] = item;
294
6
}
_ZN4ListIP6Tuple2IP3StriEE3setEiS4_
Line
Count
Source
285
2
void List<T>::set(int i, T item) {
286
2
  if (i < 0) {
287
0
    i = len_ + i;
288
0
  }
289
290
2
  assert(i >= 0);
291
0
  assert(i < capacity_);
292
293
0
  slab_->items_[i] = item;
294
2
}
_ZN4ListIP6Tuple2IiP3StrEE3setEiS4_
Line
Count
Source
285
3
void List<T>::set(int i, T item) {
286
3
  if (i < 0) {
287
0
    i = len_ + i;
288
0
  }
289
290
3
  assert(i >= 0);
291
0
  assert(i < capacity_);
292
293
0
  slab_->items_[i] = item;
294
3
}
_ZN4ListIPN10hnode_asdl5fieldEE3setEiS2_
Line
Count
Source
285
60
void List<T>::set(int i, T item) {
286
60
  if (i < 0) {
287
0
    i = len_ + i;
288
0
  }
289
290
60
  assert(i >= 0);
291
0
  assert(i < capacity_);
292
293
0
  slab_->items_[i] = item;
294
60
}
295
296
// Implements L[i]
297
template <typename T>
298
593
T List<T>::index_(int i) {
299
593
  if (i < 0) {
300
4
    int j = len_ + i;
301
4
    assert(j < len_);
302
0
    assert(j >= 0);
303
0
    return slab_->items_[j];
304
4
  }
305
306
589
  assert(i < len_);
307
0
  assert(i >= 0);
308
0
  return slab_->items_[i];
309
593
}
_ZN4ListIiE6index_Ei
Line
Count
Source
298
72
T List<T>::index_(int i) {
299
72
  if (i < 0) {
300
1
    int j = len_ + i;
301
1
    assert(j < len_);
302
0
    assert(j >= 0);
303
0
    return slab_->items_[j];
304
1
  }
305
306
71
  assert(i < len_);
307
0
  assert(i >= 0);
308
0
  return slab_->items_[i];
309
72
}
_ZN4ListIbE6index_Ei
Line
Count
Source
298
4
T List<T>::index_(int i) {
299
4
  if (i < 0) {
300
0
    int j = len_ + i;
301
0
    assert(j < len_);
302
0
    assert(j >= 0);
303
0
    return slab_->items_[j];
304
0
  }
305
306
4
  assert(i < len_);
307
0
  assert(i >= 0);
308
0
  return slab_->items_[i];
309
4
}
_ZN4ListIdE6index_Ei
Line
Count
Source
298
8
T List<T>::index_(int i) {
299
8
  if (i < 0) {
300
0
    int j = len_ + i;
301
0
    assert(j < len_);
302
0
    assert(j >= 0);
303
0
    return slab_->items_[j];
304
0
  }
305
306
8
  assert(i < len_);
307
0
  assert(i >= 0);
308
0
  return slab_->items_[i];
309
8
}
_ZN4ListIP3StrE6index_Ei
Line
Count
Source
298
509
T List<T>::index_(int i) {
299
509
  if (i < 0) {
300
3
    int j = len_ + i;
301
3
    assert(j < len_);
302
0
    assert(j >= 0);
303
0
    return slab_->items_[j];
304
3
  }
305
306
506
  assert(i < len_);
307
0
  assert(i >= 0);
308
0
  return slab_->items_[i];
309
509
}
310
311
// L.index(i) -- Python method
312
template <typename T>
313
int List<T>::index(T value) {
314
  int element_count = len(this);
315
  for (int i = 0; i < element_count; i++) {
316
    if (are_equal(slab_->items_[i], value)) {
317
      return i;
318
    }
319
  }
320
  throw Alloc<ValueError>();
321
}
322
323
// Should we have a separate API that doesn't return it?
324
// https://stackoverflow.com/questions/12600330/pop-back-return-value
325
template <typename T>
326
5
T List<T>::pop() {
327
5
  assert(len_ > 0);
328
0
  len_--;
329
5
  T result = slab_->items_[len_];
330
5
  slab_->items_[len_] = 0;  // zero for GC scan
331
5
  return result;
332
5
}
_ZN4ListIiE3popEv
Line
Count
Source
326
1
T List<T>::pop() {
327
1
  assert(len_ > 0);
328
0
  len_--;
329
1
  T result = slab_->items_[len_];
330
1
  slab_->items_[len_] = 0;  // zero for GC scan
331
1
  return result;
332
1
}
_ZN4ListIP3StrE3popEv
Line
Count
Source
326
4
T List<T>::pop() {
327
4
  assert(len_ > 0);
328
0
  len_--;
329
4
  T result = slab_->items_[len_];
330
4
  slab_->items_[len_] = 0;  // zero for GC scan
331
4
  return result;
332
4
}
333
334
// Used in osh/word_parse.py to remove from front
335
// TODO: Don't accept an arbitrary index?
336
//
337
// NOTE(Jesse): This operation is typically called 'shift' I think
338
template <typename T>
339
2
T List<T>::pop(int i) {
340
2
  assert(len_ > 0);
341
0
  assert(i == 0);  // only support popping the first item
342
343
0
  T result = index_(0);
344
2
  len_--;
345
346
  // Shift everything by one
347
2
  memmove(slab_->items_, slab_->items_ + 1, len_ * sizeof(T));
348
349
  /*
350
  for (int j = 0; j < len_; j++) {
351
    slab_->items_[j] = slab_->items_[j+1];
352
  }
353
  */
354
355
2
  slab_->items_[len_] = 0;  // zero for GC scan
356
2
  return result;
357
2
}
358
359
template <typename T>
360
3
void List<T>::clear() {
361
3
  memset(slab_->items_, 0, len_ * sizeof(T));  // zero for GC scan
362
3
  len_ = 0;
363
3
}
_ZN4ListIiE5clearEv
Line
Count
Source
360
2
void List<T>::clear() {
361
2
  memset(slab_->items_, 0, len_ * sizeof(T));  // zero for GC scan
362
2
  len_ = 0;
363
2
}
_ZN4ListIP3StrE5clearEv
Line
Count
Source
360
1
void List<T>::clear() {
361
1
  memset(slab_->items_, 0, len_ * sizeof(T));  // zero for GC scan
362
1
  len_ = 0;
363
1
}
364
365
// Used in osh/string_ops.py
366
template <typename T>
367
4
void List<T>::reverse() {
368
8
  for (int i = 0; i < len_ / 2; ++i) {
369
    // log("swapping %d and %d", i, n-i);
370
4
    T tmp = slab_->items_[i];
371
4
    int j = len_ - 1 - i;
372
4
    slab_->items_[i] = slab_->items_[j];
373
4
    slab_->items_[j] = tmp;
374
4
  }
375
4
}
_ZN4ListIiE7reverseEv
Line
Count
Source
367
4
void List<T>::reverse() {
368
8
  for (int i = 0; i < len_ / 2; ++i) {
369
    // log("swapping %d and %d", i, n-i);
370
4
    T tmp = slab_->items_[i];
371
4
    int j = len_ - 1 - i;
372
4
    slab_->items_[i] = slab_->items_[j];
373
4
    slab_->items_[j] = tmp;
374
4
  }
375
4
}
Unexecuted instantiation: _ZN4ListIP3StrE7reverseEv
376
377
// Extend this list with multiple elements.
378
template <typename T>
379
3
void List<T>::extend(List<T>* other) {
380
3
  auto self = this;
381
3
  StackRoots _roots({&self, &other});
382
383
3
  int n = other->len_;
384
3
  int new_len = self->len_ + n;
385
3
  self->reserve(new_len);
386
387
12
  for (int i = 0; i < n; ++i) {
388
9
    self->set(self->len_ + i, other->slab_->items_[i]);
389
9
  }
390
3
  self->len_ = new_len;
391
3
}
_ZN4ListIiE6extendEPS0_
Line
Count
Source
379
3
void List<T>::extend(List<T>* other) {
380
3
  auto self = this;
381
3
  StackRoots _roots({&self, &other});
382
383
3
  int n = other->len_;
384
3
  int new_len = self->len_ + n;
385
3
  self->reserve(new_len);
386
387
12
  for (int i = 0; i < n; ++i) {
388
9
    self->set(self->len_ + i, other->slab_->items_[i]);
389
9
  }
390
3
  self->len_ = new_len;
391
3
}
Unexecuted instantiation: _ZN4ListIP3StrE6extendEPS2_
392
393
// NOTE(Jesse): It's highly sus that we have str_equals and str_cmp..
394
// shouldn't we write one in terms of the other?
395
//
396
// @duplicate_string_compare_code
397
//
398
// Used by [[ a > b ]] and so forth
399
25
inline int str_cmp(Str* a, Str* b) {
400
25
  int len_a = len(a);
401
25
  int len_b = len(b);
402
403
25
  int min = std::min(len_a, len_b);
404
25
  if (min == 0) {
405
8
    return int_cmp(len_a, len_b);
406
8
  }
407
17
  int comp = memcmp(a->data_, b->data_, min);
408
17
  if (comp == 0) {
409
4
    return int_cmp(len_a, len_b);  // tiebreaker
410
4
  }
411
13
  return comp;
412
17
}
413
414
13
inline bool _cmp(Str* a, Str* b) {
415
13
  return str_cmp(a, b) < 0;
416
13
}
417
418
template <typename T>
419
3
void List<T>::sort() {
420
3
  std::sort(slab_->items_, slab_->items_ + len_, _cmp);
421
3
}
422
423
/* template <typename T> */
424
/* int len(const List<T>* L) { */
425
/*   return L->len_; */
426
/* } */
427
428
// TODO: mycpp can just generate the constructor instead?
429
// e.g. [None] * 3
430
template <typename T>
431
5
List<T>* list_repeat(T item, int times) {
432
5
  return NewList<T>(item, times);
433
5
}
_Z11list_repeatIP3StrEP4ListIT_ES3_i
Line
Count
Source
431
3
List<T>* list_repeat(T item, int times) {
432
3
  return NewList<T>(item, times);
433
3
}
_Z11list_repeatIbEP4ListIT_ES1_i
Line
Count
Source
431
2
List<T>* list_repeat(T item, int times) {
432
2
  return NewList<T>(item, times);
433
2
}
434
435
#if 0
436
template <typename T>
437
List<T>* NewList() {
438
  return Alloc<List<T>>();
439
}
440
441
// Literal ['foo', 'bar']
442
template <typename T>
443
List<T>* NewList(std::initializer_list<T> init) {
444
  auto self = Alloc<List<T>>();
445
  StackRoots _roots({&self});
446
447
  int n = init.size();
448
  self->reserve(n);
449
450
  int i = 0;
451
  for (auto item : init) {
452
    self->set(i, item);
453
    ++i;
454
  }
455
  self->len_ = n;
456
  return self;
457
}
458
459
// ['foo'] * 3
460
template <typename T>
461
List<T>* NewList(T item, int times) {
462
  auto self = Alloc<List<T>>();
463
  StackRoots _roots({&self});
464
465
  self->reserve(times);
466
  self->len_ = times;
467
  for (int i = 0; i < times; ++i) {
468
    self->set(i, item);
469
  }
470
  return self;
471
}
472
#endif
473
474
// e.g. 'a' in ['a', 'b', 'c']
475
template <typename T>
476
19
inline bool list_contains(List<T>* haystack, T needle) {
477
  // StackRoots _roots({&haystack, &needle});  // doesn't allocate
478
479
19
  int n = len(haystack);
480
43
  for (int i = 0; i < n; ++i) {
481
35
    if (are_equal(haystack->index_(i), needle)) {
482
11
      return true;
483
11
    }
484
35
  }
485
8
  return false;
486
19
}
_Z13list_containsIP3StrEbP4ListIT_ES3_
Line
Count
Source
476
9
inline bool list_contains(List<T>* haystack, T needle) {
477
  // StackRoots _roots({&haystack, &needle});  // doesn't allocate
478
479
9
  int n = len(haystack);
480
20
  for (int i = 0; i < n; ++i) {
481
16
    if (are_equal(haystack->index_(i), needle)) {
482
5
      return true;
483
5
    }
484
16
  }
485
4
  return false;
486
9
}
_Z13list_containsIiEbP4ListIT_ES1_
Line
Count
Source
476
6
inline bool list_contains(List<T>* haystack, T needle) {
477
  // StackRoots _roots({&haystack, &needle});  // doesn't allocate
478
479
6
  int n = len(haystack);
480
13
  for (int i = 0; i < n; ++i) {
481
11
    if (are_equal(haystack->index_(i), needle)) {
482
4
      return true;
483
4
    }
484
11
  }
485
2
  return false;
486
6
}
_Z13list_containsIdEbP4ListIT_ES1_
Line
Count
Source
476
4
inline bool list_contains(List<T>* haystack, T needle) {
477
  // StackRoots _roots({&haystack, &needle});  // doesn't allocate
478
479
4
  int n = len(haystack);
480
10
  for (int i = 0; i < n; ++i) {
481
8
    if (are_equal(haystack->index_(i), needle)) {
482
2
      return true;
483
2
    }
484
8
  }
485
2
  return false;
486
4
}
487
488
// NOTE(Jesse): Move to gc_dict_impl once I get there
489
template <typename K, typename V>
490
class Dict;
491
492
template <typename V>
493
1
List<Str*>* sorted(Dict<Str*, V>* d) {
494
1
  auto keys = d->keys();
495
1
  keys->sort();
496
1
  return keys;
497
1
}
498
499
// list(L) copies the list
500
template <typename T>
501
List<T>* list(List<T>* other) {
502
  auto result = NewList<T>();
503
  for (int i = 0; i < len(other); ++i) {
504
    result->set(i, other->index_(i));
505
  }
506
  return result;
507
}
508
509
#define GLOBAL_LIST(T, N, name, array)                                      \
510
  GlobalSlab<T, N> _slab_##name = {Tag::Global, 0, kZeroMask, kNoObjLen,    \
511
                                   array};                                  \
512
  GlobalList<T, N> _list_##name = {Tag::Global, 0, kZeroMask,    kNoObjLen, \
513
                                   N,           N, &_slab_##name};          \
514
  List<T>* name = reinterpret_cast<List<T>*>(&_list_##name);
515
516
template <class T>
517
class ListIter {
518
 public:
519
112
  explicit ListIter(List<T>* L) : L_(L), i_(0) {
520
    // We need this because ListIter is directly on the stack, and L_ could be
521
    // moved during iteration.
522
112
    gHeap.PushRoot(reinterpret_cast<Obj**>(&L_));
523
112
  }
_ZN8ListIterIiEC2EP4ListIiE
Line
Count
Source
519
6
  explicit ListIter(List<T>* L) : L_(L), i_(0) {
520
    // We need this because ListIter is directly on the stack, and L_ could be
521
    // moved during iteration.
522
6
    gHeap.PushRoot(reinterpret_cast<Obj**>(&L_));
523
6
  }
_ZN8ListIterIP3StrEC2EP4ListIS1_E
Line
Count
Source
519
23
  explicit ListIter(List<T>* L) : L_(L), i_(0) {
520
    // We need this because ListIter is directly on the stack, and L_ could be
521
    // moved during iteration.
522
23
    gHeap.PushRoot(reinterpret_cast<Obj**>(&L_));
523
23
  }
_ZN8ListIterIP6Tuple2IP3StriEEC2EP4ListIS4_E
Line
Count
Source
519
1
  explicit ListIter(List<T>* L) : L_(L), i_(0) {
520
    // We need this because ListIter is directly on the stack, and L_ could be
521
    // moved during iteration.
522
1
    gHeap.PushRoot(reinterpret_cast<Obj**>(&L_));
523
1
  }
_ZN8ListIterIP6Tuple2IiP3StrEEC2EP4ListIS4_E
Line
Count
Source
519
2
  explicit ListIter(List<T>* L) : L_(L), i_(0) {
520
    // We need this because ListIter is directly on the stack, and L_ could be
521
    // moved during iteration.
522
2
    gHeap.PushRoot(reinterpret_cast<Obj**>(&L_));
523
2
  }
Unexecuted instantiation: _ZN8ListIterIPN10hnode_asdl7hnode_tEEC2EP4ListIS2_E
_ZN8ListIterIPN10hnode_asdl5fieldEEC2EP4ListIS2_E
Line
Count
Source
519
79
  explicit ListIter(List<T>* L) : L_(L), i_(0) {
520
    // We need this because ListIter is directly on the stack, and L_ could be
521
    // moved during iteration.
522
79
    gHeap.PushRoot(reinterpret_cast<Obj**>(&L_));
523
79
  }
_ZN8ListIterIbEC2EP4ListIbE
Line
Count
Source
519
1
  explicit ListIter(List<T>* L) : L_(L), i_(0) {
520
    // We need this because ListIter is directly on the stack, and L_ could be
521
    // moved during iteration.
522
1
    gHeap.PushRoot(reinterpret_cast<Obj**>(&L_));
523
1
  }
524
112
  ~ListIter() {
525
112
    gHeap.PopRoot();
526
112
  }
_ZN8ListIterIiED2Ev
Line
Count
Source
524
6
  ~ListIter() {
525
6
    gHeap.PopRoot();
526
6
  }
_ZN8ListIterIP3StrED2Ev
Line
Count
Source
524
23
  ~ListIter() {
525
23
    gHeap.PopRoot();
526
23
  }
_ZN8ListIterIP6Tuple2IP3StriEED2Ev
Line
Count
Source
524
1
  ~ListIter() {
525
1
    gHeap.PopRoot();
526
1
  }
_ZN8ListIterIP6Tuple2IiP3StrEED2Ev
Line
Count
Source
524
2
  ~ListIter() {
525
2
    gHeap.PopRoot();
526
2
  }
Unexecuted instantiation: _ZN8ListIterIPN10hnode_asdl7hnode_tEED2Ev
_ZN8ListIterIPN10hnode_asdl5fieldEED2Ev
Line
Count
Source
524
79
  ~ListIter() {
525
79
    gHeap.PopRoot();
526
79
  }
_ZN8ListIterIbED2Ev
Line
Count
Source
524
1
  ~ListIter() {
525
1
    gHeap.PopRoot();
526
1
  }
527
242
  void Next() {
528
242
    i_++;
529
242
  }
_ZN8ListIterIiE4NextEv
Line
Count
Source
527
19
  void Next() {
528
19
    i_++;
529
19
  }
_ZN8ListIterIP3StrE4NextEv
Line
Count
Source
527
97
  void Next() {
528
97
    i_++;
529
97
  }
_ZN8ListIterIP6Tuple2IP3StriEE4NextEv
Line
Count
Source
527
2
  void Next() {
528
2
    i_++;
529
2
  }
_ZN8ListIterIP6Tuple2IiP3StrEE4NextEv
Line
Count
Source
527
4
  void Next() {
528
4
    i_++;
529
4
  }
Unexecuted instantiation: _ZN8ListIterIPN10hnode_asdl7hnode_tEE4NextEv
_ZN8ListIterIPN10hnode_asdl5fieldEE4NextEv
Line
Count
Source
527
118
  void Next() {
528
118
    i_++;
529
118
  }
_ZN8ListIterIbE4NextEv
Line
Count
Source
527
2
  void Next() {
528
2
    i_++;
529
2
  }
530
354
  bool Done() {
531
    // "unsigned size_t was a mistake"
532
354
    return i_ >= static_cast<int>(L_->len_);
533
354
  }
_ZN8ListIterIiE4DoneEv
Line
Count
Source
530
25
  bool Done() {
531
    // "unsigned size_t was a mistake"
532
25
    return i_ >= static_cast<int>(L_->len_);
533
25
  }
_ZN8ListIterIP3StrE4DoneEv
Line
Count
Source
530
120
  bool Done() {
531
    // "unsigned size_t was a mistake"
532
120
    return i_ >= static_cast<int>(L_->len_);
533
120
  }
_ZN8ListIterIP6Tuple2IP3StriEE4DoneEv
Line
Count
Source
530
3
  bool Done() {
531
    // "unsigned size_t was a mistake"
532
3
    return i_ >= static_cast<int>(L_->len_);
533
3
  }
_ZN8ListIterIP6Tuple2IiP3StrEE4DoneEv
Line
Count
Source
530
6
  bool Done() {
531
    // "unsigned size_t was a mistake"
532
6
    return i_ >= static_cast<int>(L_->len_);
533
6
  }
Unexecuted instantiation: _ZN8ListIterIPN10hnode_asdl7hnode_tEE4DoneEv
_ZN8ListIterIPN10hnode_asdl5fieldEE4DoneEv
Line
Count
Source
530
197
  bool Done() {
531
    // "unsigned size_t was a mistake"
532
197
    return i_ >= static_cast<int>(L_->len_);
533
197
  }
_ZN8ListIterIbE4DoneEv
Line
Count
Source
530
3
  bool Done() {
531
    // "unsigned size_t was a mistake"
532
3
    return i_ >= static_cast<int>(L_->len_);
533
3
  }
534
266
  T Value() {
535
266
    return L_->slab_->items_[i_];
536
266
  }
_ZN8ListIterIiE5ValueEv
Line
Count
Source
534
19
  T Value() {
535
19
    return L_->slab_->items_[i_];
536
19
  }
_ZN8ListIterIP3StrE5ValueEv
Line
Count
Source
534
98
  T Value() {
535
98
    return L_->slab_->items_[i_];
536
98
  }
_ZN8ListIterIP6Tuple2IP3StriEE5ValueEv
Line
Count
Source
534
2
  T Value() {
535
2
    return L_->slab_->items_[i_];
536
2
  }
_ZN8ListIterIP6Tuple2IiP3StrEE5ValueEv
Line
Count
Source
534
4
  T Value() {
535
4
    return L_->slab_->items_[i_];
536
4
  }
Unexecuted instantiation: _ZN8ListIterIPN10hnode_asdl7hnode_tEE5ValueEv
_ZN8ListIterIPN10hnode_asdl5fieldEE5ValueEv
Line
Count
Source
534
141
  T Value() {
535
141
    return L_->slab_->items_[i_];
536
141
  }
_ZN8ListIterIbE5ValueEv
Line
Count
Source
534
2
  T Value() {
535
2
    return L_->slab_->items_[i_];
536
2
  }
537
538
 private:
539
  List<T>* L_;
540
  int i_;
541
};
542
543
// TODO: Does using pointers rather than indices make this more efficient?
544
template <class T>
545
class ReverseListIter {
546
 public:
547
4
  explicit ReverseListIter(List<T>* L) : L_(L), i_(L_->len_ - 1) {
548
4
  }
_ZN15ReverseListIterIiEC2EP4ListIiE
Line
Count
Source
547
2
  explicit ReverseListIter(List<T>* L) : L_(L), i_(L_->len_ - 1) {
548
2
  }
_ZN15ReverseListIterIP3StrEC2EP4ListIS1_E
Line
Count
Source
547
1
  explicit ReverseListIter(List<T>* L) : L_(L), i_(L_->len_ - 1) {
548
1
  }
_ZN15ReverseListIterIP6Tuple2IiP3StrEEC2EP4ListIS4_E
Line
Count
Source
547
1
  explicit ReverseListIter(List<T>* L) : L_(L), i_(L_->len_ - 1) {
548
1
  }
549
10
  void Next() {
550
10
    i_--;
551
10
  }
_ZN15ReverseListIterIiE4NextEv
Line
Count
Source
549
6
  void Next() {
550
6
    i_--;
551
6
  }
_ZN15ReverseListIterIP3StrE4NextEv
Line
Count
Source
549
2
  void Next() {
550
2
    i_--;
551
2
  }
_ZN15ReverseListIterIP6Tuple2IiP3StrEE4NextEv
Line
Count
Source
549
2
  void Next() {
550
2
    i_--;
551
2
  }
552
14
  bool Done() {
553
14
    return i_ < 0;
554
14
  }
_ZN15ReverseListIterIiE4DoneEv
Line
Count
Source
552
8
  bool Done() {
553
8
    return i_ < 0;
554
8
  }
_ZN15ReverseListIterIP3StrE4DoneEv
Line
Count
Source
552
3
  bool Done() {
553
3
    return i_ < 0;
554
3
  }
_ZN15ReverseListIterIP6Tuple2IiP3StrEE4DoneEv
Line
Count
Source
552
3
  bool Done() {
553
3
    return i_ < 0;
554
3
  }
555
10
  T Value() {
556
10
    return L_->slab_->items_[i_];
557
10
  }
_ZN15ReverseListIterIiE5ValueEv
Line
Count
Source
555
6
  T Value() {
556
6
    return L_->slab_->items_[i_];
557
6
  }
_ZN15ReverseListIterIP3StrE5ValueEv
Line
Count
Source
555
2
  T Value() {
556
2
    return L_->slab_->items_[i_];
557
2
  }
_ZN15ReverseListIterIP6Tuple2IiP3StrEE5ValueEv
Line
Count
Source
555
2
  T Value() {
556
2
    return L_->slab_->items_[i_];
557
2
  }
558
559
 private:
560
  List<T>* L_;
561
  int i_;
562
};
563
564
#endif  // LIST_TYPES_H