diff --git a/flow/Arena.cpp b/flow/Arena.cpp index dcdaa39ee2..16908dbefd 100644 --- a/flow/Arena.cpp +++ b/flow/Arena.cpp @@ -118,14 +118,14 @@ Arena::Arena(Arena&& r) noexcept = default; Arena& Arena::operator=(const Arena& r) = default; Arena& Arena::operator=(Arena&& r) noexcept = default; void Arena::dependsOn(const Arena& p) { - if (p.impl) { + // x.dependsOn(y) is a no-op if they refer to the same ArenaBlocks. + // They will already have the same lifetime. + if (p.impl && p.impl.getPtr() != impl.getPtr()) { allowAccess(impl.getPtr()); allowAccess(p.impl.getPtr()); ArenaBlock::dependOn(impl, p.impl.getPtr()); disallowAccess(p.impl.getPtr()); - if (p.impl.getPtr() != impl.getPtr()) { - disallowAccess(impl.getPtr()); - } + disallowAccess(impl.getPtr()); } } @@ -297,6 +297,7 @@ void* ArenaBlock::make4kAlignedBuffer(uint32_t size) { } void ArenaBlock::dependOn(Reference& self, ArenaBlock* other) { + ASSERT(self->getData() != other->getData()); other->addref(); if (!self || self->isTiny() || self->unused() < sizeof(ArenaBlockRef)) create(SMALL, self)->makeReference(other); @@ -775,6 +776,16 @@ TEST_CASE("/flow/Arena/Size") { return Void(); } +// Test that x.dependsOn(x) works, and is effectively a no-op. +TEST_CASE("/flow/Arena/SelfRef") { + Arena a(4096); + + // This should be a no-op. + a.dependsOn(a); + + return Void(); +} + TEST_CASE("flow/StringRef/eat") { StringRef str = "test/case"_sr; StringRef first = str.eat("/"); @@ -815,4 +826,4 @@ TEST_CASE("flow/StringRef/eat") { ASSERT(str == ""_sr); return Void(); -} \ No newline at end of file +}