Use deferred release instead of hacky dontInvalidate logic
This commit is contained in:
@@ -1849,7 +1849,7 @@ void freeAndMakeCapacityAtLeast(Node *&self, int capacity,
|
|||||||
newSelf->copyChildrenAndKeyFrom(*self0);
|
newSelf->copyChildrenAndKeyFrom(*self0);
|
||||||
getInTree(self, impl) = newSelf;
|
getInTree(self, impl) = newSelf;
|
||||||
if (kUseFreeList) {
|
if (kUseFreeList) {
|
||||||
writeContext->release(self0);
|
writeContext->deferRelease(self0, newSelf);
|
||||||
} else {
|
} else {
|
||||||
removeNode(self0);
|
removeNode(self0);
|
||||||
safe_free(self0, self0->size());
|
safe_free(self0, self0->size());
|
||||||
@@ -1862,7 +1862,7 @@ void freeAndMakeCapacityAtLeast(Node *&self, int capacity,
|
|||||||
newSelf->copyChildrenAndKeyFrom(*self3);
|
newSelf->copyChildrenAndKeyFrom(*self3);
|
||||||
getInTree(self, impl) = newSelf;
|
getInTree(self, impl) = newSelf;
|
||||||
if (kUseFreeList) {
|
if (kUseFreeList) {
|
||||||
writeContext->release(self3);
|
writeContext->deferRelease(self3, newSelf);
|
||||||
} else {
|
} else {
|
||||||
removeNode(self3);
|
removeNode(self3);
|
||||||
safe_free(self3, self3->size());
|
safe_free(self3, self3->size());
|
||||||
@@ -1875,7 +1875,7 @@ void freeAndMakeCapacityAtLeast(Node *&self, int capacity,
|
|||||||
newSelf->copyChildrenAndKeyFrom(*self16);
|
newSelf->copyChildrenAndKeyFrom(*self16);
|
||||||
getInTree(self, impl) = newSelf;
|
getInTree(self, impl) = newSelf;
|
||||||
if (kUseFreeList) {
|
if (kUseFreeList) {
|
||||||
writeContext->release(self16);
|
writeContext->deferRelease(self16, newSelf);
|
||||||
} else {
|
} else {
|
||||||
removeNode(self16);
|
removeNode(self16);
|
||||||
safe_free(self16, self16->size());
|
safe_free(self16, self16->size());
|
||||||
@@ -1888,7 +1888,7 @@ void freeAndMakeCapacityAtLeast(Node *&self, int capacity,
|
|||||||
newSelf->copyChildrenAndKeyFrom(*self48);
|
newSelf->copyChildrenAndKeyFrom(*self48);
|
||||||
getInTree(self, impl) = newSelf;
|
getInTree(self, impl) = newSelf;
|
||||||
if (kUseFreeList) {
|
if (kUseFreeList) {
|
||||||
writeContext->release(self48);
|
writeContext->deferRelease(self48, newSelf);
|
||||||
} else {
|
} else {
|
||||||
removeNode(self48);
|
removeNode(self48);
|
||||||
safe_free(self48, self48->size());
|
safe_free(self48, self48->size());
|
||||||
@@ -1901,7 +1901,7 @@ void freeAndMakeCapacityAtLeast(Node *&self, int capacity,
|
|||||||
newSelf->copyChildrenAndKeyFrom(*self256);
|
newSelf->copyChildrenAndKeyFrom(*self256);
|
||||||
getInTree(self, impl) = newSelf;
|
getInTree(self, impl) = newSelf;
|
||||||
if (kUseFreeList) {
|
if (kUseFreeList) {
|
||||||
writeContext->release(self256);
|
writeContext->deferRelease(self256, newSelf);
|
||||||
} else {
|
} else {
|
||||||
removeNode(self256);
|
removeNode(self256);
|
||||||
safe_free(self256, self256->size());
|
safe_free(self256, self256->size());
|
||||||
@@ -1999,18 +1999,13 @@ void rezero(Node *n, InternalVersionT z) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void mergeWithChild(TaggedNodePointer &self, WriteContext *writeContext,
|
void mergeWithChild(TaggedNodePointer &self, WriteContext *writeContext,
|
||||||
ConflictSet::Impl *impl, Node *&dontInvalidate,
|
ConflictSet::Impl *impl, Node3 *self3) {
|
||||||
Node3 *self3) {
|
|
||||||
assert(!self3->entryPresent);
|
assert(!self3->entryPresent);
|
||||||
Node *child = self3->children[0];
|
Node *child = self3->children[0];
|
||||||
int minCapacity = self3->partialKeyLen + 1 + child->partialKeyLen;
|
int minCapacity = self3->partialKeyLen + 1 + child->partialKeyLen;
|
||||||
|
|
||||||
if (minCapacity > child->getCapacity()) {
|
if (minCapacity > child->getCapacity()) {
|
||||||
const bool update = child == dontInvalidate;
|
|
||||||
freeAndMakeCapacityAtLeast(child, minCapacity, writeContext, impl, true);
|
freeAndMakeCapacityAtLeast(child, minCapacity, writeContext, impl, true);
|
||||||
if (update) {
|
|
||||||
dontInvalidate = child;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge partial key with child
|
// Merge partial key with child
|
||||||
@@ -2037,7 +2032,7 @@ void mergeWithChild(TaggedNodePointer &self, WriteContext *writeContext,
|
|||||||
setMaxVersion(child, std::max(childMaxVersion, writeContext->zero));
|
setMaxVersion(child, std::max(childMaxVersion, writeContext->zero));
|
||||||
|
|
||||||
self = child;
|
self = child;
|
||||||
writeContext->release(self3);
|
writeContext->deferRelease(self3, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool needsDownsize(Node *n) {
|
bool needsDownsize(Node *n) {
|
||||||
@@ -2046,17 +2041,16 @@ bool needsDownsize(Node *n) {
|
|||||||
return n->numChildren + n->entryPresent < minTable[n->getType()];
|
return n->numChildren + n->entryPresent < minTable[n->getType()];
|
||||||
}
|
}
|
||||||
|
|
||||||
void downsize(Node3 *self, WriteContext *writeContext, ConflictSet::Impl *impl,
|
void downsize(Node3 *self, WriteContext *writeContext,
|
||||||
Node *&dontInvalidate) {
|
ConflictSet::Impl *impl) {
|
||||||
if (self->numChildren == 0) {
|
if (self->numChildren == 0) {
|
||||||
auto *newSelf = writeContext->allocate<Node0>(self->partialKeyLen);
|
auto *newSelf = writeContext->allocate<Node0>(self->partialKeyLen);
|
||||||
newSelf->copyChildrenAndKeyFrom(*self);
|
newSelf->copyChildrenAndKeyFrom(*self);
|
||||||
getInTree(self, impl) = newSelf;
|
getInTree(self, impl) = newSelf;
|
||||||
writeContext->release(self);
|
writeContext->deferRelease(self, newSelf);
|
||||||
} else {
|
} else {
|
||||||
assert(self->numChildren == 1 && !self->entryPresent);
|
assert(self->numChildren == 1 && !self->entryPresent);
|
||||||
mergeWithChild(getInTree(self, impl), writeContext, impl, dontInvalidate,
|
mergeWithChild(getInTree(self, impl), writeContext, impl, self);
|
||||||
self);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2066,7 +2060,7 @@ void downsize(Node16 *self, WriteContext *writeContext,
|
|||||||
auto *newSelf = writeContext->allocate<Node3>(self->partialKeyLen);
|
auto *newSelf = writeContext->allocate<Node3>(self->partialKeyLen);
|
||||||
newSelf->copyChildrenAndKeyFrom(*self);
|
newSelf->copyChildrenAndKeyFrom(*self);
|
||||||
getInTree(self, impl) = newSelf;
|
getInTree(self, impl) = newSelf;
|
||||||
writeContext->release(self);
|
writeContext->deferRelease(self, newSelf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void downsize(Node48 *self, WriteContext *writeContext,
|
void downsize(Node48 *self, WriteContext *writeContext,
|
||||||
@@ -2075,7 +2069,7 @@ void downsize(Node48 *self, WriteContext *writeContext,
|
|||||||
auto *newSelf = writeContext->allocate<Node16>(self->partialKeyLen);
|
auto *newSelf = writeContext->allocate<Node16>(self->partialKeyLen);
|
||||||
newSelf->copyChildrenAndKeyFrom(*self);
|
newSelf->copyChildrenAndKeyFrom(*self);
|
||||||
getInTree(self, impl) = newSelf;
|
getInTree(self, impl) = newSelf;
|
||||||
writeContext->release(self);
|
writeContext->deferRelease(self, newSelf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void downsize(Node256 *self, WriteContext *writeContext,
|
void downsize(Node256 *self, WriteContext *writeContext,
|
||||||
@@ -2085,17 +2079,16 @@ void downsize(Node256 *self, WriteContext *writeContext,
|
|||||||
auto *newSelf = writeContext->allocate<Node48>(self->partialKeyLen);
|
auto *newSelf = writeContext->allocate<Node48>(self->partialKeyLen);
|
||||||
newSelf->copyChildrenAndKeyFrom(*self256);
|
newSelf->copyChildrenAndKeyFrom(*self256);
|
||||||
getInTree(self, impl) = newSelf;
|
getInTree(self, impl) = newSelf;
|
||||||
writeContext->release(self256);
|
writeContext->deferRelease(self256, newSelf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void downsize(Node *self, WriteContext *writeContext, ConflictSet::Impl *impl,
|
void downsize(Node *self, WriteContext *writeContext, ConflictSet::Impl *impl) {
|
||||||
Node *&dontInvalidate) {
|
|
||||||
|
|
||||||
switch (self->getType()) {
|
switch (self->getType()) {
|
||||||
case Type_Node0: // GCOVR_EXCL_LINE
|
case Type_Node0: // GCOVR_EXCL_LINE
|
||||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||||
case Type_Node3:
|
case Type_Node3:
|
||||||
downsize(static_cast<Node3 *>(self), writeContext, impl, dontInvalidate);
|
downsize(static_cast<Node3 *>(self), writeContext, impl);
|
||||||
break;
|
break;
|
||||||
case Type_Node16:
|
case Type_Node16:
|
||||||
downsize(static_cast<Node16 *>(self), writeContext, impl);
|
downsize(static_cast<Node16 *>(self), writeContext, impl);
|
||||||
@@ -2135,7 +2128,12 @@ Node *erase(Node *self, WriteContext *writeContext, ConflictSet::Impl *impl,
|
|||||||
|
|
||||||
if (self->numChildren != 0) {
|
if (self->numChildren != 0) {
|
||||||
if (needsDownsize(self)) {
|
if (needsDownsize(self)) {
|
||||||
downsize(self, writeContext, impl, result);
|
downsize(self, writeContext, impl);
|
||||||
|
}
|
||||||
|
if (result != nullptr) {
|
||||||
|
while (result->releaseDeferred) {
|
||||||
|
result = result->forwardTo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -2158,7 +2156,7 @@ Node *erase(Node *self, WriteContext *writeContext, ConflictSet::Impl *impl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (needsDownsize(parent3)) {
|
if (needsDownsize(parent3)) {
|
||||||
downsize(parent3, writeContext, impl, result);
|
downsize(parent3, writeContext, impl);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case Type_Node16: {
|
case Type_Node16: {
|
||||||
@@ -2173,7 +2171,7 @@ Node *erase(Node *self, WriteContext *writeContext, ConflictSet::Impl *impl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (needsDownsize(parent16)) {
|
if (needsDownsize(parent16)) {
|
||||||
downsize(parent16, writeContext, impl, result);
|
downsize(parent16, writeContext, impl);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case Type_Node48: {
|
case Type_Node48: {
|
||||||
@@ -2201,7 +2199,7 @@ Node *erase(Node *self, WriteContext *writeContext, ConflictSet::Impl *impl,
|
|||||||
parent48->childMaxVersion[lastChildrenIndex] = writeContext->zero;
|
parent48->childMaxVersion[lastChildrenIndex] = writeContext->zero;
|
||||||
|
|
||||||
if (needsDownsize(parent48)) {
|
if (needsDownsize(parent48)) {
|
||||||
downsize(parent48, writeContext, impl, result);
|
downsize(parent48, writeContext, impl);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case Type_Node256: {
|
case Type_Node256: {
|
||||||
@@ -2212,13 +2210,18 @@ Node *erase(Node *self, WriteContext *writeContext, ConflictSet::Impl *impl,
|
|||||||
--parent->numChildren;
|
--parent->numChildren;
|
||||||
|
|
||||||
if (needsDownsize(parent256)) {
|
if (needsDownsize(parent256)) {
|
||||||
downsize(parent256, writeContext, impl, result);
|
downsize(parent256, writeContext, impl);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
default: // GCOVR_EXCL_LINE
|
default: // GCOVR_EXCL_LINE
|
||||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result != nullptr) {
|
||||||
|
while (result->releaseDeferred) {
|
||||||
|
result = result->forwardTo;
|
||||||
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5102,6 +5105,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
|||||||
n = nextPhysical(n);
|
n = nextPhysical(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
writeContext.releaseDeferred();
|
||||||
gc_iterations_total.add(set_oldest_iterations_accum);
|
gc_iterations_total.add(set_oldest_iterations_accum);
|
||||||
if (n == nullptr) {
|
if (n == nullptr) {
|
||||||
removalKey = {};
|
removalKey = {};
|
||||||
|
Reference in New Issue
Block a user