cpp

Coverage Report

Created: 2025-05-19 02:30

/home/uke/oil/mycpp/gc_dict.h
Line
Count
Source (jump to first uncovered line)
1
// Hash table based on CPython's "compact dict":
2
//
3
//   https://mail.python.org/pipermail/python-dev/2012-December/123028.html
4
//   https://code.activestate.com/recipes/578375/
5
//
6
// Main differences:
7
// - It's type-specialized in C++ -- Dict<K, V>.
8
// - It's integrated with our mark and sweep GC, using Slab<int>, Slab<K>, and
9
//   Slab<V>
10
// - We use linear probing, not the pseudo-random number generator
11
12
#ifndef MYCPP_GC_DICT_H
13
#define MYCPP_GC_DICT_H
14
15
#include "mycpp/comparators.h"
16
#include "mycpp/gc_builtins.h"
17
#include "mycpp/gc_list.h"
18
#include "mycpp/hash.h"
19
20
// Non-negative entries in index_ are array indices into keys_ and values_.
21
// There are two special negative entries:
22
23
// index_ value to say this Dict item was deleted (a tombstone).
24
const int kDeletedEntry = -1;
25
26
// index_ value to say this Dict entry is free.
27
const int kEmptyEntry = -2;
28
29
// Return value for find_kv_index(), not stored in index_.
30
const int kNotFound = -3;
31
32
// Return value for hash_and_probe(), not stored in index_.
33
const int kTooSmall = -4;
34
35
// Helper for keys() and values()
36
template <typename T>
37
18
List<T>* ListFromDictSlab(Slab<T>* slab, int n) {
38
18
  List<T>* result = Alloc<List<T>>();
39
18
  result->reserve(n);
40
41
102
  for (int i = 0; i < n; ++i) {
42
84
    result->append(slab->items_[i]);
43
84
  }
44
18
  return result;
45
18
}
_Z16ListFromDictSlabIP6BigStrEP4ListIT_EP4SlabIS3_Ei
Line
Count
Source
37
12
List<T>* ListFromDictSlab(Slab<T>* slab, int n) {
38
12
  List<T>* result = Alloc<List<T>>();
39
12
  result->reserve(n);
40
41
38
  for (int i = 0; i < n; ++i) {
42
26
    result->append(slab->items_[i]);
43
26
  }
44
12
  return result;
45
12
}
_Z16ListFromDictSlabIiEP4ListIT_EP4SlabIS1_Ei
Line
Count
Source
37
6
List<T>* ListFromDictSlab(Slab<T>* slab, int n) {
38
6
  List<T>* result = Alloc<List<T>>();
39
6
  result->reserve(n);
40
41
64
  for (int i = 0; i < n; ++i) {
42
58
    result->append(slab->items_[i]);
43
58
  }
44
6
  return result;
45
6
}
46
47
// GlobalDict is layout-compatible with Dict (unit tests assert this), and it
48
// can be a true C global (incurs zero startup time)
49
50
template <typename K, typename V, int N>
51
class GlobalDict {
52
 public:
53
  int len_;
54
  int capacity_;
55
  int index_len_;
56
  GlobalSlab<int, N>* index_;
57
  GlobalSlab<K, N>* keys_;
58
  GlobalSlab<V, N>* values_;
59
};
60
61
#define GLOBAL_DICT(name, K, V, N, keys, vals)                                 \
62
  GcGlobal<GlobalSlab<K, N>> _keys_##name = {ObjHeader::Global(TypeTag::Slab), \
63
                                             {.items_ = keys}};                \
64
  GcGlobal<GlobalSlab<V, N>> _vals_##name = {ObjHeader::Global(TypeTag::Slab), \
65
                                             {.items_ = vals}};                \
66
  GcGlobal<GlobalDict<K, V, N>> _dict_##name = {                               \
67
      ObjHeader::Global(TypeTag::Dict),                                        \
68
      {.len_ = N,                                                              \
69
       .capacity_ = N,                                                         \
70
       .index_len_ = 0,                                                        \
71
       .index_ = nullptr,                                                      \
72
       .keys_ = &_keys_##name.obj,                                             \
73
       .values_ = &_vals_##name.obj},                                          \
74
  };                                                                           \
75
  Dict<K, V>* name = reinterpret_cast<Dict<K, V>*>(&_dict_##name.obj);
76
77
template <class K, class V>
78
class Dict {
79
 public:
80
  Dict()
81
      : len_(0),
82
        capacity_(0),
83
        index_len_(0),
84
        index_(nullptr),
85
        keys_(nullptr),
86
115
        values_(nullptr) {
87
115
  }
_ZN4DictIP6BigStriEC2Ev
Line
Count
Source
86
20
        values_(nullptr) {
87
20
  }
_ZN4DictIP6BigStrS1_EC2Ev
Line
Count
Source
86
12
        values_(nullptr) {
87
12
  }
_ZN4DictIibEC2Ev
Line
Count
Source
86
38
        values_(nullptr) {
87
38
  }
_ZN4DictIiiEC2Ev
Line
Count
Source
86
16
        values_(nullptr) {
87
16
  }
_ZN4DictIP5PointP6BigStrEC2Ev
Line
Count
Source
86
2
        values_(nullptr) {
87
2
  }
_ZN4DictIiP6BigStrEC2Ev
Line
Count
Source
86
10
        values_(nullptr) {
87
10
  }
_ZN4DictIlP6BigStrEC2Ev
Line
Count
Source
86
4
        values_(nullptr) {
87
4
  }
_ZN4DictIP6Tuple2IiiEiEC2Ev
Line
Count
Source
86
2
        values_(nullptr) {
87
2
  }
_ZN4DictIP6Tuple2IP6BigStriEiEC2Ev
Line
Count
Source
86
2
        values_(nullptr) {
87
2
  }
Unexecuted instantiation: _ZN4DictIiP6Tuple2IP4ListIPS1_IPS0_IiiEEEPS_IiiEEEC2Ev
_ZN4DictIP6BigStrPN4args7_ActionEEC2Ev
Line
Count
Source
86
6
        values_(nullptr) {
87
6
  }
_ZN4DictIP6BigStrPN10value_asdl7value_tEEC2Ev
Line
Count
Source
86
3
        values_(nullptr) {
87
3
  }
88
89
  Dict(std::initializer_list<K> keys, std::initializer_list<V> values)
90
      : len_(0),
91
        capacity_(0),
92
        index_len_(0),
93
        index_(nullptr),
94
        keys_(nullptr),
95
6
        values_(nullptr) {
96
6
    DCHECK(keys.size() == values.size());
97
0
    auto v = values.begin();  // This simulates a "zip" loop
98
9
    for (auto key : keys) {
99
      // note: calls reserve(), and may allocate
100
9
      this->set(key, *v);
101
9
      ++v;
102
9
    }
103
6
  }
_ZN4DictIP6BigStriEC2ESt16initializer_listIS1_ES3_IiE
Line
Count
Source
95
3
        values_(nullptr) {
96
3
    DCHECK(keys.size() == values.size());
97
0
    auto v = values.begin();  // This simulates a "zip" loop
98
6
    for (auto key : keys) {
99
      // note: calls reserve(), and may allocate
100
6
      this->set(key, *v);
101
6
      ++v;
102
6
    }
103
3
  }
_ZN4DictIP6BigStrS1_EC2ESt16initializer_listIS1_ES4_
Line
Count
Source
95
1
        values_(nullptr) {
96
1
    DCHECK(keys.size() == values.size());
97
0
    auto v = values.begin();  // This simulates a "zip" loop
98
1
    for (auto key : keys) {
99
      // note: calls reserve(), and may allocate
100
1
      this->set(key, *v);
101
1
      ++v;
102
1
    }
103
1
  }
_ZN4DictIiP6BigStrEC2ESt16initializer_listIiES3_IS1_E
Line
Count
Source
95
2
        values_(nullptr) {
96
2
    DCHECK(keys.size() == values.size());
97
0
    auto v = values.begin();  // This simulates a "zip" loop
98
2
    for (auto key : keys) {
99
      // note: calls reserve(), and may allocate
100
2
      this->set(key, *v);
101
2
      ++v;
102
2
    }
103
2
  }
104
105
  // Reserve enough space for at LEAST this many key-value pairs.
106
  void reserve(int num_desired);
107
108
  // d[key] in Python: raises KeyError if not found
109
  V at(K key) const;
110
111
  // d.get(key) in Python. (Can't use this if V isn't a pointer!)
112
  V get(K key) const;
113
114
  // Get a key, but return a default if not found.
115
  // expr_parse.py uses this with OTHER_BALANCE
116
  V get(K key, V default_val) const;
117
118
  // Implements d[k] = v.  May resize the dictionary.
119
  void set(K key, V val);
120
121
  void update(List<Tuple2<K, V>*>* pairs);
122
  void update(Dict<K, V>* other);
123
124
  List<K>* keys() const;
125
126
  List<V>* values() const;
127
128
  void clear();
129
130
  // Helper used by find_kv_index(), set(), mylib::dict_erase() in
131
  // gc_mylib.h
132
  // Returns either:
133
  // - the slot for an existing key, or an empty slot for a new key
134
  // - kTooSmall if the table is full
135
  int hash_and_probe(K key) const;
136
137
  // Helper used by at(), get(), dict_contains()
138
  // Given a key, returns either:
139
  // - an index into keys_ and values_
140
  // - kNotFound
141
  int find_kv_index(K key) const;
142
143
401
  static constexpr ObjHeader obj_header() {
144
401
    return ObjHeader::ClassFixed(field_mask(), sizeof(Dict));
145
401
  }
_ZN4DictIP6BigStriE10obj_headerEv
Line
Count
Source
143
25
  static constexpr ObjHeader obj_header() {
144
25
    return ObjHeader::ClassFixed(field_mask(), sizeof(Dict));
145
25
  }
_ZN4DictIP6BigStrS1_E10obj_headerEv
Line
Count
Source
143
15
  static constexpr ObjHeader obj_header() {
144
15
    return ObjHeader::ClassFixed(field_mask(), sizeof(Dict));
145
15
  }
_ZN4DictIibE10obj_headerEv
Line
Count
Source
143
38
  static constexpr ObjHeader obj_header() {
144
38
    return ObjHeader::ClassFixed(field_mask(), sizeof(Dict));
145
38
  }
_ZN4DictIiiE10obj_headerEv
Line
Count
Source
143
290
  static constexpr ObjHeader obj_header() {
144
290
    return ObjHeader::ClassFixed(field_mask(), sizeof(Dict));
145
290
  }
_ZN4DictIP5PointP6BigStrE10obj_headerEv
Line
Count
Source
143
2
  static constexpr ObjHeader obj_header() {
144
2
    return ObjHeader::ClassFixed(field_mask(), sizeof(Dict));
145
2
  }
_ZN4DictIiP6BigStrE10obj_headerEv
Line
Count
Source
143
14
  static constexpr ObjHeader obj_header() {
144
14
    return ObjHeader::ClassFixed(field_mask(), sizeof(Dict));
145
14
  }
_ZN4DictIlP6BigStrE10obj_headerEv
Line
Count
Source
143
4
  static constexpr ObjHeader obj_header() {
144
4
    return ObjHeader::ClassFixed(field_mask(), sizeof(Dict));
145
4
  }
_ZN4DictIP6Tuple2IiiEiE10obj_headerEv
Line
Count
Source
143
2
  static constexpr ObjHeader obj_header() {
144
2
    return ObjHeader::ClassFixed(field_mask(), sizeof(Dict));
145
2
  }
_ZN4DictIP6Tuple2IP6BigStriEiE10obj_headerEv
Line
Count
Source
143
2
  static constexpr ObjHeader obj_header() {
144
2
    return ObjHeader::ClassFixed(field_mask(), sizeof(Dict));
145
2
  }
Unexecuted instantiation: _ZN4DictIiP6Tuple2IP4ListIPS1_IPS0_IiiEEEPS_IiiEEE10obj_headerEv
_ZN4DictIP6BigStrPN4args7_ActionEE10obj_headerEv
Line
Count
Source
143
6
  static constexpr ObjHeader obj_header() {
144
6
    return ObjHeader::ClassFixed(field_mask(), sizeof(Dict));
145
6
  }
_ZN4DictIP6BigStrPN10value_asdl7value_tEE10obj_headerEv
Line
Count
Source
143
3
  static constexpr ObjHeader obj_header() {
144
3
    return ObjHeader::ClassFixed(field_mask(), sizeof(Dict));
145
3
  }
146
147
  int len_;        // number of entries (keys and values, almost dense)
148
  int capacity_;   // number of k/v slots
149
  int index_len_;  // number of index slots
150
151
  // These 3 slabs are resized at the same time.
152
  Slab<int>* index_;  // kEmptyEntry, kDeletedEntry, or a valid index into
153
                      // keys_ and values_
154
  Slab<K>* keys_;     // Dict<K, int>
155
  Slab<V>* values_;   // Dict<int, V>
156
157
  // A dict has 3 pointers the GC needs to follow.
158
403
  static constexpr uint32_t field_mask() {
159
403
    return maskbit(offsetof(Dict, index_)) | maskbit(offsetof(Dict, keys_)) |
160
403
           maskbit(offsetof(Dict, values_));
161
403
  }
_ZN4DictIP6BigStriE10field_maskEv
Line
Count
Source
158
25
  static constexpr uint32_t field_mask() {
159
25
    return maskbit(offsetof(Dict, index_)) | maskbit(offsetof(Dict, keys_)) |
160
25
           maskbit(offsetof(Dict, values_));
161
25
  }
_ZN4DictIP6BigStrS1_E10field_maskEv
Line
Count
Source
158
15
  static constexpr uint32_t field_mask() {
159
15
    return maskbit(offsetof(Dict, index_)) | maskbit(offsetof(Dict, keys_)) |
160
15
           maskbit(offsetof(Dict, values_));
161
15
  }
_ZN4DictIibE10field_maskEv
Line
Count
Source
158
38
  static constexpr uint32_t field_mask() {
159
38
    return maskbit(offsetof(Dict, index_)) | maskbit(offsetof(Dict, keys_)) |
160
38
           maskbit(offsetof(Dict, values_));
161
38
  }
_ZN4DictIiiE10field_maskEv
Line
Count
Source
158
292
  static constexpr uint32_t field_mask() {
159
292
    return maskbit(offsetof(Dict, index_)) | maskbit(offsetof(Dict, keys_)) |
160
292
           maskbit(offsetof(Dict, values_));
161
292
  }
_ZN4DictIP5PointP6BigStrE10field_maskEv
Line
Count
Source
158
2
  static constexpr uint32_t field_mask() {
159
2
    return maskbit(offsetof(Dict, index_)) | maskbit(offsetof(Dict, keys_)) |
160
2
           maskbit(offsetof(Dict, values_));
161
2
  }
_ZN4DictIiP6BigStrE10field_maskEv
Line
Count
Source
158
14
  static constexpr uint32_t field_mask() {
159
14
    return maskbit(offsetof(Dict, index_)) | maskbit(offsetof(Dict, keys_)) |
160
14
           maskbit(offsetof(Dict, values_));
161
14
  }
_ZN4DictIlP6BigStrE10field_maskEv
Line
Count
Source
158
4
  static constexpr uint32_t field_mask() {
159
4
    return maskbit(offsetof(Dict, index_)) | maskbit(offsetof(Dict, keys_)) |
160
4
           maskbit(offsetof(Dict, values_));
161
4
  }
_ZN4DictIP6Tuple2IiiEiE10field_maskEv
Line
Count
Source
158
2
  static constexpr uint32_t field_mask() {
159
2
    return maskbit(offsetof(Dict, index_)) | maskbit(offsetof(Dict, keys_)) |
160
2
           maskbit(offsetof(Dict, values_));
161
2
  }
_ZN4DictIP6Tuple2IP6BigStriEiE10field_maskEv
Line
Count
Source
158
2
  static constexpr uint32_t field_mask() {
159
2
    return maskbit(offsetof(Dict, index_)) | maskbit(offsetof(Dict, keys_)) |
160
2
           maskbit(offsetof(Dict, values_));
161
2
  }
Unexecuted instantiation: _ZN4DictIiP6Tuple2IP4ListIPS1_IPS0_IiiEEEPS_IiiEEE10field_maskEv
_ZN4DictIP6BigStrPN4args7_ActionEE10field_maskEv
Line
Count
Source
158
6
  static constexpr uint32_t field_mask() {
159
6
    return maskbit(offsetof(Dict, index_)) | maskbit(offsetof(Dict, keys_)) |
160
6
           maskbit(offsetof(Dict, values_));
161
6
  }
_ZN4DictIP6BigStrPN10value_asdl7value_tEE10field_maskEv
Line
Count
Source
158
3
  static constexpr uint32_t field_mask() {
159
3
    return maskbit(offsetof(Dict, index_)) | maskbit(offsetof(Dict, keys_)) |
160
3
           maskbit(offsetof(Dict, values_));
161
3
  }
162
163
  DISALLOW_COPY_AND_ASSIGN(Dict);
164
165
  // kItemSize is max of K and V size.  That is, on 64-bit machines, the RARE
166
  // Dict<int, int> is smaller than other dicts
167
  static constexpr int kItemSize = sizeof(K) > sizeof(V) ? sizeof(K)
168
                                                         : sizeof(V);
169
170
  // Matches mark_sweep_heap.h
171
  static constexpr int kPoolBytes2 = 48 - sizeof(ObjHeader);
172
  static_assert(kPoolBytes2 % kItemSize == 0,
173
                "An integral number of items should fit in second pool");
174
  static constexpr int kNumItems2 = kPoolBytes2 / kItemSize;
175
176
  static const int kHeaderFudge = sizeof(ObjHeader) / kItemSize;
177
  static_assert(sizeof(ObjHeader) % kItemSize == 0,
178
                "Slab header size should be multiple of key size");
179
180
#if 0
181
  static constexpr int kMinBytes2 = 128 - sizeof(ObjHeader);
182
  static_assert(kMinBytes2 % kItemSize == 0,
183
                "An integral number of items should fit");
184
  static constexpr int kMinItems2 = kMinBytes2 / kItemSize;
185
#endif
186
187
190
  int HowManyPairs(int num_desired) {
188
    // See gc_list.h for comments on nearly identical logic
189
190
190
    if (num_desired <= kNumItems2) {  // use full cell in pool 2
191
92
      return kNumItems2;
192
92
    }
193
#if 0
194
    if (num_desired <= kMinItems2) {  // 48 -> 128, not 48 -> 64
195
      return kMinItems2;
196
    }
197
#endif
198
98
    return RoundUp(num_desired + kHeaderFudge) - kHeaderFudge;
199
190
  }
_ZN4DictIP6BigStriE12HowManyPairsEi
Line
Count
Source
187
36
  int HowManyPairs(int num_desired) {
188
    // See gc_list.h for comments on nearly identical logic
189
190
36
    if (num_desired <= kNumItems2) {  // use full cell in pool 2
191
22
      return kNumItems2;
192
22
    }
193
#if 0
194
    if (num_desired <= kMinItems2) {  // 48 -> 128, not 48 -> 64
195
      return kMinItems2;
196
    }
197
#endif
198
14
    return RoundUp(num_desired + kHeaderFudge) - kHeaderFudge;
199
36
  }
_ZN4DictIP6BigStrS1_E12HowManyPairsEi
Line
Count
Source
187
10
  int HowManyPairs(int num_desired) {
188
    // See gc_list.h for comments on nearly identical logic
189
190
10
    if (num_desired <= kNumItems2) {  // use full cell in pool 2
191
8
      return kNumItems2;
192
8
    }
193
#if 0
194
    if (num_desired <= kMinItems2) {  // 48 -> 128, not 48 -> 64
195
      return kMinItems2;
196
    }
197
#endif
198
2
    return RoundUp(num_desired + kHeaderFudge) - kHeaderFudge;
199
10
  }
_ZN4DictIibE12HowManyPairsEi
Line
Count
Source
187
19
  int HowManyPairs(int num_desired) {
188
    // See gc_list.h for comments on nearly identical logic
189
190
19
    if (num_desired <= kNumItems2) {  // use full cell in pool 2
191
19
      return kNumItems2;
192
19
    }
193
#if 0
194
    if (num_desired <= kMinItems2) {  // 48 -> 128, not 48 -> 64
195
      return kMinItems2;
196
    }
197
#endif
198
0
    return RoundUp(num_desired + kHeaderFudge) - kHeaderFudge;
199
19
  }
_ZN4DictIP5PointP6BigStrE12HowManyPairsEi
Line
Count
Source
187
10
  int HowManyPairs(int num_desired) {
188
    // See gc_list.h for comments on nearly identical logic
189
190
10
    if (num_desired <= kNumItems2) {  // use full cell in pool 2
191
2
      return kNumItems2;
192
2
    }
193
#if 0
194
    if (num_desired <= kMinItems2) {  // 48 -> 128, not 48 -> 64
195
      return kMinItems2;
196
    }
197
#endif
198
8
    return RoundUp(num_desired + kHeaderFudge) - kHeaderFudge;
199
10
  }
_ZN4DictIiP6BigStrE12HowManyPairsEi
Line
Count
Source
187
22
  int HowManyPairs(int num_desired) {
188
    // See gc_list.h for comments on nearly identical logic
189
190
22
    if (num_desired <= kNumItems2) {  // use full cell in pool 2
191
12
      return kNumItems2;
192
12
    }
193
#if 0
194
    if (num_desired <= kMinItems2) {  // 48 -> 128, not 48 -> 64
195
      return kMinItems2;
196
    }
197
#endif
198
10
    return RoundUp(num_desired + kHeaderFudge) - kHeaderFudge;
199
22
  }
_ZN4DictIlP6BigStrE12HowManyPairsEi
Line
Count
Source
187
40
  int HowManyPairs(int num_desired) {
188
    // See gc_list.h for comments on nearly identical logic
189
190
40
    if (num_desired <= kNumItems2) {  // use full cell in pool 2
191
4
      return kNumItems2;
192
4
    }
193
#if 0
194
    if (num_desired <= kMinItems2) {  // 48 -> 128, not 48 -> 64
195
      return kMinItems2;
196
    }
197
#endif
198
36
    return RoundUp(num_desired + kHeaderFudge) - kHeaderFudge;
199
40
  }
_ZN4DictIiiE12HowManyPairsEi
Line
Count
Source
187
34
  int HowManyPairs(int num_desired) {
188
    // See gc_list.h for comments on nearly identical logic
189
190
34
    if (num_desired <= kNumItems2) {  // use full cell in pool 2
191
16
      return kNumItems2;
192
16
    }
193
#if 0
194
    if (num_desired <= kMinItems2) {  // 48 -> 128, not 48 -> 64
195
      return kMinItems2;
196
    }
197
#endif
198
18
    return RoundUp(num_desired + kHeaderFudge) - kHeaderFudge;
199
34
  }
_ZN4DictIP6Tuple2IiiEiE12HowManyPairsEi
Line
Count
Source
187
2
  int HowManyPairs(int num_desired) {
188
    // See gc_list.h for comments on nearly identical logic
189
190
2
    if (num_desired <= kNumItems2) {  // use full cell in pool 2
191
2
      return kNumItems2;
192
2
    }
193
#if 0
194
    if (num_desired <= kMinItems2) {  // 48 -> 128, not 48 -> 64
195
      return kMinItems2;
196
    }
197
#endif
198
0
    return RoundUp(num_desired + kHeaderFudge) - kHeaderFudge;
199
2
  }
_ZN4DictIP6Tuple2IP6BigStriEiE12HowManyPairsEi
Line
Count
Source
187
2
  int HowManyPairs(int num_desired) {
188
    // See gc_list.h for comments on nearly identical logic
189
190
2
    if (num_desired <= kNumItems2) {  // use full cell in pool 2
191
2
      return kNumItems2;
192
2
    }
193
#if 0
194
    if (num_desired <= kMinItems2) {  // 48 -> 128, not 48 -> 64
195
      return kMinItems2;
196
    }
197
#endif
198
0
    return RoundUp(num_desired + kHeaderFudge) - kHeaderFudge;
199
2
  }
Unexecuted instantiation: _ZN4DictIiP6Tuple2IP4ListIPS1_IPS0_IiiEEEPS_IiiEEE12HowManyPairsEi
_ZN4DictIP6BigStrPN10value_asdl7value_tEE12HowManyPairsEi
Line
Count
Source
187
8
  int HowManyPairs(int num_desired) {
188
    // See gc_list.h for comments on nearly identical logic
189
190
8
    if (num_desired <= kNumItems2) {  // use full cell in pool 2
191
3
      return kNumItems2;
192
3
    }
193
#if 0
194
    if (num_desired <= kMinItems2) {  // 48 -> 128, not 48 -> 64
195
      return kMinItems2;
196
    }
197
#endif
198
5
    return RoundUp(num_desired + kHeaderFudge) - kHeaderFudge;
199
8
  }
_ZN4DictIP6BigStrPN4args7_ActionEE12HowManyPairsEi
Line
Count
Source
187
7
  int HowManyPairs(int num_desired) {
188
    // See gc_list.h for comments on nearly identical logic
189
190
7
    if (num_desired <= kNumItems2) {  // use full cell in pool 2
191
2
      return kNumItems2;
192
2
    }
193
#if 0
194
    if (num_desired <= kMinItems2) {  // 48 -> 128, not 48 -> 64
195
      return kMinItems2;
196
    }
197
#endif
198
5
    return RoundUp(num_desired + kHeaderFudge) - kHeaderFudge;
199
7
  }
200
};
201
202
template <typename K, typename V>
203
76
inline bool dict_contains(const Dict<K, V>* haystack, K needle) {
204
76
  return haystack->find_kv_index(needle) != kNotFound;
205
76
}
_Z13dict_containsIP6BigStriEbPK4DictIT_T0_ES3_
Line
Count
Source
203
5
inline bool dict_contains(const Dict<K, V>* haystack, K needle) {
204
5
  return haystack->find_kv_index(needle) != kNotFound;
205
5
}
_Z13dict_containsIibEbPK4DictIT_T0_ES1_
Line
Count
Source
203
57
inline bool dict_contains(const Dict<K, V>* haystack, K needle) {
204
57
  return haystack->find_kv_index(needle) != kNotFound;
205
57
}
_Z13dict_containsIiP6BigStrEbPK4DictIT_T0_ES3_
Line
Count
Source
203
4
inline bool dict_contains(const Dict<K, V>* haystack, K needle) {
204
4
  return haystack->find_kv_index(needle) != kNotFound;
205
4
}
_Z13dict_containsIiiEbPK4DictIT_T0_ES1_
Line
Count
Source
203
4
inline bool dict_contains(const Dict<K, V>* haystack, K needle) {
204
4
  return haystack->find_kv_index(needle) != kNotFound;
205
4
}
_Z13dict_containsIP6BigStrS1_EbPK4DictIT_T0_ES3_
Line
Count
Source
203
6
inline bool dict_contains(const Dict<K, V>* haystack, K needle) {
204
6
  return haystack->find_kv_index(needle) != kNotFound;
205
6
}
Unexecuted instantiation: _Z13dict_containsIP6BigStrPN4args7_ActionEEbPK4DictIT_T0_ES6_
206
207
template <typename K, typename V>
208
192
void Dict<K, V>::reserve(int num_desired) {
209
192
  if (capacity_ >= num_desired) {
210
2
    return;  // Don't do anything if there's already enough space.
211
2
  }
212
213
190
  int old_len = len_;
214
190
  Slab<K>* old_k = keys_;
215
190
  Slab<V>* old_v = values_;
216
217
  // Calculate the number of keys and values we should have
218
190
  capacity_ = HowManyPairs(num_desired);
219
220
  // 1) Ensure index len a power of 2, to avoid expensive modulus % operation
221
  // 2) Introduce hash table load factor.   Use capacity_+1 to simulate ceil()
222
  // div, not floor() div.
223
190
  index_len_ = RoundUp((capacity_ + 1) * 5 / 4);
224
190
  DCHECK(index_len_ > capacity_);
225
226
0
  index_ = NewSlab<int>(index_len_);
227
267k
  for (int i = 0; i < index_len_; ++i) {
228
267k
    index_->items_[i] = kEmptyEntry;
229
267k
  }
230
231
  // These are DENSE, while index_ is sparse.
232
190
  keys_ = NewSlab<K>(capacity_);
233
190
  values_ = NewSlab<V>(capacity_);
234
235
190
  if (old_k != nullptr) {  // rehash if there were any entries
236
    // log("REHASH num_desired %d", num_desired);
237
98
    len_ = 0;
238
66.6k
    for (int i = 0; i < old_len; ++i) {
239
66.5k
      set(old_k->items_[i], old_v->items_[i]);
240
66.5k
    }
241
98
  }
242
190
}
_ZN4DictIP6BigStriE7reserveEi
Line
Count
Source
208
36
void Dict<K, V>::reserve(int num_desired) {
209
36
  if (capacity_ >= num_desired) {
210
0
    return;  // Don't do anything if there's already enough space.
211
0
  }
212
213
36
  int old_len = len_;
214
36
  Slab<K>* old_k = keys_;
215
36
  Slab<V>* old_v = values_;
216
217
  // Calculate the number of keys and values we should have
218
36
  capacity_ = HowManyPairs(num_desired);
219
220
  // 1) Ensure index len a power of 2, to avoid expensive modulus % operation
221
  // 2) Introduce hash table load factor.   Use capacity_+1 to simulate ceil()
222
  // div, not floor() div.
223
36
  index_len_ = RoundUp((capacity_ + 1) * 5 / 4);
224
36
  DCHECK(index_len_ > capacity_);
225
226
0
  index_ = NewSlab<int>(index_len_);
227
916
  for (int i = 0; i < index_len_; ++i) {
228
880
    index_->items_[i] = kEmptyEntry;
229
880
  }
230
231
  // These are DENSE, while index_ is sparse.
232
36
  keys_ = NewSlab<K>(capacity_);
233
36
  values_ = NewSlab<V>(capacity_);
234
235
36
  if (old_k != nullptr) {  // rehash if there were any entries
236
    // log("REHASH num_desired %d", num_desired);
237
14
    len_ = 0;
238
184
    for (int i = 0; i < old_len; ++i) {
239
170
      set(old_k->items_[i], old_v->items_[i]);
240
170
    }
241
14
  }
242
36
}
_ZN4DictIP6BigStrS1_E7reserveEi
Line
Count
Source
208
10
void Dict<K, V>::reserve(int num_desired) {
209
10
  if (capacity_ >= num_desired) {
210
0
    return;  // Don't do anything if there's already enough space.
211
0
  }
212
213
10
  int old_len = len_;
214
10
  Slab<K>* old_k = keys_;
215
10
  Slab<V>* old_v = values_;
216
217
  // Calculate the number of keys and values we should have
218
10
  capacity_ = HowManyPairs(num_desired);
219
220
  // 1) Ensure index len a power of 2, to avoid expensive modulus % operation
221
  // 2) Introduce hash table load factor.   Use capacity_+1 to simulate ceil()
222
  // div, not floor() div.
223
10
  index_len_ = RoundUp((capacity_ + 1) * 5 / 4);
224
10
  DCHECK(index_len_ > capacity_);
225
226
0
  index_ = NewSlab<int>(index_len_);
227
122
  for (int i = 0; i < index_len_; ++i) {
228
112
    index_->items_[i] = kEmptyEntry;
229
112
  }
230
231
  // These are DENSE, while index_ is sparse.
232
10
  keys_ = NewSlab<K>(capacity_);
233
10
  values_ = NewSlab<V>(capacity_);
234
235
10
  if (old_k != nullptr) {  // rehash if there were any entries
236
    // log("REHASH num_desired %d", num_desired);
237
2
    len_ = 0;
238
14
    for (int i = 0; i < old_len; ++i) {
239
12
      set(old_k->items_[i], old_v->items_[i]);
240
12
    }
241
2
  }
242
10
}
_ZN4DictIibE7reserveEi
Line
Count
Source
208
19
void Dict<K, V>::reserve(int num_desired) {
209
19
  if (capacity_ >= num_desired) {
210
0
    return;  // Don't do anything if there's already enough space.
211
0
  }
212
213
19
  int old_len = len_;
214
19
  Slab<K>* old_k = keys_;
215
19
  Slab<V>* old_v = values_;
216
217
  // Calculate the number of keys and values we should have
218
19
  capacity_ = HowManyPairs(num_desired);
219
220
  // 1) Ensure index len a power of 2, to avoid expensive modulus % operation
221
  // 2) Introduce hash table load factor.   Use capacity_+1 to simulate ceil()
222
  // div, not floor() div.
223
19
  index_len_ = RoundUp((capacity_ + 1) * 5 / 4);
224
19
  DCHECK(index_len_ > capacity_);
225
226
0
  index_ = NewSlab<int>(index_len_);
227
323
  for (int i = 0; i < index_len_; ++i) {
228
304
    index_->items_[i] = kEmptyEntry;
229
304
  }
230
231
  // These are DENSE, while index_ is sparse.
232
19
  keys_ = NewSlab<K>(capacity_);
233
19
  values_ = NewSlab<V>(capacity_);
234
235
19
  if (old_k != nullptr) {  // rehash if there were any entries
236
    // log("REHASH num_desired %d", num_desired);
237
0
    len_ = 0;
238
0
    for (int i = 0; i < old_len; ++i) {
239
0
      set(old_k->items_[i], old_v->items_[i]);
240
0
    }
241
0
  }
242
19
}
_ZN4DictIP5PointP6BigStrE7reserveEi
Line
Count
Source
208
10
void Dict<K, V>::reserve(int num_desired) {
209
10
  if (capacity_ >= num_desired) {
210
0
    return;  // Don't do anything if there's already enough space.
211
0
  }
212
213
10
  int old_len = len_;
214
10
  Slab<K>* old_k = keys_;
215
10
  Slab<V>* old_v = values_;
216
217
  // Calculate the number of keys and values we should have
218
10
  capacity_ = HowManyPairs(num_desired);
219
220
  // 1) Ensure index len a power of 2, to avoid expensive modulus % operation
221
  // 2) Introduce hash table load factor.   Use capacity_+1 to simulate ceil()
222
  // div, not floor() div.
223
10
  index_len_ = RoundUp((capacity_ + 1) * 5 / 4);
224
10
  DCHECK(index_len_ > capacity_);
225
226
0
  index_ = NewSlab<int>(index_len_);
227
506
  for (int i = 0; i < index_len_; ++i) {
228
496
    index_->items_[i] = kEmptyEntry;
229
496
  }
230
231
  // These are DENSE, while index_ is sparse.
232
10
  keys_ = NewSlab<K>(capacity_);
233
10
  values_ = NewSlab<V>(capacity_);
234
235
10
  if (old_k != nullptr) {  // rehash if there were any entries
236
    // log("REHASH num_desired %d", num_desired);
237
8
    len_ = 0;
238
124
    for (int i = 0; i < old_len; ++i) {
239
116
      set(old_k->items_[i], old_v->items_[i]);
240
116
    }
241
8
  }
242
10
}
_ZN4DictIiP6BigStrE7reserveEi
Line
Count
Source
208
22
void Dict<K, V>::reserve(int num_desired) {
209
22
  if (capacity_ >= num_desired) {
210
0
    return;  // Don't do anything if there's already enough space.
211
0
  }
212
213
22
  int old_len = len_;
214
22
  Slab<K>* old_k = keys_;
215
22
  Slab<V>* old_v = values_;
216
217
  // Calculate the number of keys and values we should have
218
22
  capacity_ = HowManyPairs(num_desired);
219
220
  // 1) Ensure index len a power of 2, to avoid expensive modulus % operation
221
  // 2) Introduce hash table load factor.   Use capacity_+1 to simulate ceil()
222
  // div, not floor() div.
223
22
  index_len_ = RoundUp((capacity_ + 1) * 5 / 4);
224
22
  DCHECK(index_len_ > capacity_);
225
226
0
  index_ = NewSlab<int>(index_len_);
227
630
  for (int i = 0; i < index_len_; ++i) {
228
608
    index_->items_[i] = kEmptyEntry;
229
608
  }
230
231
  // These are DENSE, while index_ is sparse.
232
22
  keys_ = NewSlab<K>(capacity_);
233
22
  values_ = NewSlab<V>(capacity_);
234
235
22
  if (old_k != nullptr) {  // rehash if there were any entries
236
    // log("REHASH num_desired %d", num_desired);
237
10
    len_ = 0;
238
136
    for (int i = 0; i < old_len; ++i) {
239
126
      set(old_k->items_[i], old_v->items_[i]);
240
126
    }
241
10
  }
242
22
}
_ZN4DictIlP6BigStrE7reserveEi
Line
Count
Source
208
40
void Dict<K, V>::reserve(int num_desired) {
209
40
  if (capacity_ >= num_desired) {
210
0
    return;  // Don't do anything if there's already enough space.
211
0
  }
212
213
40
  int old_len = len_;
214
40
  Slab<K>* old_k = keys_;
215
40
  Slab<V>* old_v = values_;
216
217
  // Calculate the number of keys and values we should have
218
40
  capacity_ = HowManyPairs(num_desired);
219
220
  // 1) Ensure index len a power of 2, to avoid expensive modulus % operation
221
  // 2) Introduce hash table load factor.   Use capacity_+1 to simulate ceil()
222
  // div, not floor() div.
223
40
  index_len_ = RoundUp((capacity_ + 1) * 5 / 4);
224
40
  DCHECK(index_len_ > capacity_);
225
226
0
  index_ = NewSlab<int>(index_len_);
227
263k
  for (int i = 0; i < index_len_; ++i) {
228
263k
    index_->items_[i] = kEmptyEntry;
229
263k
  }
230
231
  // These are DENSE, while index_ is sparse.
232
40
  keys_ = NewSlab<K>(capacity_);
233
40
  values_ = NewSlab<V>(capacity_);
234
235
40
  if (old_k != nullptr) {  // rehash if there were any entries
236
    // log("REHASH num_desired %d", num_desired);
237
36
    len_ = 0;
238
65.7k
    for (int i = 0; i < old_len; ++i) {
239
65.7k
      set(old_k->items_[i], old_v->items_[i]);
240
65.7k
    }
241
36
  }
242
40
}
_ZN4DictIiiE7reserveEi
Line
Count
Source
208
36
void Dict<K, V>::reserve(int num_desired) {
209
36
  if (capacity_ >= num_desired) {
210
2
    return;  // Don't do anything if there's already enough space.
211
2
  }
212
213
34
  int old_len = len_;
214
34
  Slab<K>* old_k = keys_;
215
34
  Slab<V>* old_v = values_;
216
217
  // Calculate the number of keys and values we should have
218
34
  capacity_ = HowManyPairs(num_desired);
219
220
  // 1) Ensure index len a power of 2, to avoid expensive modulus % operation
221
  // 2) Introduce hash table load factor.   Use capacity_+1 to simulate ceil()
222
  // div, not floor() div.
223
34
  index_len_ = RoundUp((capacity_ + 1) * 5 / 4);
224
34
  DCHECK(index_len_ > capacity_);
225
226
0
  index_ = NewSlab<int>(index_len_);
227
1.69k
  for (int i = 0; i < index_len_; ++i) {
228
1.66k
    index_->items_[i] = kEmptyEntry;
229
1.66k
  }
230
231
  // These are DENSE, while index_ is sparse.
232
34
  keys_ = NewSlab<K>(capacity_);
233
34
  values_ = NewSlab<V>(capacity_);
234
235
34
  if (old_k != nullptr) {  // rehash if there were any entries
236
    // log("REHASH num_desired %d", num_desired);
237
18
    len_ = 0;
238
308
    for (int i = 0; i < old_len; ++i) {
239
290
      set(old_k->items_[i], old_v->items_[i]);
240
290
    }
241
18
  }
242
34
}
_ZN4DictIP6Tuple2IiiEiE7reserveEi
Line
Count
Source
208
2
void Dict<K, V>::reserve(int num_desired) {
209
2
  if (capacity_ >= num_desired) {
210
0
    return;  // Don't do anything if there's already enough space.
211
0
  }
212
213
2
  int old_len = len_;
214
2
  Slab<K>* old_k = keys_;
215
2
  Slab<V>* old_v = values_;
216
217
  // Calculate the number of keys and values we should have
218
2
  capacity_ = HowManyPairs(num_desired);
219
220
  // 1) Ensure index len a power of 2, to avoid expensive modulus % operation
221
  // 2) Introduce hash table load factor.   Use capacity_+1 to simulate ceil()
222
  // div, not floor() div.
223
2
  index_len_ = RoundUp((capacity_ + 1) * 5 / 4);
224
2
  DCHECK(index_len_ > capacity_);
225
226
0
  index_ = NewSlab<int>(index_len_);
227
18
  for (int i = 0; i < index_len_; ++i) {
228
16
    index_->items_[i] = kEmptyEntry;
229
16
  }
230
231
  // These are DENSE, while index_ is sparse.
232
2
  keys_ = NewSlab<K>(capacity_);
233
2
  values_ = NewSlab<V>(capacity_);
234
235
2
  if (old_k != nullptr) {  // rehash if there were any entries
236
    // log("REHASH num_desired %d", num_desired);
237
0
    len_ = 0;
238
0
    for (int i = 0; i < old_len; ++i) {
239
0
      set(old_k->items_[i], old_v->items_[i]);
240
0
    }
241
0
  }
242
2
}
_ZN4DictIP6Tuple2IP6BigStriEiE7reserveEi
Line
Count
Source
208
2
void Dict<K, V>::reserve(int num_desired) {
209
2
  if (capacity_ >= num_desired) {
210
0
    return;  // Don't do anything if there's already enough space.
211
0
  }
212
213
2
  int old_len = len_;
214
2
  Slab<K>* old_k = keys_;
215
2
  Slab<V>* old_v = values_;
216
217
  // Calculate the number of keys and values we should have
218
2
  capacity_ = HowManyPairs(num_desired);
219
220
  // 1) Ensure index len a power of 2, to avoid expensive modulus % operation
221
  // 2) Introduce hash table load factor.   Use capacity_+1 to simulate ceil()
222
  // div, not floor() div.
223
2
  index_len_ = RoundUp((capacity_ + 1) * 5 / 4);
224
2
  DCHECK(index_len_ > capacity_);
225
226
0
  index_ = NewSlab<int>(index_len_);
227
18
  for (int i = 0; i < index_len_; ++i) {
228
16
    index_->items_[i] = kEmptyEntry;
229
16
  }
230
231
  // These are DENSE, while index_ is sparse.
232
2
  keys_ = NewSlab<K>(capacity_);
233
2
  values_ = NewSlab<V>(capacity_);
234
235
2
  if (old_k != nullptr) {  // rehash if there were any entries
236
    // log("REHASH num_desired %d", num_desired);
237
0
    len_ = 0;
238
0
    for (int i = 0; i < old_len; ++i) {
239
0
      set(old_k->items_[i], old_v->items_[i]);
240
0
    }
241
0
  }
242
2
}
Unexecuted instantiation: _ZN4DictIiP6Tuple2IP4ListIPS1_IPS0_IiiEEEPS_IiiEEE7reserveEi
_ZN4DictIP6BigStrPN10value_asdl7value_tEE7reserveEi
Line
Count
Source
208
8
void Dict<K, V>::reserve(int num_desired) {
209
8
  if (capacity_ >= num_desired) {
210
0
    return;  // Don't do anything if there's already enough space.
211
0
  }
212
213
8
  int old_len = len_;
214
8
  Slab<K>* old_k = keys_;
215
8
  Slab<V>* old_v = values_;
216
217
  // Calculate the number of keys and values we should have
218
8
  capacity_ = HowManyPairs(num_desired);
219
220
  // 1) Ensure index len a power of 2, to avoid expensive modulus % operation
221
  // 2) Introduce hash table load factor.   Use capacity_+1 to simulate ceil()
222
  // div, not floor() div.
223
8
  index_len_ = RoundUp((capacity_ + 1) * 5 / 4);
224
8
  DCHECK(index_len_ > capacity_);
225
226
0
  index_ = NewSlab<int>(index_len_);
227
192
  for (int i = 0; i < index_len_; ++i) {
228
184
    index_->items_[i] = kEmptyEntry;
229
184
  }
230
231
  // These are DENSE, while index_ is sparse.
232
8
  keys_ = NewSlab<K>(capacity_);
233
8
  values_ = NewSlab<V>(capacity_);
234
235
8
  if (old_k != nullptr) {  // rehash if there were any entries
236
    // log("REHASH num_desired %d", num_desired);
237
5
    len_ = 0;
238
44
    for (int i = 0; i < old_len; ++i) {
239
39
      set(old_k->items_[i], old_v->items_[i]);
240
39
    }
241
5
  }
242
8
}
_ZN4DictIP6BigStrPN4args7_ActionEE7reserveEi
Line
Count
Source
208
7
void Dict<K, V>::reserve(int num_desired) {
209
7
  if (capacity_ >= num_desired) {
210
0
    return;  // Don't do anything if there's already enough space.
211
0
  }
212
213
7
  int old_len = len_;
214
7
  Slab<K>* old_k = keys_;
215
7
  Slab<V>* old_v = values_;
216
217
  // Calculate the number of keys and values we should have
218
7
  capacity_ = HowManyPairs(num_desired);
219
220
  // 1) Ensure index len a power of 2, to avoid expensive modulus % operation
221
  // 2) Introduce hash table load factor.   Use capacity_+1 to simulate ceil()
222
  // div, not floor() div.
223
7
  index_len_ = RoundUp((capacity_ + 1) * 5 / 4);
224
7
  DCHECK(index_len_ > capacity_);
225
226
0
  index_ = NewSlab<int>(index_len_);
227
183
  for (int i = 0; i < index_len_; ++i) {
228
176
    index_->items_[i] = kEmptyEntry;
229
176
  }
230
231
  // These are DENSE, while index_ is sparse.
232
7
  keys_ = NewSlab<K>(capacity_);
233
7
  values_ = NewSlab<V>(capacity_);
234
235
7
  if (old_k != nullptr) {  // rehash if there were any entries
236
    // log("REHASH num_desired %d", num_desired);
237
5
    len_ = 0;
238
44
    for (int i = 0; i < old_len; ++i) {
239
39
      set(old_k->items_[i], old_v->items_[i]);
240
39
    }
241
5
  }
242
7
}
243
244
template <typename K, typename V>
245
16.2k
V Dict<K, V>::at(K key) const {
246
16.2k
  int kv_index = find_kv_index(key);
247
16.2k
  if (kv_index == kNotFound) {
248
0
    throw Alloc<KeyError>();
249
16.2k
  } else {
250
16.2k
    return values_->items_[kv_index];
251
16.2k
  }
252
16.2k
}
_ZNK4DictIP6BigStriE2atES1_
Line
Count
Source
245
19
V Dict<K, V>::at(K key) const {
246
19
  int kv_index = find_kv_index(key);
247
19
  if (kv_index == kNotFound) {
248
0
    throw Alloc<KeyError>();
249
19
  } else {
250
19
    return values_->items_[kv_index];
251
19
  }
252
19
}
_ZNK4DictIiP6BigStrE2atEi
Line
Count
Source
245
7
V Dict<K, V>::at(K key) const {
246
7
  int kv_index = find_kv_index(key);
247
7
  if (kv_index == kNotFound) {
248
0
    throw Alloc<KeyError>();
249
7
  } else {
250
7
    return values_->items_[kv_index];
251
7
  }
252
7
}
_ZNK4DictIP6BigStrS1_E2atES1_
Line
Count
Source
245
8
V Dict<K, V>::at(K key) const {
246
8
  int kv_index = find_kv_index(key);
247
8
  if (kv_index == kNotFound) {
248
0
    throw Alloc<KeyError>();
249
8
  } else {
250
8
    return values_->items_[kv_index];
251
8
  }
252
8
}
_ZNK4DictIiiE2atEi
Line
Count
Source
245
16.1k
V Dict<K, V>::at(K key) const {
246
16.1k
  int kv_index = find_kv_index(key);
247
16.1k
  if (kv_index == kNotFound) {
248
0
    throw Alloc<KeyError>();
249
16.1k
  } else {
250
16.1k
    return values_->items_[kv_index];
251
16.1k
  }
252
16.1k
}
_ZNK4DictIP6Tuple2IiiEiE2atES2_
Line
Count
Source
245
4
V Dict<K, V>::at(K key) const {
246
4
  int kv_index = find_kv_index(key);
247
4
  if (kv_index == kNotFound) {
248
0
    throw Alloc<KeyError>();
249
4
  } else {
250
4
    return values_->items_[kv_index];
251
4
  }
252
4
}
_ZNK4DictIP6Tuple2IP6BigStriEiE2atES4_
Line
Count
Source
245
4
V Dict<K, V>::at(K key) const {
246
4
  int kv_index = find_kv_index(key);
247
4
  if (kv_index == kNotFound) {
248
0
    throw Alloc<KeyError>();
249
4
  } else {
250
4
    return values_->items_[kv_index];
251
4
  }
252
4
}
Unexecuted instantiation: _ZNK4DictIP6BigStrPN10value_asdl7value_tEE2atES1_
Unexecuted instantiation: _ZNK4DictIP6BigStrPN4args7_ActionEE2atES1_
253
254
template <typename K, typename V>
255
8
V Dict<K, V>::get(K key) const {
256
8
  int kv_index = find_kv_index(key);
257
8
  if (kv_index == kNotFound) {
258
5
    return nullptr;
259
5
  } else {
260
3
    return values_->items_[kv_index];
261
3
  }
262
8
}
_ZNK4DictIP6BigStrS1_E3getES1_
Line
Count
Source
255
4
V Dict<K, V>::get(K key) const {
256
4
  int kv_index = find_kv_index(key);
257
4
  if (kv_index == kNotFound) {
258
3
    return nullptr;
259
3
  } else {
260
1
    return values_->items_[kv_index];
261
1
  }
262
4
}
_ZNK4DictIiP6BigStrE3getEi
Line
Count
Source
255
4
V Dict<K, V>::get(K key) const {
256
4
  int kv_index = find_kv_index(key);
257
4
  if (kv_index == kNotFound) {
258
2
    return nullptr;
259
2
  } else {
260
2
    return values_->items_[kv_index];
261
2
  }
262
4
}
Unexecuted instantiation: _ZNK4DictIP6BigStrPN4args7_ActionEE3getES1_
263
264
template <typename K, typename V>
265
2
V Dict<K, V>::get(K key, V default_val) const {
266
2
  int kv_index = find_kv_index(key);
267
2
  if (kv_index == kNotFound) {
268
2
    return default_val;
269
2
  } else {
270
0
    return values_->items_[kv_index];
271
0
  }
272
2
}
_ZNK4DictIP6BigStrS1_E3getES1_S1_
Line
Count
Source
265
2
V Dict<K, V>::get(K key, V default_val) const {
266
2
  int kv_index = find_kv_index(key);
267
2
  if (kv_index == kNotFound) {
268
2
    return default_val;
269
2
  } else {
270
0
    return values_->items_[kv_index];
271
0
  }
272
2
}
Unexecuted instantiation: _ZNK4DictIiP6BigStrE3getEiS1_
Unexecuted instantiation: _ZNK4DictIP6BigStriE3getES1_i
273
274
template <typename K, typename V>
275
14
List<K>* Dict<K, V>::keys() const {
276
14
  return ListFromDictSlab<K>(keys_, len_);
277
14
}
_ZNK4DictIP6BigStriE4keysEv
Line
Count
Source
275
8
List<K>* Dict<K, V>::keys() const {
276
8
  return ListFromDictSlab<K>(keys_, len_);
277
8
}
_ZNK4DictIP6BigStrS1_E4keysEv
Line
Count
Source
275
2
List<K>* Dict<K, V>::keys() const {
276
2
  return ListFromDictSlab<K>(keys_, len_);
277
2
}
_ZNK4DictIiiE4keysEv
Line
Count
Source
275
4
List<K>* Dict<K, V>::keys() const {
276
4
  return ListFromDictSlab<K>(keys_, len_);
277
4
}
278
279
template <typename K, typename V>
280
4
List<V>* Dict<K, V>::values() const {
281
4
  return ListFromDictSlab<V>(values_, len_);
282
4
}
_ZNK4DictIP6BigStriE6valuesEv
Line
Count
Source
280
2
List<V>* Dict<K, V>::values() const {
281
2
  return ListFromDictSlab<V>(values_, len_);
282
2
}
_ZNK4DictIP6BigStrS1_E6valuesEv
Line
Count
Source
280
2
List<V>* Dict<K, V>::values() const {
281
2
  return ListFromDictSlab<V>(values_, len_);
282
2
}
283
284
template <typename K, typename V>
285
27
void Dict<K, V>::clear() {
286
  // Maintain invariant
287
811
  for (int i = 0; i < index_len_; ++i) {
288
784
    index_->items_[i] = kEmptyEntry;
289
784
  }
290
291
27
  if (keys_) {
292
6
    memset(keys_->items_, 0, len_ * sizeof(K));  // zero for GC scan
293
6
  }
294
27
  if (values_) {
295
6
    memset(values_->items_, 0, len_ * sizeof(V));  // zero for GC scan
296
6
  }
297
27
  len_ = 0;
298
27
}
_ZN4DictIibE5clearEv
Line
Count
Source
285
19
void Dict<K, V>::clear() {
286
  // Maintain invariant
287
19
  for (int i = 0; i < index_len_; ++i) {
288
0
    index_->items_[i] = kEmptyEntry;
289
0
  }
290
291
19
  if (keys_) {
292
0
    memset(keys_->items_, 0, len_ * sizeof(K));  // zero for GC scan
293
0
  }
294
19
  if (values_) {
295
0
    memset(values_->items_, 0, len_ * sizeof(V));  // zero for GC scan
296
0
  }
297
19
  len_ = 0;
298
19
}
_ZN4DictIiP6BigStrE5clearEv
Line
Count
Source
285
2
void Dict<K, V>::clear() {
286
  // Maintain invariant
287
2
  for (int i = 0; i < index_len_; ++i) {
288
0
    index_->items_[i] = kEmptyEntry;
289
0
  }
290
291
2
  if (keys_) {
292
0
    memset(keys_->items_, 0, len_ * sizeof(K));  // zero for GC scan
293
0
  }
294
2
  if (values_) {
295
0
    memset(values_->items_, 0, len_ * sizeof(V));  // zero for GC scan
296
0
  }
297
2
  len_ = 0;
298
2
}
_ZN4DictIP6BigStriE5clearEv
Line
Count
Source
285
2
void Dict<K, V>::clear() {
286
  // Maintain invariant
287
18
  for (int i = 0; i < index_len_; ++i) {
288
16
    index_->items_[i] = kEmptyEntry;
289
16
  }
290
291
2
  if (keys_) {
292
2
    memset(keys_->items_, 0, len_ * sizeof(K));  // zero for GC scan
293
2
  }
294
2
  if (values_) {
295
2
    memset(values_->items_, 0, len_ * sizeof(V));  // zero for GC scan
296
2
  }
297
2
  len_ = 0;
298
2
}
_ZN4DictIiiE5clearEv
Line
Count
Source
285
4
void Dict<K, V>::clear() {
286
  // Maintain invariant
287
772
  for (int i = 0; i < index_len_; ++i) {
288
768
    index_->items_[i] = kEmptyEntry;
289
768
  }
290
291
4
  if (keys_) {
292
4
    memset(keys_->items_, 0, len_ * sizeof(K));  // zero for GC scan
293
4
  }
294
4
  if (values_) {
295
4
    memset(values_->items_, 0, len_ * sizeof(V));  // zero for GC scan
296
4
  }
297
4
  len_ = 0;
298
4
}
299
300
// TODO:
301
// - Special case to intern BigStr* when it's hashed?  How?
302
//   - Should we have wrappers like:
303
//   - V GetAndIntern<V>(D, &string_key)
304
//   - SetAndIntern<V>(D, &string_key, value)
305
//   This will enable duplicate copies of the string to be garbage collected
306
template <typename K, typename V>
307
196k
int Dict<K, V>::hash_and_probe(K key) const {
308
196k
  if (capacity_ == 0) {
309
90
    return kTooSmall;
310
90
  }
311
312
  // Hash the key onto a slot in the index. If the first slot is occupied,
313
  // probe until an empty one is found.
314
196k
  unsigned h = hash_key(key);
315
  // faster % using & -- assuming index_len_ is power of 2
316
196k
  int init_bucket = h & (index_len_ - 1);
317
318
  // If we see a tombstone along the probing path, stash it.
319
196k
  int open_slot = -1;
320
321
262k
  for (int i = 0; i < index_len_; ++i) {
322
    // Start at init_bucket and wrap araound
323
324
    // faster % using & -- assuming index_len_ is power of 2
325
262k
    int slot = (i + init_bucket) & (index_len_ - 1);
326
327
262k
    int kv_index = index_->items_[slot];
328
262k
    DCHECK(kv_index < len_);
329
    // Optimistically this is the common case once the table has been populated.
330
262k
    if (kv_index >= 0) {
331
131k
      unsigned h2 = hash_key(keys_->items_[kv_index]);
332
131k
      if (h == h2 && keys_equal(keys_->items_[kv_index], key)) {
333
72.4k
        return slot;
334
72.4k
      }
335
131k
    }
336
337
189k
    if (kv_index == kEmptyEntry) {
338
123k
      if (open_slot != -1) {
339
6
        slot = open_slot;
340
6
      }
341
      // If there isn't room in the entry arrays, tell the caller to resize.
342
123k
      return len_ < capacity_ ? slot : kTooSmall;
343
123k
    }
344
345
    // Tombstone or collided keys unequal. Keep scanning.
346
66.0k
    DCHECK(kv_index >= 0 || kv_index == kDeletedEntry);
347
66.0k
    if (kv_index == kDeletedEntry && open_slot == -1) {
348
      // NOTE: We only record the open slot here. We DON'T return it. If we're
349
      // looking for a key that was writen before this tombstone was written to
350
      // the index we should continue probing until we get to that key. If we
351
      // get to an empty index slot or the end of the index then we know we are
352
      // dealing with a new key and can safely replace the tombstone without
353
      // disrupting any existing keys.
354
5.05k
      open_slot = slot;
355
5.05k
    }
356
66.0k
  }
357
358
2
  if (open_slot != -1) {
359
2
    return len_ < capacity_ ? open_slot : kTooSmall;
360
2
  }
361
362
0
  return kTooSmall;
363
2
}
_ZNK4DictIP6BigStriE14hash_and_probeES1_
Line
Count
Source
307
387
int Dict<K, V>::hash_and_probe(K key) const {
308
387
  if (capacity_ == 0) {
309
22
    return kTooSmall;
310
22
  }
311
312
  // Hash the key onto a slot in the index. If the first slot is occupied,
313
  // probe until an empty one is found.
314
365
  unsigned h = hash_key(key);
315
  // faster % using & -- assuming index_len_ is power of 2
316
365
  int init_bucket = h & (index_len_ - 1);
317
318
  // If we see a tombstone along the probing path, stash it.
319
365
  int open_slot = -1;
320
321
481
  for (int i = 0; i < index_len_; ++i) {
322
    // Start at init_bucket and wrap araound
323
324
    // faster % using & -- assuming index_len_ is power of 2
325
481
    int slot = (i + init_bucket) & (index_len_ - 1);
326
327
481
    int kv_index = index_->items_[slot];
328
481
    DCHECK(kv_index < len_);
329
    // Optimistically this is the common case once the table has been populated.
330
481
    if (kv_index >= 0) {
331
138
      unsigned h2 = hash_key(keys_->items_[kv_index]);
332
138
      if (h == h2 && keys_equal(keys_->items_[kv_index], key)) {
333
24
        return slot;
334
24
      }
335
138
    }
336
337
457
    if (kv_index == kEmptyEntry) {
338
341
      if (open_slot != -1) {
339
2
        slot = open_slot;
340
2
      }
341
      // If there isn't room in the entry arrays, tell the caller to resize.
342
341
      return len_ < capacity_ ? slot : kTooSmall;
343
341
    }
344
345
    // Tombstone or collided keys unequal. Keep scanning.
346
116
    DCHECK(kv_index >= 0 || kv_index == kDeletedEntry);
347
116
    if (kv_index == kDeletedEntry && open_slot == -1) {
348
      // NOTE: We only record the open slot here. We DON'T return it. If we're
349
      // looking for a key that was writen before this tombstone was written to
350
      // the index we should continue probing until we get to that key. If we
351
      // get to an empty index slot or the end of the index then we know we are
352
      // dealing with a new key and can safely replace the tombstone without
353
      // disrupting any existing keys.
354
2
      open_slot = slot;
355
2
    }
356
116
  }
357
358
0
  if (open_slot != -1) {
359
0
    return len_ < capacity_ ? open_slot : kTooSmall;
360
0
  }
361
362
0
  return kTooSmall;
363
0
}
_ZNK4DictIiP6BigStrE14hash_and_probeEi
Line
Count
Source
307
248
int Dict<K, V>::hash_and_probe(K key) const {
308
248
  if (capacity_ == 0) {
309
12
    return kTooSmall;
310
12
  }
311
312
  // Hash the key onto a slot in the index. If the first slot is occupied,
313
  // probe until an empty one is found.
314
236
  unsigned h = hash_key(key);
315
  // faster % using & -- assuming index_len_ is power of 2
316
236
  int init_bucket = h & (index_len_ - 1);
317
318
  // If we see a tombstone along the probing path, stash it.
319
236
  int open_slot = -1;
320
321
418
  for (int i = 0; i < index_len_; ++i) {
322
    // Start at init_bucket and wrap araound
323
324
    // faster % using & -- assuming index_len_ is power of 2
325
418
    int slot = (i + init_bucket) & (index_len_ - 1);
326
327
418
    int kv_index = index_->items_[slot];
328
418
    DCHECK(kv_index < len_);
329
    // Optimistically this is the common case once the table has been populated.
330
418
    if (kv_index >= 0) {
331
192
      unsigned h2 = hash_key(keys_->items_[kv_index]);
332
192
      if (h == h2 && keys_equal(keys_->items_[kv_index], key)) {
333
10
        return slot;
334
10
      }
335
192
    }
336
337
408
    if (kv_index == kEmptyEntry) {
338
226
      if (open_slot != -1) {
339
0
        slot = open_slot;
340
0
      }
341
      // If there isn't room in the entry arrays, tell the caller to resize.
342
226
      return len_ < capacity_ ? slot : kTooSmall;
343
226
    }
344
345
    // Tombstone or collided keys unequal. Keep scanning.
346
182
    DCHECK(kv_index >= 0 || kv_index == kDeletedEntry);
347
182
    if (kv_index == kDeletedEntry && open_slot == -1) {
348
      // NOTE: We only record the open slot here. We DON'T return it. If we're
349
      // looking for a key that was writen before this tombstone was written to
350
      // the index we should continue probing until we get to that key. If we
351
      // get to an empty index slot or the end of the index then we know we are
352
      // dealing with a new key and can safely replace the tombstone without
353
      // disrupting any existing keys.
354
0
      open_slot = slot;
355
0
    }
356
182
  }
357
358
0
  if (open_slot != -1) {
359
0
    return len_ < capacity_ ? open_slot : kTooSmall;
360
0
  }
361
362
0
  return kTooSmall;
363
0
}
_ZNK4DictIP6BigStrS1_E14hash_and_probeES1_
Line
Count
Source
307
48
int Dict<K, V>::hash_and_probe(K key) const {
308
48
  if (capacity_ == 0) {
309
8
    return kTooSmall;
310
8
  }
311
312
  // Hash the key onto a slot in the index. If the first slot is occupied,
313
  // probe until an empty one is found.
314
40
  unsigned h = hash_key(key);
315
  // faster % using & -- assuming index_len_ is power of 2
316
40
  int init_bucket = h & (index_len_ - 1);
317
318
  // If we see a tombstone along the probing path, stash it.
319
40
  int open_slot = -1;
320
321
46
  for (int i = 0; i < index_len_; ++i) {
322
    // Start at init_bucket and wrap araound
323
324
    // faster % using & -- assuming index_len_ is power of 2
325
46
    int slot = (i + init_bucket) & (index_len_ - 1);
326
327
46
    int kv_index = index_->items_[slot];
328
46
    DCHECK(kv_index < len_);
329
    // Optimistically this is the common case once the table has been populated.
330
46
    if (kv_index >= 0) {
331
12
      unsigned h2 = hash_key(keys_->items_[kv_index]);
332
12
      if (h == h2 && keys_equal(keys_->items_[kv_index], key)) {
333
6
        return slot;
334
6
      }
335
12
    }
336
337
40
    if (kv_index == kEmptyEntry) {
338
34
      if (open_slot != -1) {
339
0
        slot = open_slot;
340
0
      }
341
      // If there isn't room in the entry arrays, tell the caller to resize.
342
34
      return len_ < capacity_ ? slot : kTooSmall;
343
34
    }
344
345
    // Tombstone or collided keys unequal. Keep scanning.
346
6
    DCHECK(kv_index >= 0 || kv_index == kDeletedEntry);
347
6
    if (kv_index == kDeletedEntry && open_slot == -1) {
348
      // NOTE: We only record the open slot here. We DON'T return it. If we're
349
      // looking for a key that was writen before this tombstone was written to
350
      // the index we should continue probing until we get to that key. If we
351
      // get to an empty index slot or the end of the index then we know we are
352
      // dealing with a new key and can safely replace the tombstone without
353
      // disrupting any existing keys.
354
0
      open_slot = slot;
355
0
    }
356
6
  }
357
358
0
  if (open_slot != -1) {
359
0
    return len_ < capacity_ ? open_slot : kTooSmall;
360
0
  }
361
362
0
  return kTooSmall;
363
0
}
_ZNK4DictIibE14hash_and_probeEi
Line
Count
Source
307
114
int Dict<K, V>::hash_and_probe(K key) const {
308
114
  if (capacity_ == 0) {
309
19
    return kTooSmall;
310
19
  }
311
312
  // Hash the key onto a slot in the index. If the first slot is occupied,
313
  // probe until an empty one is found.
314
95
  unsigned h = hash_key(key);
315
  // faster % using & -- assuming index_len_ is power of 2
316
95
  int init_bucket = h & (index_len_ - 1);
317
318
  // If we see a tombstone along the probing path, stash it.
319
95
  int open_slot = -1;
320
321
97
  for (int i = 0; i < index_len_; ++i) {
322
    // Start at init_bucket and wrap araound
323
324
    // faster % using & -- assuming index_len_ is power of 2
325
97
    int slot = (i + init_bucket) & (index_len_ - 1);
326
327
97
    int kv_index = index_->items_[slot];
328
97
    DCHECK(kv_index < len_);
329
    // Optimistically this is the common case once the table has been populated.
330
97
    if (kv_index >= 0) {
331
2
      unsigned h2 = hash_key(keys_->items_[kv_index]);
332
2
      if (h == h2 && keys_equal(keys_->items_[kv_index], key)) {
333
0
        return slot;
334
0
      }
335
2
    }
336
337
97
    if (kv_index == kEmptyEntry) {
338
95
      if (open_slot != -1) {
339
0
        slot = open_slot;
340
0
      }
341
      // If there isn't room in the entry arrays, tell the caller to resize.
342
95
      return len_ < capacity_ ? slot : kTooSmall;
343
95
    }
344
345
    // Tombstone or collided keys unequal. Keep scanning.
346
2
    DCHECK(kv_index >= 0 || kv_index == kDeletedEntry);
347
2
    if (kv_index == kDeletedEntry && open_slot == -1) {
348
      // NOTE: We only record the open slot here. We DON'T return it. If we're
349
      // looking for a key that was writen before this tombstone was written to
350
      // the index we should continue probing until we get to that key. If we
351
      // get to an empty index slot or the end of the index then we know we are
352
      // dealing with a new key and can safely replace the tombstone without
353
      // disrupting any existing keys.
354
0
      open_slot = slot;
355
0
    }
356
2
  }
357
358
0
  if (open_slot != -1) {
359
0
    return len_ < capacity_ ? open_slot : kTooSmall;
360
0
  }
361
362
0
  return kTooSmall;
363
0
}
_ZNK4DictIP5PointP6BigStrE14hash_and_probeES1_
Line
Count
Source
307
190
int Dict<K, V>::hash_and_probe(K key) const {
308
190
  if (capacity_ == 0) {
309
2
    return kTooSmall;
310
2
  }
311
312
  // Hash the key onto a slot in the index. If the first slot is occupied,
313
  // probe until an empty one is found.
314
188
  unsigned h = hash_key(key);
315
  // faster % using & -- assuming index_len_ is power of 2
316
188
  int init_bucket = h & (index_len_ - 1);
317
318
  // If we see a tombstone along the probing path, stash it.
319
188
  int open_slot = -1;
320
321
252
  for (int i = 0; i < index_len_; ++i) {
322
    // Start at init_bucket and wrap araound
323
324
    // faster % using & -- assuming index_len_ is power of 2
325
252
    int slot = (i + init_bucket) & (index_len_ - 1);
326
327
252
    int kv_index = index_->items_[slot];
328
252
    DCHECK(kv_index < len_);
329
    // Optimistically this is the common case once the table has been populated.
330
252
    if (kv_index >= 0) {
331
64
      unsigned h2 = hash_key(keys_->items_[kv_index]);
332
64
      if (h == h2 && keys_equal(keys_->items_[kv_index], key)) {
333
0
        return slot;
334
0
      }
335
64
    }
336
337
252
    if (kv_index == kEmptyEntry) {
338
188
      if (open_slot != -1) {
339
0
        slot = open_slot;
340
0
      }
341
      // If there isn't room in the entry arrays, tell the caller to resize.
342
188
      return len_ < capacity_ ? slot : kTooSmall;
343
188
    }
344
345
    // Tombstone or collided keys unequal. Keep scanning.
346
64
    DCHECK(kv_index >= 0 || kv_index == kDeletedEntry);
347
64
    if (kv_index == kDeletedEntry && open_slot == -1) {
348
      // NOTE: We only record the open slot here. We DON'T return it. If we're
349
      // looking for a key that was writen before this tombstone was written to
350
      // the index we should continue probing until we get to that key. If we
351
      // get to an empty index slot or the end of the index then we know we are
352
      // dealing with a new key and can safely replace the tombstone without
353
      // disrupting any existing keys.
354
0
      open_slot = slot;
355
0
    }
356
64
  }
357
358
0
  if (open_slot != -1) {
359
0
    return len_ < capacity_ ? open_slot : kTooSmall;
360
0
  }
361
362
0
  return kTooSmall;
363
0
}
_ZNK4DictIlP6BigStrE14hash_and_probeEl
Line
Count
Source
307
161k
int Dict<K, V>::hash_and_probe(K key) const {
308
161k
  if (capacity_ == 0) {
309
4
    return kTooSmall;
310
4
  }
311
312
  // Hash the key onto a slot in the index. If the first slot is occupied,
313
  // probe until an empty one is found.
314
161k
  unsigned h = hash_key(key);
315
  // faster % using & -- assuming index_len_ is power of 2
316
161k
  int init_bucket = h & (index_len_ - 1);
317
318
  // If we see a tombstone along the probing path, stash it.
319
161k
  int open_slot = -1;
320
321
212k
  for (int i = 0; i < index_len_; ++i) {
322
    // Start at init_bucket and wrap araound
323
324
    // faster % using & -- assuming index_len_ is power of 2
325
212k
    int slot = (i + init_bucket) & (index_len_ - 1);
326
327
212k
    int kv_index = index_->items_[slot];
328
212k
    DCHECK(kv_index < len_);
329
    // Optimistically this is the common case once the table has been populated.
330
212k
    if (kv_index >= 0) {
331
90.6k
      unsigned h2 = hash_key(keys_->items_[kv_index]);
332
90.6k
      if (h == h2 && keys_equal(keys_->items_[kv_index], key)) {
333
39.9k
        return slot;
334
39.9k
      }
335
90.6k
    }
336
337
172k
    if (kv_index == kEmptyEntry) {
338
122k
      if (open_slot != -1) {
339
0
        slot = open_slot;
340
0
      }
341
      // If there isn't room in the entry arrays, tell the caller to resize.
342
122k
      return len_ < capacity_ ? slot : kTooSmall;
343
122k
    }
344
345
    // Tombstone or collided keys unequal. Keep scanning.
346
50.7k
    DCHECK(kv_index >= 0 || kv_index == kDeletedEntry);
347
50.7k
    if (kv_index == kDeletedEntry && open_slot == -1) {
348
      // NOTE: We only record the open slot here. We DON'T return it. If we're
349
      // looking for a key that was writen before this tombstone was written to
350
      // the index we should continue probing until we get to that key. If we
351
      // get to an empty index slot or the end of the index then we know we are
352
      // dealing with a new key and can safely replace the tombstone without
353
      // disrupting any existing keys.
354
0
      open_slot = slot;
355
0
    }
356
50.7k
  }
357
358
0
  if (open_slot != -1) {
359
0
    return len_ < capacity_ ? open_slot : kTooSmall;
360
0
  }
361
362
0
  return kTooSmall;
363
0
}
_ZNK4DictIiiE14hash_and_probeEi
Line
Count
Source
307
33.3k
int Dict<K, V>::hash_and_probe(K key) const {
308
33.3k
  if (capacity_ == 0) {
309
14
    return kTooSmall;
310
14
  }
311
312
  // Hash the key onto a slot in the index. If the first slot is occupied,
313
  // probe until an empty one is found.
314
33.3k
  unsigned h = hash_key(key);
315
  // faster % using & -- assuming index_len_ is power of 2
316
33.3k
  int init_bucket = h & (index_len_ - 1);
317
318
  // If we see a tombstone along the probing path, stash it.
319
33.3k
  int open_slot = -1;
320
321
48.1k
  for (int i = 0; i < index_len_; ++i) {
322
    // Start at init_bucket and wrap araound
323
324
    // faster % using & -- assuming index_len_ is power of 2
325
48.1k
    int slot = (i + init_bucket) & (index_len_ - 1);
326
327
48.1k
    int kv_index = index_->items_[slot];
328
48.1k
    DCHECK(kv_index < len_);
329
    // Optimistically this is the common case once the table has been populated.
330
48.1k
    if (kv_index >= 0) {
331
40.4k
      unsigned h2 = hash_key(keys_->items_[kv_index]);
332
40.4k
      if (h == h2 && keys_equal(keys_->items_[kv_index], key)) {
333
32.4k
        return slot;
334
32.4k
      }
335
40.4k
    }
336
337
15.7k
    if (kv_index == kEmptyEntry) {
338
842
      if (open_slot != -1) {
339
4
        slot = open_slot;
340
4
      }
341
      // If there isn't room in the entry arrays, tell the caller to resize.
342
842
      return len_ < capacity_ ? slot : kTooSmall;
343
842
    }
344
345
    // Tombstone or collided keys unequal. Keep scanning.
346
14.8k
    DCHECK(kv_index >= 0 || kv_index == kDeletedEntry);
347
14.8k
    if (kv_index == kDeletedEntry && open_slot == -1) {
348
      // NOTE: We only record the open slot here. We DON'T return it. If we're
349
      // looking for a key that was writen before this tombstone was written to
350
      // the index we should continue probing until we get to that key. If we
351
      // get to an empty index slot or the end of the index then we know we are
352
      // dealing with a new key and can safely replace the tombstone without
353
      // disrupting any existing keys.
354
5.05k
      open_slot = slot;
355
5.05k
    }
356
14.8k
  }
357
358
2
  if (open_slot != -1) {
359
2
    return len_ < capacity_ ? open_slot : kTooSmall;
360
2
  }
361
362
0
  return kTooSmall;
363
2
}
_ZNK4DictIP6Tuple2IiiEiE14hash_and_probeES2_
Line
Count
Source
307
10
int Dict<K, V>::hash_and_probe(K key) const {
308
10
  if (capacity_ == 0) {
309
2
    return kTooSmall;
310
2
  }
311
312
  // Hash the key onto a slot in the index. If the first slot is occupied,
313
  // probe until an empty one is found.
314
8
  unsigned h = hash_key(key);
315
  // faster % using & -- assuming index_len_ is power of 2
316
8
  int init_bucket = h & (index_len_ - 1);
317
318
  // If we see a tombstone along the probing path, stash it.
319
8
  int open_slot = -1;
320
321
8
  for (int i = 0; i < index_len_; ++i) {
322
    // Start at init_bucket and wrap araound
323
324
    // faster % using & -- assuming index_len_ is power of 2
325
8
    int slot = (i + init_bucket) & (index_len_ - 1);
326
327
8
    int kv_index = index_->items_[slot];
328
8
    DCHECK(kv_index < len_);
329
    // Optimistically this is the common case once the table has been populated.
330
8
    if (kv_index >= 0) {
331
4
      unsigned h2 = hash_key(keys_->items_[kv_index]);
332
4
      if (h == h2 && keys_equal(keys_->items_[kv_index], key)) {
333
4
        return slot;
334
4
      }
335
4
    }
336
337
4
    if (kv_index == kEmptyEntry) {
338
4
      if (open_slot != -1) {
339
0
        slot = open_slot;
340
0
      }
341
      // If there isn't room in the entry arrays, tell the caller to resize.
342
4
      return len_ < capacity_ ? slot : kTooSmall;
343
4
    }
344
345
    // Tombstone or collided keys unequal. Keep scanning.
346
0
    DCHECK(kv_index >= 0 || kv_index == kDeletedEntry);
347
0
    if (kv_index == kDeletedEntry && open_slot == -1) {
348
      // NOTE: We only record the open slot here. We DON'T return it. If we're
349
      // looking for a key that was writen before this tombstone was written to
350
      // the index we should continue probing until we get to that key. If we
351
      // get to an empty index slot or the end of the index then we know we are
352
      // dealing with a new key and can safely replace the tombstone without
353
      // disrupting any existing keys.
354
0
      open_slot = slot;
355
0
    }
356
0
  }
357
358
0
  if (open_slot != -1) {
359
0
    return len_ < capacity_ ? open_slot : kTooSmall;
360
0
  }
361
362
0
  return kTooSmall;
363
0
}
_ZNK4DictIP6Tuple2IP6BigStriEiE14hash_and_probeES4_
Line
Count
Source
307
10
int Dict<K, V>::hash_and_probe(K key) const {
308
10
  if (capacity_ == 0) {
309
2
    return kTooSmall;
310
2
  }
311
312
  // Hash the key onto a slot in the index. If the first slot is occupied,
313
  // probe until an empty one is found.
314
8
  unsigned h = hash_key(key);
315
  // faster % using & -- assuming index_len_ is power of 2
316
8
  int init_bucket = h & (index_len_ - 1);
317
318
  // If we see a tombstone along the probing path, stash it.
319
8
  int open_slot = -1;
320
321
8
  for (int i = 0; i < index_len_; ++i) {
322
    // Start at init_bucket and wrap araound
323
324
    // faster % using & -- assuming index_len_ is power of 2
325
8
    int slot = (i + init_bucket) & (index_len_ - 1);
326
327
8
    int kv_index = index_->items_[slot];
328
8
    DCHECK(kv_index < len_);
329
    // Optimistically this is the common case once the table has been populated.
330
8
    if (kv_index >= 0) {
331
4
      unsigned h2 = hash_key(keys_->items_[kv_index]);
332
4
      if (h == h2 && keys_equal(keys_->items_[kv_index], key)) {
333
4
        return slot;
334
4
      }
335
4
    }
336
337
4
    if (kv_index == kEmptyEntry) {
338
4
      if (open_slot != -1) {
339
0
        slot = open_slot;
340
0
      }
341
      // If there isn't room in the entry arrays, tell the caller to resize.
342
4
      return len_ < capacity_ ? slot : kTooSmall;
343
4
    }
344
345
    // Tombstone or collided keys unequal. Keep scanning.
346
0
    DCHECK(kv_index >= 0 || kv_index == kDeletedEntry);
347
0
    if (kv_index == kDeletedEntry && open_slot == -1) {
348
      // NOTE: We only record the open slot here. We DON'T return it. If we're
349
      // looking for a key that was writen before this tombstone was written to
350
      // the index we should continue probing until we get to that key. If we
351
      // get to an empty index slot or the end of the index then we know we are
352
      // dealing with a new key and can safely replace the tombstone without
353
      // disrupting any existing keys.
354
0
      open_slot = slot;
355
0
    }
356
0
  }
357
358
0
  if (open_slot != -1) {
359
0
    return len_ < capacity_ ? open_slot : kTooSmall;
360
0
  }
361
362
0
  return kTooSmall;
363
0
}
Unexecuted instantiation: _ZNK4DictIiP6Tuple2IP4ListIPS1_IPS0_IiiEEEPS_IiiEEE14hash_and_probeEi
_ZNK4DictIP6BigStrPN10value_asdl7value_tEE14hash_and_probeES1_
Line
Count
Source
307
82
int Dict<K, V>::hash_and_probe(K key) const {
308
82
  if (capacity_ == 0) {
309
3
    return kTooSmall;
310
3
  }
311
312
  // Hash the key onto a slot in the index. If the first slot is occupied,
313
  // probe until an empty one is found.
314
79
  unsigned h = hash_key(key);
315
  // faster % using & -- assuming index_len_ is power of 2
316
79
  int init_bucket = h & (index_len_ - 1);
317
318
  // If we see a tombstone along the probing path, stash it.
319
79
  int open_slot = -1;
320
321
106
  for (int i = 0; i < index_len_; ++i) {
322
    // Start at init_bucket and wrap araound
323
324
    // faster % using & -- assuming index_len_ is power of 2
325
106
    int slot = (i + init_bucket) & (index_len_ - 1);
326
327
106
    int kv_index = index_->items_[slot];
328
106
    DCHECK(kv_index < len_);
329
    // Optimistically this is the common case once the table has been populated.
330
106
    if (kv_index >= 0) {
331
27
      unsigned h2 = hash_key(keys_->items_[kv_index]);
332
27
      if (h == h2 && keys_equal(keys_->items_[kv_index], key)) {
333
0
        return slot;
334
0
      }
335
27
    }
336
337
106
    if (kv_index == kEmptyEntry) {
338
79
      if (open_slot != -1) {
339
0
        slot = open_slot;
340
0
      }
341
      // If there isn't room in the entry arrays, tell the caller to resize.
342
79
      return len_ < capacity_ ? slot : kTooSmall;
343
79
    }
344
345
    // Tombstone or collided keys unequal. Keep scanning.
346
27
    DCHECK(kv_index >= 0 || kv_index == kDeletedEntry);
347
27
    if (kv_index == kDeletedEntry && open_slot == -1) {
348
      // NOTE: We only record the open slot here. We DON'T return it. If we're
349
      // looking for a key that was writen before this tombstone was written to
350
      // the index we should continue probing until we get to that key. If we
351
      // get to an empty index slot or the end of the index then we know we are
352
      // dealing with a new key and can safely replace the tombstone without
353
      // disrupting any existing keys.
354
0
      open_slot = slot;
355
0
    }
356
27
  }
357
358
0
  if (open_slot != -1) {
359
0
    return len_ < capacity_ ? open_slot : kTooSmall;
360
0
  }
361
362
0
  return kTooSmall;
363
0
}
_ZNK4DictIP6BigStrPN4args7_ActionEE14hash_and_probeES1_
Line
Count
Source
307
79
int Dict<K, V>::hash_and_probe(K key) const {
308
79
  if (capacity_ == 0) {
309
2
    return kTooSmall;
310
2
  }
311
312
  // Hash the key onto a slot in the index. If the first slot is occupied,
313
  // probe until an empty one is found.
314
77
  unsigned h = hash_key(key);
315
  // faster % using & -- assuming index_len_ is power of 2
316
77
  int init_bucket = h & (index_len_ - 1);
317
318
  // If we see a tombstone along the probing path, stash it.
319
77
  int open_slot = -1;
320
321
107
  for (int i = 0; i < index_len_; ++i) {
322
    // Start at init_bucket and wrap araound
323
324
    // faster % using & -- assuming index_len_ is power of 2
325
107
    int slot = (i + init_bucket) & (index_len_ - 1);
326
327
107
    int kv_index = index_->items_[slot];
328
107
    DCHECK(kv_index < len_);
329
    // Optimistically this is the common case once the table has been populated.
330
107
    if (kv_index >= 0) {
331
30
      unsigned h2 = hash_key(keys_->items_[kv_index]);
332
30
      if (h == h2 && keys_equal(keys_->items_[kv_index], key)) {
333
0
        return slot;
334
0
      }
335
30
    }
336
337
107
    if (kv_index == kEmptyEntry) {
338
77
      if (open_slot != -1) {
339
0
        slot = open_slot;
340
0
      }
341
      // If there isn't room in the entry arrays, tell the caller to resize.
342
77
      return len_ < capacity_ ? slot : kTooSmall;
343
77
    }
344
345
    // Tombstone or collided keys unequal. Keep scanning.
346
30
    DCHECK(kv_index >= 0 || kv_index == kDeletedEntry);
347
30
    if (kv_index == kDeletedEntry && open_slot == -1) {
348
      // NOTE: We only record the open slot here. We DON'T return it. If we're
349
      // looking for a key that was writen before this tombstone was written to
350
      // the index we should continue probing until we get to that key. If we
351
      // get to an empty index slot or the end of the index then we know we are
352
      // dealing with a new key and can safely replace the tombstone without
353
      // disrupting any existing keys.
354
0
      open_slot = slot;
355
0
    }
356
30
  }
357
358
0
  if (open_slot != -1) {
359
0
    return len_ < capacity_ ? open_slot : kTooSmall;
360
0
  }
361
362
0
  return kTooSmall;
363
0
}
364
365
template <typename K, typename V>
366
16.3k
int Dict<K, V>::find_kv_index(K key) const {
367
16.3k
  if (index_ != nullptr) {  // Common case
368
16.2k
    int pos = hash_and_probe(key);
369
16.2k
    if (pos == kTooSmall) {
370
0
      return kNotFound;
371
0
    }
372
16.2k
    DCHECK(pos >= 0);
373
0
    int kv_index = index_->items_[pos];
374
16.2k
    if (kv_index < 0) {
375
48
      return kNotFound;
376
48
    }
377
16.2k
    return kv_index;
378
16.2k
  }
379
380
  // Linear search on GlobalDict instances.
381
  // TODO: Should we populate and compare their hash values?
382
51
  for (int i = 0; i < len_; ++i) {
383
25
    if (keys_equal(keys_->items_[i], key)) {
384
15
      return i;
385
15
    }
386
25
  }
387
388
26
  return kNotFound;
389
41
}
_ZNK4DictIP6BigStriE13find_kv_indexES1_
Line
Count
Source
366
24
int Dict<K, V>::find_kv_index(K key) const {
367
24
  if (index_ != nullptr) {  // Common case
368
23
    int pos = hash_and_probe(key);
369
23
    if (pos == kTooSmall) {
370
0
      return kNotFound;
371
0
    }
372
23
    DCHECK(pos >= 0);
373
0
    int kv_index = index_->items_[pos];
374
23
    if (kv_index < 0) {
375
2
      return kNotFound;
376
2
    }
377
21
    return kv_index;
378
23
  }
379
380
  // Linear search on GlobalDict instances.
381
  // TODO: Should we populate and compare their hash values?
382
1
  for (int i = 0; i < len_; ++i) {
383
1
    if (keys_equal(keys_->items_[i], key)) {
384
1
      return i;
385
1
    }
386
1
  }
387
388
0
  return kNotFound;
389
1
}
_ZNK4DictIiP6BigStrE13find_kv_indexEi
Line
Count
Source
366
15
int Dict<K, V>::find_kv_index(K key) const {
367
15
  if (index_ != nullptr) {  // Common case
368
14
    int pos = hash_and_probe(key);
369
14
    if (pos == kTooSmall) {
370
0
      return kNotFound;
371
0
    }
372
14
    DCHECK(pos >= 0);
373
0
    int kv_index = index_->items_[pos];
374
14
    if (kv_index < 0) {
375
4
      return kNotFound;
376
4
    }
377
10
    return kv_index;
378
14
  }
379
380
  // Linear search on GlobalDict instances.
381
  // TODO: Should we populate and compare their hash values?
382
1
  for (int i = 0; i < len_; ++i) {
383
1
    if (keys_equal(keys_->items_[i], key)) {
384
1
      return i;
385
1
    }
386
1
  }
387
388
0
  return kNotFound;
389
1
}
_ZNK4DictIP6BigStrS1_E13find_kv_indexES1_
Line
Count
Source
366
20
int Dict<K, V>::find_kv_index(K key) const {
367
20
  if (index_ != nullptr) {  // Common case
368
4
    int pos = hash_and_probe(key);
369
4
    if (pos == kTooSmall) {
370
0
      return kNotFound;
371
0
    }
372
4
    DCHECK(pos >= 0);
373
0
    int kv_index = index_->items_[pos];
374
4
    if (kv_index < 0) {
375
0
      return kNotFound;
376
0
    }
377
4
    return kv_index;
378
4
  }
379
380
  // Linear search on GlobalDict instances.
381
  // TODO: Should we populate and compare their hash values?
382
24
  for (int i = 0; i < len_; ++i) {
383
17
    if (keys_equal(keys_->items_[i], key)) {
384
9
      return i;
385
9
    }
386
17
  }
387
388
7
  return kNotFound;
389
16
}
_ZNK4DictIibE13find_kv_indexEi
Line
Count
Source
366
57
int Dict<K, V>::find_kv_index(K key) const {
367
57
  if (index_ != nullptr) {  // Common case
368
38
    int pos = hash_and_probe(key);
369
38
    if (pos == kTooSmall) {
370
0
      return kNotFound;
371
0
    }
372
38
    DCHECK(pos >= 0);
373
0
    int kv_index = index_->items_[pos];
374
38
    if (kv_index < 0) {
375
38
      return kNotFound;
376
38
    }
377
0
    return kv_index;
378
38
  }
379
380
  // Linear search on GlobalDict instances.
381
  // TODO: Should we populate and compare their hash values?
382
19
  for (int i = 0; i < len_; ++i) {
383
0
    if (keys_equal(keys_->items_[i], key)) {
384
0
      return i;
385
0
    }
386
0
  }
387
388
19
  return kNotFound;
389
19
}
_ZNK4DictIiiE13find_kv_indexEi
Line
Count
Source
366
16.1k
int Dict<K, V>::find_kv_index(K key) const {
367
16.1k
  if (index_ != nullptr) {  // Common case
368
16.1k
    int pos = hash_and_probe(key);
369
16.1k
    if (pos == kTooSmall) {
370
0
      return kNotFound;
371
0
    }
372
16.1k
    DCHECK(pos >= 0);
373
0
    int kv_index = index_->items_[pos];
374
16.1k
    if (kv_index < 0) {
375
4
      return kNotFound;
376
4
    }
377
16.1k
    return kv_index;
378
16.1k
  }
379
380
  // Linear search on GlobalDict instances.
381
  // TODO: Should we populate and compare their hash values?
382
6
  for (int i = 0; i < len_; ++i) {
383
6
    if (keys_equal(keys_->items_[i], key)) {
384
4
      return i;
385
4
    }
386
6
  }
387
388
0
  return kNotFound;
389
4
}
_ZNK4DictIP6Tuple2IiiEiE13find_kv_indexES2_
Line
Count
Source
366
4
int Dict<K, V>::find_kv_index(K key) const {
367
4
  if (index_ != nullptr) {  // Common case
368
4
    int pos = hash_and_probe(key);
369
4
    if (pos == kTooSmall) {
370
0
      return kNotFound;
371
0
    }
372
4
    DCHECK(pos >= 0);
373
0
    int kv_index = index_->items_[pos];
374
4
    if (kv_index < 0) {
375
0
      return kNotFound;
376
0
    }
377
4
    return kv_index;
378
4
  }
379
380
  // Linear search on GlobalDict instances.
381
  // TODO: Should we populate and compare their hash values?
382
0
  for (int i = 0; i < len_; ++i) {
383
0
    if (keys_equal(keys_->items_[i], key)) {
384
0
      return i;
385
0
    }
386
0
  }
387
388
0
  return kNotFound;
389
0
}
_ZNK4DictIP6Tuple2IP6BigStriEiE13find_kv_indexES4_
Line
Count
Source
366
4
int Dict<K, V>::find_kv_index(K key) const {
367
4
  if (index_ != nullptr) {  // Common case
368
4
    int pos = hash_and_probe(key);
369
4
    if (pos == kTooSmall) {
370
0
      return kNotFound;
371
0
    }
372
4
    DCHECK(pos >= 0);
373
0
    int kv_index = index_->items_[pos];
374
4
    if (kv_index < 0) {
375
0
      return kNotFound;
376
0
    }
377
4
    return kv_index;
378
4
  }
379
380
  // Linear search on GlobalDict instances.
381
  // TODO: Should we populate and compare their hash values?
382
0
  for (int i = 0; i < len_; ++i) {
383
0
    if (keys_equal(keys_->items_[i], key)) {
384
0
      return i;
385
0
    }
386
0
  }
387
388
0
  return kNotFound;
389
0
}
Unexecuted instantiation: _ZNK4DictIP6BigStrPN10value_asdl7value_tEE13find_kv_indexES1_
Unexecuted instantiation: _ZNK4DictIP6BigStrPN4args7_ActionEE13find_kv_indexES1_
390
391
template <typename K, typename V>
392
179k
void Dict<K, V>::set(K key, V val) {
393
179k
  DCHECK(obj_header().heap_tag != HeapTag::Global);
394
0
  int pos = hash_and_probe(key);
395
179k
  if (pos == kTooSmall) {
396
184
    reserve(len_ + 1);
397
184
    pos = hash_and_probe(key);
398
184
  }
399
179k
  DCHECK(pos >= 0);
400
401
0
  int kv_index = index_->items_[pos];
402
179k
  DCHECK(kv_index < len_);
403
179k
  if (kv_index < 0) {
404
    // Write new entries to the end of the k/v arrays. This allows us to recall
405
    // insertion order until the first deletion.
406
123k
    keys_->items_[len_] = key;
407
123k
    values_->items_[len_] = val;
408
123k
    index_->items_[pos] = len_;
409
123k
    len_++;
410
123k
    DCHECK(len_ <= capacity_);
411
123k
  } else {
412
55.7k
    values_->items_[kv_index] = val;
413
55.7k
  }
414
179k
}
_ZN4DictIP6BigStriE3setES1_i
Line
Count
Source
392
326
void Dict<K, V>::set(K key, V val) {
393
326
  DCHECK(obj_header().heap_tag != HeapTag::Global);
394
0
  int pos = hash_and_probe(key);
395
326
  if (pos == kTooSmall) {
396
36
    reserve(len_ + 1);
397
36
    pos = hash_and_probe(key);
398
36
  }
399
326
  DCHECK(pos >= 0);
400
401
0
  int kv_index = index_->items_[pos];
402
326
  DCHECK(kv_index < len_);
403
326
  if (kv_index < 0) {
404
    // Write new entries to the end of the k/v arrays. This allows us to recall
405
    // insertion order until the first deletion.
406
325
    keys_->items_[len_] = key;
407
325
    values_->items_[len_] = val;
408
325
    index_->items_[pos] = len_;
409
325
    len_++;
410
325
    DCHECK(len_ <= capacity_);
411
325
  } else {
412
1
    values_->items_[kv_index] = val;
413
1
  }
414
326
}
_ZN4DictIP6BigStrS1_E3setES1_S1_
Line
Count
Source
392
32
void Dict<K, V>::set(K key, V val) {
393
32
  DCHECK(obj_header().heap_tag != HeapTag::Global);
394
0
  int pos = hash_and_probe(key);
395
32
  if (pos == kTooSmall) {
396
10
    reserve(len_ + 1);
397
10
    pos = hash_and_probe(key);
398
10
  }
399
32
  DCHECK(pos >= 0);
400
401
0
  int kv_index = index_->items_[pos];
402
32
  DCHECK(kv_index < len_);
403
32
  if (kv_index < 0) {
404
    // Write new entries to the end of the k/v arrays. This allows us to recall
405
    // insertion order until the first deletion.
406
32
    keys_->items_[len_] = key;
407
32
    values_->items_[len_] = val;
408
32
    index_->items_[pos] = len_;
409
32
    len_++;
410
32
    DCHECK(len_ <= capacity_);
411
32
  } else {
412
0
    values_->items_[kv_index] = val;
413
0
  }
414
32
}
_ZN4DictIibE3setEib
Line
Count
Source
392
57
void Dict<K, V>::set(K key, V val) {
393
57
  DCHECK(obj_header().heap_tag != HeapTag::Global);
394
0
  int pos = hash_and_probe(key);
395
57
  if (pos == kTooSmall) {
396
19
    reserve(len_ + 1);
397
19
    pos = hash_and_probe(key);
398
19
  }
399
57
  DCHECK(pos >= 0);
400
401
0
  int kv_index = index_->items_[pos];
402
57
  DCHECK(kv_index < len_);
403
57
  if (kv_index < 0) {
404
    // Write new entries to the end of the k/v arrays. This allows us to recall
405
    // insertion order until the first deletion.
406
57
    keys_->items_[len_] = key;
407
57
    values_->items_[len_] = val;
408
57
    index_->items_[pos] = len_;
409
57
    len_++;
410
57
    DCHECK(len_ <= capacity_);
411
57
  } else {
412
0
    values_->items_[kv_index] = val;
413
0
  }
414
57
}
_ZN4DictIP5PointP6BigStrE3setES1_S3_
Line
Count
Source
392
180
void Dict<K, V>::set(K key, V val) {
393
180
  DCHECK(obj_header().heap_tag != HeapTag::Global);
394
0
  int pos = hash_and_probe(key);
395
180
  if (pos == kTooSmall) {
396
10
    reserve(len_ + 1);
397
10
    pos = hash_and_probe(key);
398
10
  }
399
180
  DCHECK(pos >= 0);
400
401
0
  int kv_index = index_->items_[pos];
402
180
  DCHECK(kv_index < len_);
403
180
  if (kv_index < 0) {
404
    // Write new entries to the end of the k/v arrays. This allows us to recall
405
    // insertion order until the first deletion.
406
180
    keys_->items_[len_] = key;
407
180
    values_->items_[len_] = val;
408
180
    index_->items_[pos] = len_;
409
180
    len_++;
410
180
    DCHECK(len_ <= capacity_);
411
180
  } else {
412
0
    values_->items_[kv_index] = val;
413
0
  }
414
180
}
_ZN4DictIiP6BigStrE3setEiS1_
Line
Count
Source
392
210
void Dict<K, V>::set(K key, V val) {
393
210
  DCHECK(obj_header().heap_tag != HeapTag::Global);
394
0
  int pos = hash_and_probe(key);
395
210
  if (pos == kTooSmall) {
396
22
    reserve(len_ + 1);
397
22
    pos = hash_and_probe(key);
398
22
  }
399
210
  DCHECK(pos >= 0);
400
401
0
  int kv_index = index_->items_[pos];
402
210
  DCHECK(kv_index < len_);
403
210
  if (kv_index < 0) {
404
    // Write new entries to the end of the k/v arrays. This allows us to recall
405
    // insertion order until the first deletion.
406
210
    keys_->items_[len_] = key;
407
210
    values_->items_[len_] = val;
408
210
    index_->items_[pos] = len_;
409
210
    len_++;
410
210
    DCHECK(len_ <= capacity_);
411
210
  } else {
412
0
    values_->items_[kv_index] = val;
413
0
  }
414
210
}
_ZN4DictIlP6BigStrE3setElS1_
Line
Count
Source
392
161k
void Dict<K, V>::set(K key, V val) {
393
161k
  DCHECK(obj_header().heap_tag != HeapTag::Global);
394
0
  int pos = hash_and_probe(key);
395
161k
  if (pos == kTooSmall) {
396
40
    reserve(len_ + 1);
397
40
    pos = hash_and_probe(key);
398
40
  }
399
161k
  DCHECK(pos >= 0);
400
401
0
  int kv_index = index_->items_[pos];
402
161k
  DCHECK(kv_index < len_);
403
161k
  if (kv_index < 0) {
404
    // Write new entries to the end of the k/v arrays. This allows us to recall
405
    // insertion order until the first deletion.
406
121k
    keys_->items_[len_] = key;
407
121k
    values_->items_[len_] = val;
408
121k
    index_->items_[pos] = len_;
409
121k
    len_++;
410
121k
    DCHECK(len_ <= capacity_);
411
121k
  } else {
412
39.9k
    values_->items_[kv_index] = val;
413
39.9k
  }
414
161k
}
_ZN4DictIiiE3setEii
Line
Count
Source
392
16.7k
void Dict<K, V>::set(K key, V val) {
393
16.7k
  DCHECK(obj_header().heap_tag != HeapTag::Global);
394
0
  int pos = hash_and_probe(key);
395
16.7k
  if (pos == kTooSmall) {
396
28
    reserve(len_ + 1);
397
28
    pos = hash_and_probe(key);
398
28
  }
399
16.7k
  DCHECK(pos >= 0);
400
401
0
  int kv_index = index_->items_[pos];
402
16.7k
  DCHECK(kv_index < len_);
403
16.7k
  if (kv_index < 0) {
404
    // Write new entries to the end of the k/v arrays. This allows us to recall
405
    // insertion order until the first deletion.
406
826
    keys_->items_[len_] = key;
407
826
    values_->items_[len_] = val;
408
826
    index_->items_[pos] = len_;
409
826
    len_++;
410
826
    DCHECK(len_ <= capacity_);
411
15.8k
  } else {
412
15.8k
    values_->items_[kv_index] = val;
413
15.8k
  }
414
16.7k
}
_ZN4DictIP6Tuple2IiiEiE3setES2_i
Line
Count
Source
392
4
void Dict<K, V>::set(K key, V val) {
393
4
  DCHECK(obj_header().heap_tag != HeapTag::Global);
394
0
  int pos = hash_and_probe(key);
395
4
  if (pos == kTooSmall) {
396
2
    reserve(len_ + 1);
397
2
    pos = hash_and_probe(key);
398
2
  }
399
4
  DCHECK(pos >= 0);
400
401
0
  int kv_index = index_->items_[pos];
402
4
  DCHECK(kv_index < len_);
403
4
  if (kv_index < 0) {
404
    // Write new entries to the end of the k/v arrays. This allows us to recall
405
    // insertion order until the first deletion.
406
4
    keys_->items_[len_] = key;
407
4
    values_->items_[len_] = val;
408
4
    index_->items_[pos] = len_;
409
4
    len_++;
410
4
    DCHECK(len_ <= capacity_);
411
4
  } else {
412
0
    values_->items_[kv_index] = val;
413
0
  }
414
4
}
_ZN4DictIP6Tuple2IP6BigStriEiE3setES4_i
Line
Count
Source
392
4
void Dict<K, V>::set(K key, V val) {
393
4
  DCHECK(obj_header().heap_tag != HeapTag::Global);
394
0
  int pos = hash_and_probe(key);
395
4
  if (pos == kTooSmall) {
396
2
    reserve(len_ + 1);
397
2
    pos = hash_and_probe(key);
398
2
  }
399
4
  DCHECK(pos >= 0);
400
401
0
  int kv_index = index_->items_[pos];
402
4
  DCHECK(kv_index < len_);
403
4
  if (kv_index < 0) {
404
    // Write new entries to the end of the k/v arrays. This allows us to recall
405
    // insertion order until the first deletion.
406
4
    keys_->items_[len_] = key;
407
4
    values_->items_[len_] = val;
408
4
    index_->items_[pos] = len_;
409
4
    len_++;
410
4
    DCHECK(len_ <= capacity_);
411
4
  } else {
412
0
    values_->items_[kv_index] = val;
413
0
  }
414
4
}
Unexecuted instantiation: _ZN4DictIiP6Tuple2IP4ListIPS1_IPS0_IiiEEEPS_IiiEEE3setEiSB_
_ZN4DictIP6BigStrPN10value_asdl7value_tEE3setES1_S4_
Line
Count
Source
392
74
void Dict<K, V>::set(K key, V val) {
393
74
  DCHECK(obj_header().heap_tag != HeapTag::Global);
394
0
  int pos = hash_and_probe(key);
395
74
  if (pos == kTooSmall) {
396
8
    reserve(len_ + 1);
397
8
    pos = hash_and_probe(key);
398
8
  }
399
74
  DCHECK(pos >= 0);
400
401
0
  int kv_index = index_->items_[pos];
402
74
  DCHECK(kv_index < len_);
403
74
  if (kv_index < 0) {
404
    // Write new entries to the end of the k/v arrays. This allows us to recall
405
    // insertion order until the first deletion.
406
74
    keys_->items_[len_] = key;
407
74
    values_->items_[len_] = val;
408
74
    index_->items_[pos] = len_;
409
74
    len_++;
410
74
    DCHECK(len_ <= capacity_);
411
74
  } else {
412
0
    values_->items_[kv_index] = val;
413
0
  }
414
74
}
_ZN4DictIP6BigStrPN4args7_ActionEE3setES1_S4_
Line
Count
Source
392
72
void Dict<K, V>::set(K key, V val) {
393
72
  DCHECK(obj_header().heap_tag != HeapTag::Global);
394
0
  int pos = hash_and_probe(key);
395
72
  if (pos == kTooSmall) {
396
7
    reserve(len_ + 1);
397
7
    pos = hash_and_probe(key);
398
7
  }
399
72
  DCHECK(pos >= 0);
400
401
0
  int kv_index = index_->items_[pos];
402
72
  DCHECK(kv_index < len_);
403
72
  if (kv_index < 0) {
404
    // Write new entries to the end of the k/v arrays. This allows us to recall
405
    // insertion order until the first deletion.
406
72
    keys_->items_[len_] = key;
407
72
    values_->items_[len_] = val;
408
72
    index_->items_[pos] = len_;
409
72
    len_++;
410
72
    DCHECK(len_ <= capacity_);
411
72
  } else {
412
0
    values_->items_[kv_index] = val;
413
0
  }
414
72
}
415
416
template <typename K, typename V>
417
61
inline int len(const Dict<K, V>* d) {
418
61
  return d->len_;
419
61
}
_Z3lenIP6BigStrS1_EiPK4DictIT_T0_E
Line
Count
Source
417
13
inline int len(const Dict<K, V>* d) {
418
13
  return d->len_;
419
13
}
_Z3lenIP6BigStriEiPK4DictIT_T0_E
Line
Count
Source
417
19
inline int len(const Dict<K, V>* d) {
418
19
  return d->len_;
419
19
}
_Z3lenIiP6BigStrEiPK4DictIT_T0_E
Line
Count
Source
417
9
inline int len(const Dict<K, V>* d) {
418
9
  return d->len_;
419
9
}
_Z3lenIP5PointP6BigStrEiPK4DictIT_T0_E
Line
Count
Source
417
2
inline int len(const Dict<K, V>* d) {
418
2
  return d->len_;
419
2
}
_Z3lenIlP6BigStrEiPK4DictIT_T0_E
Line
Count
Source
417
4
inline int len(const Dict<K, V>* d) {
418
4
  return d->len_;
419
4
}
_Z3lenIiiEiPK4DictIT_T0_E
Line
Count
Source
417
14
inline int len(const Dict<K, V>* d) {
418
14
  return d->len_;
419
14
}
Unexecuted instantiation: _Z3lenIP6BigStrPN10value_asdl7value_tEEiPK4DictIT_T0_E
Unexecuted instantiation: _Z3lenIP6BigStrPN4args7_ActionEEiPK4DictIT_T0_E
420
421
template <class K, class V>
422
class DictIter {
423
 public:
424
11
  explicit DictIter(Dict<K, V>* D) : D_(D), pos_(0) {
425
11
  }
_ZN8DictIterIP6BigStriEC2EP4DictIS1_iE
Line
Count
Source
424
9
  explicit DictIter(Dict<K, V>* D) : D_(D), pos_(0) {
425
9
  }
Unexecuted instantiation: _ZN8DictIterIP6BigStrPN10value_asdl7value_tEEC2EP4DictIS1_S4_E
Unexecuted instantiation: _ZN8DictIterIP6BigStrPN12runtime_asdl7HayNodeEEC2EP4DictIS1_S4_E
Unexecuted instantiation: _ZN8DictIterIlP6BigStrEC2EP4DictIlS1_E
_ZN8DictIterIP6BigStrS1_EC2EP4DictIS1_S1_E
Line
Count
Source
424
2
  explicit DictIter(Dict<K, V>* D) : D_(D), pos_(0) {
425
2
  }
Unexecuted instantiation: _ZN8DictIterIP6BigStrPN12runtime_asdl4CellEEC2EP4DictIS1_S4_E
426
17
  void Next() {
427
17
    pos_++;
428
17
  }
_ZN8DictIterIP6BigStriE4NextEv
Line
Count
Source
426
17
  void Next() {
427
17
    pos_++;
428
17
  }
Unexecuted instantiation: _ZN8DictIterIP6BigStrPN10value_asdl7value_tEE4NextEv
Unexecuted instantiation: _ZN8DictIterIP6BigStrPN12runtime_asdl7HayNodeEE4NextEv
Unexecuted instantiation: _ZN8DictIterIlP6BigStrE4NextEv
Unexecuted instantiation: _ZN8DictIterIP6BigStrS1_E4NextEv
Unexecuted instantiation: _ZN8DictIterIP6BigStrPN12runtime_asdl4CellEE4NextEv
429
28
  bool Done() {
430
28
    return pos_ == D_->len_;
431
28
  }
_ZN8DictIterIP6BigStriE4DoneEv
Line
Count
Source
429
26
  bool Done() {
430
26
    return pos_ == D_->len_;
431
26
  }
Unexecuted instantiation: _ZN8DictIterIP6BigStrPN10value_asdl7value_tEE4DoneEv
Unexecuted instantiation: _ZN8DictIterIP6BigStrPN12runtime_asdl7HayNodeEE4DoneEv
Unexecuted instantiation: _ZN8DictIterIlP6BigStrE4DoneEv
_ZN8DictIterIP6BigStrS1_E4DoneEv
Line
Count
Source
429
2
  bool Done() {
430
2
    return pos_ == D_->len_;
431
2
  }
Unexecuted instantiation: _ZN8DictIterIP6BigStrPN12runtime_asdl4CellEE4DoneEv
432
17
  K Key() {
433
17
    return D_->keys_->items_[pos_];
434
17
  }
_ZN8DictIterIP6BigStriE3KeyEv
Line
Count
Source
432
17
  K Key() {
433
17
    return D_->keys_->items_[pos_];
434
17
  }
Unexecuted instantiation: _ZN8DictIterIP6BigStrPN10value_asdl7value_tEE3KeyEv
Unexecuted instantiation: _ZN8DictIterIP6BigStrPN12runtime_asdl7HayNodeEE3KeyEv
Unexecuted instantiation: _ZN8DictIterIlP6BigStrE3KeyEv
Unexecuted instantiation: _ZN8DictIterIP6BigStrS1_E3KeyEv
Unexecuted instantiation: _ZN8DictIterIP6BigStrPN12runtime_asdl4CellEE3KeyEv
435
10
  V Value() {
436
10
    return D_->values_->items_[pos_];
437
10
  }
_ZN8DictIterIP6BigStriE5ValueEv
Line
Count
Source
435
10
  V Value() {
436
10
    return D_->values_->items_[pos_];
437
10
  }
Unexecuted instantiation: _ZN8DictIterIP6BigStrPN10value_asdl7value_tEE5ValueEv
Unexecuted instantiation: _ZN8DictIterIP6BigStrPN12runtime_asdl7HayNodeEE5ValueEv
Unexecuted instantiation: _ZN8DictIterIlP6BigStrE5ValueEv
Unexecuted instantiation: _ZN8DictIterIP6BigStrS1_E5ValueEv
Unexecuted instantiation: _ZN8DictIterIP6BigStrPN12runtime_asdl4CellEE5ValueEv
438
439
 private:
440
  const Dict<K, V>* D_;
441
  int pos_;
442
};
443
444
// dict(mylist) converts a list of (k, v) tuples into a dict
445
template <typename K, typename V>
446
2
Dict<K, V>* dict(List<Tuple2<K, V>*>* l) {
447
2
  auto ret = Alloc<Dict<K, V>>();
448
2
  ret->reserve(len(l));
449
6
  for (ListIter<Tuple2<K, V>*> it(l); !it.Done(); it.Next()) {
450
4
    ret->set(it.Value()->at0(), it.Value()->at1());
451
4
  }
452
2
  return ret;
453
2
}
454
455
template <class K, class V>
456
2
void Dict<K, V>::update(List<Tuple2<K, V>*>* pairs) {
457
2
  reserve(len_ + len(pairs));
458
6
  for (ListIter<Tuple2<K, V>*> it(pairs); !it.Done(); it.Next()) {
459
4
    set(it.Value()->at0(), it.Value()->at1());
460
4
  }
461
2
}
462
463
template <class K, class V>
464
0
void Dict<K, V>::update(Dict<K, V>* other) {
465
0
  reserve(len_ + len(other));
466
0
  for (DictIter<K, V> it(other); !it.Done(); it.Next()) {
467
0
    set(it.Key(), it.Value());
468
0
  }
469
0
}
470
471
#endif  // MYCPP_GC_DICT_H