Skip to content

Commit 5444b2c

Browse files
committed
[reactor] Improve storage adapters
1 parent b5d80bc commit 5444b2c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1191
-939
lines changed
Lines changed: 312 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
1+
#ifndef KLEE_FIXEDSIZESTORAGEADAPTER_H
2+
#define KLEE_FIXEDSIZESTORAGEADAPTER_H
3+
4+
#ifndef IMMER_NO_EXCEPTIONS
5+
#define IMMER_NO_EXCEPTIONS
6+
#endif /* IMMER_NO_EXCEPTIONS */
7+
8+
#include <immer/vector.hpp>
9+
#include <immer/vector_transient.hpp>
10+
11+
#include <cstddef>
12+
#include <vector>
13+
14+
namespace llvm {
15+
class raw_ostream;
16+
};
17+
18+
namespace klee {
19+
20+
enum class FixedSizeStorageIteratorKind { Array, Vector, PersistentVector };
21+
22+
template <typename ValueType> struct VectorAdapterIterator {
23+
using storage_ty = std::vector<ValueType>;
24+
using value_ty = ValueType;
25+
typename storage_ty::const_iterator it;
26+
VectorAdapterIterator(typename storage_ty::const_iterator it) : it(it) {}
27+
VectorAdapterIterator &operator++() {
28+
++it;
29+
return *this;
30+
}
31+
value_ty operator*() { return *it; }
32+
bool operator!=(const VectorAdapterIterator &other) const {
33+
return other.it != it;
34+
}
35+
};
36+
37+
template <typename ValueType> struct PersistentVectorAdapterIterator {
38+
using storage_ty = immer::vector_transient<ValueType>;
39+
using value_ty = ValueType;
40+
typename storage_ty::iterator it;
41+
PersistentVectorAdapterIterator(typename storage_ty::iterator it) : it(it) {}
42+
PersistentVectorAdapterIterator &operator++() {
43+
++it;
44+
return *this;
45+
}
46+
value_ty operator*() { return *it; }
47+
bool operator!=(const PersistentVectorAdapterIterator &other) const {
48+
return other.it != it;
49+
}
50+
};
51+
52+
template <typename ValueType> struct ArrayAdapterIterator {
53+
using storage_ty = ValueType *;
54+
using value_ty = ValueType;
55+
storage_ty it;
56+
57+
public:
58+
ArrayAdapterIterator(storage_ty it) : it(it) {}
59+
ArrayAdapterIterator &operator++() {
60+
++it;
61+
return *this;
62+
}
63+
value_ty operator*() { return *it; }
64+
bool operator!=(const ArrayAdapterIterator &other) const {
65+
return other.it != it;
66+
}
67+
};
68+
69+
template <typename ValueType> union FixedSizeStorageIterator {
70+
VectorAdapterIterator<ValueType> vaIt;
71+
PersistentVectorAdapterIterator<ValueType> pvaIt;
72+
ArrayAdapterIterator<ValueType> aaIt;
73+
~FixedSizeStorageIterator() {}
74+
FixedSizeStorageIterator(const VectorAdapterIterator<ValueType> &other)
75+
: vaIt(other) {}
76+
FixedSizeStorageIterator(
77+
const PersistentVectorAdapterIterator<ValueType> &other)
78+
: pvaIt(other) {}
79+
FixedSizeStorageIterator(const ArrayAdapterIterator<ValueType> &other)
80+
: aaIt(other) {}
81+
};
82+
83+
template <typename ValueType> struct FixedSizeStorageAdapter {
84+
using value_ty = ValueType;
85+
class iterator {
86+
FixedSizeStorageIteratorKind kind;
87+
FixedSizeStorageIterator<ValueType> impl;
88+
89+
public:
90+
iterator(const VectorAdapterIterator<ValueType> &impl)
91+
: kind(FixedSizeStorageIteratorKind::Vector), impl(impl) {}
92+
iterator(const PersistentVectorAdapterIterator<ValueType> &impl)
93+
: kind(FixedSizeStorageIteratorKind::PersistentVector), impl(impl) {}
94+
iterator(const ArrayAdapterIterator<ValueType> &impl)
95+
: kind(FixedSizeStorageIteratorKind::Array), impl(impl) {}
96+
iterator(iterator const &right) : kind(right.kind) {
97+
switch (kind) {
98+
case klee::FixedSizeStorageIteratorKind::Vector: {
99+
impl.vaIt = right.impl.vaIt;
100+
break;
101+
}
102+
case klee::FixedSizeStorageIteratorKind::PersistentVector: {
103+
impl.pvaIt = right.impl.pvaIt;
104+
break;
105+
}
106+
case klee::FixedSizeStorageIteratorKind::Array: {
107+
impl.aaIt = right.impl.aaIt;
108+
break;
109+
}
110+
default:
111+
assert(0 && "unhandled iterator kind");
112+
}
113+
}
114+
~iterator() {
115+
switch (kind) {
116+
case klee::FixedSizeStorageIteratorKind::Vector: {
117+
impl.vaIt.~VectorAdapterIterator();
118+
break;
119+
}
120+
case klee::FixedSizeStorageIteratorKind::PersistentVector: {
121+
impl.pvaIt.~PersistentVectorAdapterIterator();
122+
break;
123+
}
124+
case klee::FixedSizeStorageIteratorKind::Array: {
125+
impl.aaIt.~ArrayAdapterIterator();
126+
break;
127+
}
128+
default:
129+
assert(0 && "unhandled iterator kind");
130+
}
131+
}
132+
133+
// forward operators to virtual calls through impl.
134+
iterator &operator++() {
135+
switch (kind) {
136+
case klee::FixedSizeStorageIteratorKind::Vector: {
137+
++impl.vaIt;
138+
break;
139+
}
140+
case klee::FixedSizeStorageIteratorKind::PersistentVector: {
141+
++impl.pvaIt;
142+
break;
143+
}
144+
case klee::FixedSizeStorageIteratorKind::Array: {
145+
++impl.aaIt;
146+
break;
147+
}
148+
default:
149+
assert(0 && "unhandled iterator kind");
150+
}
151+
return *this;
152+
}
153+
value_ty operator*() {
154+
switch (kind) {
155+
case klee::FixedSizeStorageIteratorKind::Vector: {
156+
return *impl.vaIt;
157+
}
158+
case klee::FixedSizeStorageIteratorKind::PersistentVector: {
159+
return *impl.pvaIt;
160+
}
161+
case klee::FixedSizeStorageIteratorKind::Array: {
162+
return *impl.aaIt;
163+
}
164+
default:
165+
assert(0 && "unhandled iterator kind");
166+
}
167+
}
168+
bool operator!=(const iterator &other) const {
169+
switch (kind) {
170+
case klee::FixedSizeStorageIteratorKind::Vector: {
171+
return impl.vaIt != other.impl.vaIt;
172+
}
173+
case klee::FixedSizeStorageIteratorKind::PersistentVector: {
174+
return impl.pvaIt != other.impl.pvaIt;
175+
}
176+
case klee::FixedSizeStorageIteratorKind::Array: {
177+
return impl.aaIt != other.impl.aaIt;
178+
}
179+
default:
180+
assert(0 && "unhandled iterator kind");
181+
}
182+
}
183+
};
184+
185+
virtual ~FixedSizeStorageAdapter() = default;
186+
virtual iterator begin() const = 0;
187+
virtual iterator end() const = 0;
188+
virtual bool empty() const = 0;
189+
virtual void set(size_t key, const ValueType &value) = 0;
190+
virtual const value_ty &at(size_t key) const = 0;
191+
virtual size_t size() const = 0;
192+
virtual FixedSizeStorageAdapter<ValueType> *clone() const = 0;
193+
const value_ty &operator[](const size_t &index) const { return at(index); }
194+
};
195+
196+
template <typename ValueType>
197+
struct VectorAdapter : public FixedSizeStorageAdapter<ValueType> {
198+
public:
199+
using storage_ty = std::vector<ValueType>;
200+
using base_ty = FixedSizeStorageAdapter<ValueType>;
201+
using iterator = typename base_ty::iterator;
202+
203+
VectorAdapter(size_t storageSize) { storage = storage_ty(storageSize); }
204+
VectorAdapter(const VectorAdapter<ValueType> &va) : storage(va.storage) {}
205+
storage_ty storage;
206+
iterator begin() const override {
207+
return iterator(VectorAdapterIterator<ValueType>(storage.begin()));
208+
}
209+
iterator end() const override {
210+
return iterator(VectorAdapterIterator<ValueType>(storage.end()));
211+
}
212+
bool empty() const override { return storage.empty(); }
213+
void set(size_t key, const ValueType &value) override {
214+
storage[key] = value;
215+
}
216+
const ValueType &at(size_t key) const override { return storage.at(key); }
217+
size_t size() const override { return storage.size(); }
218+
FixedSizeStorageAdapter<ValueType> *clone() const override {
219+
return new VectorAdapter<ValueType>(*this);
220+
}
221+
};
222+
223+
template <typename ValueType>
224+
struct PersistentVectorAdapter : public FixedSizeStorageAdapter<ValueType> {
225+
public:
226+
using storage_ty = immer::vector_transient<ValueType>;
227+
using storage_persistent_ty = immer::vector<ValueType>;
228+
using base_ty = FixedSizeStorageAdapter<ValueType>;
229+
using iterator = typename base_ty::iterator;
230+
231+
PersistentVectorAdapter(size_t storageSize) {
232+
storage = storage_persistent_ty(storageSize).transient();
233+
}
234+
PersistentVectorAdapter(const PersistentVectorAdapter<ValueType> &va)
235+
: storage(va.storage.persistent().transient()) {}
236+
PersistentVectorAdapter &operator=(const PersistentVectorAdapter &b) {
237+
storage = b.storage.persistent().transient();
238+
return *this;
239+
}
240+
mutable storage_ty storage;
241+
iterator begin() const override {
242+
return iterator(
243+
PersistentVectorAdapterIterator<ValueType>(storage.begin()));
244+
}
245+
iterator end() const override {
246+
return iterator(PersistentVectorAdapterIterator<ValueType>(storage.end()));
247+
}
248+
bool empty() const override { return storage.empty(); }
249+
void set(size_t key, const ValueType &value) override {
250+
storage.set(key, value);
251+
}
252+
const ValueType &at(size_t key) const override { return storage.at(key); }
253+
size_t size() const override { return storage.size(); }
254+
FixedSizeStorageAdapter<ValueType> *clone() const override {
255+
return new PersistentVectorAdapter<ValueType>(*this);
256+
}
257+
};
258+
259+
template <typename ValueType>
260+
struct ArrayAdapter : public FixedSizeStorageAdapter<ValueType> {
261+
using storage_ty = ValueType *;
262+
using base_ty = FixedSizeStorageAdapter<ValueType>;
263+
using iterator = typename base_ty::iterator;
264+
265+
storage_ty storage;
266+
size_t storageSize;
267+
ArrayAdapter(size_t storageSize) : storageSize(storageSize) {
268+
storage = new ValueType[storageSize];
269+
clear();
270+
}
271+
ArrayAdapter(const ArrayAdapter<ValueType> &pa)
272+
: storageSize(pa.storageSize) {
273+
storage = new ValueType[storageSize];
274+
for (size_t i = 0; i < storageSize; ++i) {
275+
set(i, pa.at(i));
276+
}
277+
}
278+
ArrayAdapter &operator=(const ArrayAdapter<ValueType> &pa) {
279+
storageSize = pa.storageSize;
280+
delete[] storage;
281+
storage = new ValueType[storageSize];
282+
for (size_t i = 0; i < storageSize; ++i) {
283+
set(i, pa.at(i));
284+
}
285+
return *this;
286+
}
287+
~ArrayAdapter() override { delete[] storage; }
288+
iterator begin() const override {
289+
return ArrayAdapterIterator<ValueType>(storage);
290+
}
291+
iterator end() const override {
292+
return ArrayAdapterIterator<ValueType>(storage + storageSize);
293+
}
294+
bool empty() const override { return storageSize == 0; }
295+
void set(size_t key, const ValueType &value) override {
296+
storage[key] = value;
297+
}
298+
const ValueType &at(size_t key) const override { return storage[key]; }
299+
void clear() {
300+
for (size_t i = 0; i < storageSize; ++i) {
301+
set(i, ValueType());
302+
}
303+
}
304+
size_t size() const override { return storageSize; }
305+
FixedSizeStorageAdapter<ValueType> *clone() const override {
306+
return new ArrayAdapter<ValueType>(*this);
307+
}
308+
};
309+
310+
} // namespace klee
311+
312+
#endif

include/klee/ADT/KTest.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#ifndef KLEE_KTEST_H
1111
#define KLEE_KTEST_H
1212

13-
#include <stddef.h>
1413
#include <stdint.h>
1514

1615
#ifdef __cplusplus

include/klee/ADT/PersistentHashMap.h

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,33 @@
1515
#endif /* IMMER_NO_EXCEPTIONS */
1616

1717
#include <immer/map.hpp>
18+
#include <immer/map_transient.hpp>
1819

1920
namespace klee {
2021

2122
template <class K, class D, class HASH = std::hash<K>,
2223
class EQUAL = std::equal_to<K>>
2324
class PersistentHashMap {
2425
public:
25-
typedef immer::map<K, D, HASH, EQUAL> Map;
26+
typedef immer::map_transient<K, D, HASH, EQUAL> Map;
2627
typedef typename Map::iterator iterator;
2728
typedef K key_type;
2829
typedef std::pair<K, D> value_type;
2930

3031
private:
31-
Map elts;
32+
mutable Map elts;
3233

33-
PersistentHashMap(const Map &b) : elts(b) {}
34+
PersistentHashMap(const Map &b) : elts(b.persistent().transient()) {}
3435

3536
public:
36-
PersistentHashMap() {}
37-
PersistentHashMap(const PersistentHashMap &b) : elts(b.elts) {}
38-
~PersistentHashMap() {}
37+
PersistentHashMap() = default;
38+
PersistentHashMap(const PersistentHashMap &b) {
39+
elts = b.elts.persistent().transient();
40+
}
41+
~PersistentHashMap() = default;
3942

4043
PersistentHashMap &operator=(const PersistentHashMap &b) {
41-
elts = b.elts;
44+
elts = b.elts.persistent().transient();
4245
return *this;
4346
}
4447
bool operator==(const PersistentHashMap &b) const { return elts == b.elts; }
@@ -51,29 +54,17 @@ class PersistentHashMap {
5154

5255
void insert(const value_type &value) {
5356
if (!lookup(value.first)) {
54-
elts = elts.insert(value);
57+
elts.insert(value);
5558
}
5659
}
57-
void replace(const value_type &value) { elts = elts.insert(value); }
58-
void remove(const key_type &key) { elts = elts.erase(key); }
60+
void replace(const value_type &value) { elts.insert(value); }
61+
void remove(const key_type &key) { elts.erase(key); }
5962

6063
iterator begin() const { return elts.begin(); }
6164
iterator end() const { return elts.end(); }
6265

63-
const D &operator[](const key_type &key) {
64-
return elts[key];
65-
// auto value = lookup(key);
66-
// if (value) {
67-
// return *value;
68-
// } else {
69-
// value_type defVal;
70-
// defVal.first = key;
71-
// insert(defVal);
72-
// return *lookup(key);
73-
// }
74-
}
75-
7666
const D &at(const key_type &key) const { return elts.at(key); }
67+
const D &operator[](const key_type &key) { return at(key); }
7768

7869
void clear() { elts = Map(); }
7970
};

0 commit comments

Comments
 (0)