Initialize version sooner in VersionedMap::begin
This commit is contained in:
4
Facade.h
4
Facade.h
@@ -138,12 +138,16 @@ struct Facade {
|
|||||||
String(m.param2, m.param2Len);
|
String(m.param2, m.param2Len);
|
||||||
break;
|
break;
|
||||||
case weaselab::VersionedMap::Clear:
|
case weaselab::VersionedMap::Clear:
|
||||||
|
if (m.param2Len == 0) {
|
||||||
|
unversioned.erase(String(m.param1, m.param1Len));
|
||||||
|
} else {
|
||||||
for (auto unversionedIter =
|
for (auto unversionedIter =
|
||||||
unversioned.lower_bound(String(m.param1, m.param1Len));
|
unversioned.lower_bound(String(m.param1, m.param1Len));
|
||||||
unversionedIter != unversioned.end() &&
|
unversionedIter != unversioned.end() &&
|
||||||
unversionedIter->first < String(m.param2, m.param2Len);) {
|
unversionedIter->first < String(m.param2, m.param2Len);) {
|
||||||
unversionedIter = unversioned.erase(unversionedIter);
|
unversionedIter = unversioned.erase(unversionedIter);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
#include "Internal.h"
|
#include "Internal.h"
|
||||||
#include "KeyCompare.h"
|
#include "KeyCompare.h"
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
@@ -81,10 +82,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|||||||
case 1: {
|
case 1: {
|
||||||
// Set oldest version
|
// Set oldest version
|
||||||
|
|
||||||
facade.setOldestVersion(facade.getOldestVersion() +
|
const int64_t newOldestVersion =
|
||||||
gArbitrary.bounded(facade.getVersion() -
|
|
||||||
facade.getOldestVersion() +
|
facade.getOldestVersion() +
|
||||||
1));
|
gArbitrary.bounded(facade.getVersion() - facade.getOldestVersion() +
|
||||||
|
1);
|
||||||
|
|
||||||
|
facade.setOldestVersion(newOldestVersion);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case 2: {
|
case 2: {
|
||||||
// Check range read
|
// Check range read
|
||||||
|
@@ -123,6 +123,11 @@ struct RootSet::Impl {
|
|||||||
firstToFree = firstToFree->next;
|
firstToFree = firstToFree->next;
|
||||||
safe_free(tmp, ThreadSafeHandle::Impl::sizeForCapacity(tmp->capacity));
|
safe_free(tmp, ThreadSafeHandle::Impl::sizeForCapacity(tmp->capacity));
|
||||||
}
|
}
|
||||||
|
#ifndef NDEBUG
|
||||||
|
assert(rootCount() > 0);
|
||||||
|
auto *h = handle.load(std::memory_order_relaxed);
|
||||||
|
assert(h->versions()[h->lastLeq(oldestVersion)] <= oldestVersion);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t *roots() const {
|
const uint32_t *roots() const {
|
||||||
|
@@ -262,62 +262,49 @@ struct MemManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void gc(const uint32_t *roots, int numRoots, int64_t oldestVersion) {
|
void gc(const uint32_t *roots, int numRoots, int64_t oldestVersion) {
|
||||||
#if DEBUG_VERBOSE
|
|
||||||
if (debugVerboseEnabled) {
|
|
||||||
printf("GC roots:\n");
|
|
||||||
for (int i = 0; i < numRoots; ++i) {
|
|
||||||
printf(" %u\n", roots[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// Calculate reachable set
|
// Calculate reachable set
|
||||||
BitSet reachable{next};
|
BitSet reachable{next};
|
||||||
// Each node has at most 3 children and nodes along the search path aren't
|
// Each node has at most 3 children and nodes along the search path aren't
|
||||||
// in the stack, so we need 2 * kPathLengthUpperBound
|
// in the stack, so we need 2 * kPathLengthUpperBound
|
||||||
uint32_t stack[2 * kPathLengthUpperBound];
|
uint32_t stack[2 * kPathLengthUpperBound];
|
||||||
int stackIndex = 0;
|
int stackIndex = 0;
|
||||||
auto tryPush = [&](uint32_t p) {
|
auto tryPush = [&](uint32_t parent, uint32_t child) {
|
||||||
|
if (!reachable.set(child)) {
|
||||||
#if DEBUG_VERBOSE
|
#if DEBUG_VERBOSE
|
||||||
if (debugVerboseEnabled) {
|
if (debugVerboseEnabled) {
|
||||||
printf(" GC: visit: %u\n", p);
|
printf(" GC: reach: %u (parent %u)\n", child, parent);
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (!reachable.set(p)) {
|
|
||||||
#if DEBUG_VERBOSE
|
|
||||||
if (debugVerboseEnabled) {
|
|
||||||
printf(" GC: push on to stack: %u\n", p);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
assert(stackIndex < sizeof(stack) / sizeof(stack[0]));
|
assert(stackIndex < sizeof(stack) / sizeof(stack[0]));
|
||||||
stack[stackIndex++] = p;
|
stack[stackIndex++] = child;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
for (int i = 0; i < numRoots; ++i) {
|
for (int i = 0; i < numRoots; ++i) {
|
||||||
if (roots[i] == 0) {
|
if (roots[i] == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
tryPush(roots[i]);
|
tryPush(0, roots[i]);
|
||||||
while (stackIndex > 0) {
|
while (stackIndex > 0) {
|
||||||
uint32_t p = stack[--stackIndex];
|
uint32_t p = stack[--stackIndex];
|
||||||
auto &node = base[p];
|
auto &node = base[p];
|
||||||
if (node.updated.load(std::memory_order_relaxed)) {
|
if (node.updated.load(std::memory_order_relaxed)) {
|
||||||
if (node.pointer[!node.replacedPointer] != 0) {
|
if (node.pointer[!node.replacedPointer] != 0) {
|
||||||
tryPush(node.pointer[!node.replacedPointer]);
|
tryPush(p, node.pointer[!node.replacedPointer]);
|
||||||
}
|
}
|
||||||
if (oldestVersion < node.updateVersion) {
|
if (oldestVersion < node.updateVersion) {
|
||||||
if (node.pointer[node.replacedPointer] != 0) {
|
if (node.pointer[node.replacedPointer] != 0) {
|
||||||
tryPush(node.pointer[node.replacedPointer]);
|
tryPush(p, node.pointer[node.replacedPointer]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (node.pointer[2] != 0) {
|
if (node.pointer[2] != 0) {
|
||||||
tryPush(node.pointer[2]);
|
tryPush(p, node.pointer[2]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (node.pointer[0] != 0) {
|
if (node.pointer[0] != 0) {
|
||||||
tryPush(node.pointer[0]);
|
tryPush(p, node.pointer[0]);
|
||||||
}
|
}
|
||||||
if (node.pointer[1] != 0) {
|
if (node.pointer[1] != 0) {
|
||||||
tryPush(node.pointer[1]);
|
tryPush(p, node.pointer[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -495,6 +482,11 @@ struct __attribute__((__visibility__("hidden"))) VersionedMap::Impl {
|
|||||||
result = n.pointer[which];
|
result = n.pointer[which];
|
||||||
}
|
}
|
||||||
assert(result == 0 || result >= kMinAddressable);
|
assert(result == 0 || result >= kMinAddressable);
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if (result != 0) {
|
||||||
|
assert(mm.base[result].entry != nullptr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1174,6 +1166,7 @@ void VersionedMap::firstGeq(const Key *key, const int64_t *version,
|
|||||||
VersionedMap::Iterator VersionedMap::begin(int64_t version) const {
|
VersionedMap::Iterator VersionedMap::begin(int64_t version) const {
|
||||||
VersionedMap::Iterator result;
|
VersionedMap::Iterator result;
|
||||||
result.impl = new (safe_malloc(sizeof(Iterator::Impl))) Iterator::Impl();
|
result.impl = new (safe_malloc(sizeof(Iterator::Impl))) Iterator::Impl();
|
||||||
|
result.impl->version = version;
|
||||||
|
|
||||||
bool ignored;
|
bool ignored;
|
||||||
result.impl->finger.push(
|
result.impl->finger.push(
|
||||||
@@ -1205,7 +1198,6 @@ VersionedMap::Iterator VersionedMap::begin(int64_t version) const {
|
|||||||
}
|
}
|
||||||
result.impl->mutationIndex = 0;
|
result.impl->mutationIndex = 0;
|
||||||
|
|
||||||
result.impl->version = version;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user