diff --git a/compiler-rt/lib/scudo/standalone/local_cache.h b/compiler-rt/lib/scudo/standalone/local_cache.h --- a/compiler-rt/lib/scudo/standalone/local_cache.h +++ b/compiler-rt/lib/scudo/standalone/local_cache.h @@ -122,8 +122,16 @@ } TransferBatch *createBatch(uptr ClassId, void *B) { - if (ClassId != BatchClassId) + if (ClassId != BatchClassId) { B = allocate(BatchClassId); + const uptr BatchSize = SizeClassAllocator::getSizeByClassId(BatchClassId); + // We don't want to track allocated/free'd stats of transfer batches. + // Specializing or branching in allocate() based on `ClassId != + // BatchClassId` ends up trashing the icache for a very hot function, and + // so we just undo the changes to the stats back here in the slow path. + Stats.sub(StatAllocated, BatchSize); + Stats.add(StatFree, BatchSize); + } return reinterpret_cast(B); } @@ -159,8 +167,16 @@ } void destroyBatch(uptr ClassId, void *B) { - if (ClassId != BatchClassId) + if (ClassId != BatchClassId) { deallocate(BatchClassId, B); + const uptr BatchSize = SizeClassAllocator::getSizeByClassId(BatchClassId); + // We don't want to track allocated/free'd stats of transfer batches. + // Specializing or branching in deallocate() based on `ClassId != + // BatchClassId` ends up trashing the icache for a very hot function, and + // so we just undo the changes to the stats back here in the slow path. + Stats.add(StatAllocated, BatchSize); + Stats.sub(StatFree, BatchSize); + } } NOINLINE bool refill(PerClass *C, uptr ClassId) {