diff options
-rw-r--r-- | lib/scudo/standalone/allocator_config.h | 4 | ||||
-rw-r--r-- | lib/scudo/standalone/combined.h | 33 | ||||
-rw-r--r-- | lib/scudo/standalone/size_class_map.h | 6 | ||||
-rw-r--r-- | lib/scudo/standalone/tests/combined_test.cpp | 15 | ||||
-rw-r--r-- | lib/scudo/standalone/tests/wrappers_c_test.cpp | 1 |
5 files changed, 44 insertions, 15 deletions
diff --git a/lib/scudo/standalone/allocator_config.h b/lib/scudo/standalone/allocator_config.h index 06ec4f3f7..62c6f2875 100644 --- a/lib/scudo/standalone/allocator_config.h +++ b/lib/scudo/standalone/allocator_config.h @@ -53,8 +53,8 @@ struct AndroidSvelteConfig { // 512MB regions typedef SizeClassAllocator64<SizeClassMap, 29U> Primary; #else - // 256KB regions - typedef SizeClassAllocator32<SizeClassMap, 18U> Primary; + // 64KB regions + typedef SizeClassAllocator32<SizeClassMap, 16U> Primary; #endif template <class A> using TSDRegistryT = TSDRegistrySharedT<A, 1U>; // Shared, only 1 TSD. diff --git a/lib/scudo/standalone/combined.h b/lib/scudo/standalone/combined.h index 05a4ebcdf..b2dc25f78 100644 --- a/lib/scudo/standalone/combined.h +++ b/lib/scudo/standalone/combined.h @@ -311,18 +311,30 @@ public: OldHeader.Origin, Chunk::Origin::Malloc); } - const uptr OldSize = getSize(OldPtr, &OldHeader); - // If the new size is identical to the old one, or lower but within an - // acceptable range, we just keep the old chunk, and update its header. - if (UNLIKELY(NewSize == OldSize)) - return OldPtr; - if (NewSize < OldSize) { - const uptr Delta = OldSize - NewSize; - if (Delta < (SizeClassMap::MaxSize / 2)) { + void *BlockBegin = getBlockBegin(OldPtr, &OldHeader); + uptr BlockEnd; + uptr OldSize; + const uptr ClassId = OldHeader.ClassId; + if (LIKELY(ClassId)) { + BlockEnd = reinterpret_cast<uptr>(BlockBegin) + + SizeClassMap::getSizeByClassId(ClassId); + OldSize = OldHeader.SizeOrUnusedBytes; + } else { + BlockEnd = SecondaryT::getBlockEnd(BlockBegin); + OldSize = BlockEnd - + (reinterpret_cast<uptr>(OldPtr) + OldHeader.SizeOrUnusedBytes); + } + // If the new chunk still fits in the previously allocated block (with a + // reasonable delta), we just keep the old block, and update the chunk + // header to reflect the size change. + if (reinterpret_cast<uptr>(OldPtr) + NewSize <= BlockEnd) { + const uptr Delta = + OldSize < NewSize ? NewSize - OldSize : OldSize - NewSize; + if (Delta <= SizeClassMap::MaxSize / 2) { Chunk::UnpackedHeader NewHeader = OldHeader; NewHeader.SizeOrUnusedBytes = - (OldHeader.ClassId ? NewHeader.SizeOrUnusedBytes - Delta - : NewHeader.SizeOrUnusedBytes + Delta) & + (ClassId ? NewSize + : BlockEnd - (reinterpret_cast<uptr>(OldPtr) + NewSize)) & Chunk::SizeOrUnusedBytesMask; Chunk::compareExchangeHeader(Cookie, OldPtr, &NewHeader, &OldHeader); return OldPtr; @@ -335,6 +347,7 @@ public: // are currently unclear. void *NewPtr = allocate(NewSize, Chunk::Origin::Malloc, Alignment); if (NewPtr) { + const uptr OldSize = getSize(OldPtr, &OldHeader); memcpy(NewPtr, OldPtr, Min(NewSize, OldSize)); quarantineOrDeallocateChunk(OldPtr, &OldHeader, OldSize); } diff --git a/lib/scudo/standalone/size_class_map.h b/lib/scudo/standalone/size_class_map.h index fa52e6d9b..3b494afb3 100644 --- a/lib/scudo/standalone/size_class_map.h +++ b/lib/scudo/standalone/size_class_map.h @@ -137,11 +137,11 @@ typedef SizeClassMap<3, 5, 8, 17, 8, 10> DefaultSizeClassMap; // TODO(kostyak): further tune class maps for Android & Fuchsia. #if SCUDO_WORDSIZE == 64U -typedef SizeClassMap<3, 5, 8, 15, 8, 10> SvelteSizeClassMap; +typedef SizeClassMap<4, 4, 8, 14, 4, 10> SvelteSizeClassMap; typedef SizeClassMap<3, 5, 8, 17, 14, 14> AndroidSizeClassMap; #else -typedef SizeClassMap<3, 4, 7, 15, 8, 10> SvelteSizeClassMap; -typedef SizeClassMap<3, 4, 7, 17, 14, 14> AndroidSizeClassMap; +typedef SizeClassMap<4, 3, 7, 14, 5, 10> SvelteSizeClassMap; +typedef SizeClassMap<3, 5, 8, 17, 14, 14> AndroidSizeClassMap; #endif } // namespace scudo diff --git a/lib/scudo/standalone/tests/combined_test.cpp b/lib/scudo/standalone/tests/combined_test.cpp index c8801f955..c9c65690a 100644 --- a/lib/scudo/standalone/tests/combined_test.cpp +++ b/lib/scudo/standalone/tests/combined_test.cpp @@ -97,6 +97,21 @@ template <class Config> static void testAllocator() { } Allocator->deallocate(P, Origin); + // Check that reallocating a chunk to a slightly smaller or larger size + // returns the same chunk. This requires that all the sizes we iterate on use + // the same block size, but that should be the case for 2048 with our default + // class size maps. + P = Allocator->allocate(DataSize, Origin); + memset(P, Marker, DataSize); + for (scudo::sptr Delta = -32; Delta < 32; Delta += 8) { + const scudo::uptr NewSize = DataSize + Delta; + void *NewP = Allocator->reallocate(P, NewSize); + EXPECT_EQ(NewP, P); + for (scudo::uptr I = 0; I < scudo::Min(DataSize, NewSize); I++) + EXPECT_EQ((reinterpret_cast<char *>(NewP))[I], Marker); + } + Allocator->deallocate(P, Origin); + // Allocates a bunch of chunks, then iterate over all the chunks, ensuring // they are the ones we allocated. This requires the allocator to not have any // other allocated chunk at this point (eg: won't work with the Quarantine). diff --git a/lib/scudo/standalone/tests/wrappers_c_test.cpp b/lib/scudo/standalone/tests/wrappers_c_test.cpp index 6d6bbbf61..28c21ebc8 100644 --- a/lib/scudo/standalone/tests/wrappers_c_test.cpp +++ b/lib/scudo/standalone/tests/wrappers_c_test.cpp @@ -12,6 +12,7 @@ #include <limits.h> #include <malloc.h> +#include <stdlib.h> #include <unistd.h> extern "C" { |