<div dir="ltr"><div class="gmail_default" style><br></div><div class="gmail_default" style>This triggers an assert: </div><div class="gmail_default" style>==12750== AddressSanitizer CHECK failed: compiler-rt/lib/asan/asan_allocator2.cc:82 "((sizeof(AllocatorCache))) <= ((sizeof(ms->allocator2_cache)))" (0x61610, 0x2000)<br>
</div><div dir="ltr"><div class="gmail_extra"><br><br>--kcc <br><br><div class="gmail_quote">On Tue, Jan 15, 2013 at 1:02 PM, Dmitry Vyukov <span dir="ltr"><<a href="mailto:dvyukov@google.com" target="_blank">dvyukov@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: dvyukov<br>
Date: Tue Jan 15 03:02:20 2013<br>
New Revision: 172521<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=172521&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=172521&view=rev</a><br>
Log:<br>
asan: faster thead-local cache for memory allocator<br>
<br>
Modified:<br>
compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.h<br>
<br>
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.h?rev=172521&r1=172520&r2=172521&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.h?rev=172521&r1=172520&r2=172521&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.h (original)<br>
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.h Tue Jan 15 03:02:20 2013<br>
@@ -65,7 +65,7 @@<br>
// c32 => s: 512 diff: +32 06% l 9 cached: 64 32768; id 32<br>
<br>
<br>
-template <uptr kMaxSizeLog, uptr kMaxNumCached, uptr kMaxBytesCachedLog,<br>
+template <uptr kMaxSizeLog, uptr kMaxNumCachedT, uptr kMaxBytesCachedLog,<br>
uptr kMinBatchClassT><br>
class SizeClassMap {<br>
static const uptr kMinSizeLog = 3;<br>
@@ -77,6 +77,7 @@<br>
static const uptr M = (1 << S) - 1;<br>
<br>
public:<br>
+ static const uptr kMaxNumCached = kMaxNumCachedT;<br>
struct TransferBatch {<br>
TransferBatch *next;<br>
uptr count;<br>
@@ -598,6 +599,7 @@<br>
uptr size = SizeClassMap::Size(class_id);<br>
uptr reg = AllocateRegion(class_id);<br>
uptr n_chunks = kRegionSize / (size + kMetadataSize);<br>
+ uptr max_count = SizeClassMap::MaxCached(class_id);<br>
Batch *b = 0;<br>
for (uptr i = reg; i < reg + n_chunks * size; i += size) {<br>
if (b == 0) {<br>
@@ -608,7 +610,7 @@<br>
b->count = 0;<br>
}<br>
b->batch[b->count++] = (void*)i;<br>
- if (b->count == SizeClassMap::MaxCached(class_id)) {<br>
+ if (b->count == max_count) {<br>
sci->free_list.push_back(b);<br>
b = 0;<br>
}<br>
@@ -631,6 +633,7 @@<br>
struct SizeClassAllocatorLocalCache {<br>
typedef SizeClassAllocator Allocator;<br>
static const uptr kNumClasses = SizeClassAllocator::kNumClasses;<br>
+<br>
// Don't need to call Init if the object is a global (i.e. zero-initialized).<br>
void Init() {<br>
internal_memset(this, 0, sizeof(*this));<br>
@@ -640,18 +643,10 @@<br>
CHECK_NE(class_id, 0UL);<br>
CHECK_LT(class_id, kNumClasses);<br>
PerClass *c = &per_class_[class_id];<br>
- if (c->cur == 0) {<br>
- DCHECK_EQ(c->old, 0);<br>
- c->cur = allocator->AllocateBatch(this, class_id);<br>
- }<br>
- DCHECK_GT(c->cur->count, 0);<br>
- void *res = c->cur->batch[--c->cur->count];<br>
- if (c->cur->count == 0) {<br>
- if (class_id < SizeClassMap::kMinBatchClass)<br>
- Deallocate(allocator, SizeClassMap::ClassID(sizeof(Batch)), c->cur);<br>
- c->cur = c->old;<br>
- c->old = 0;<br>
- }<br>
+ if (UNLIKELY(c->count == 0))<br>
+ Refill(allocator, class_id);<br>
+ void *res = c->batch[--c->count];<br>
+ PREFETCH(c->batch[c->count - 1]);<br>
return res;<br>
}<br>
<br>
@@ -659,31 +654,16 @@<br>
CHECK_NE(class_id, 0UL);<br>
CHECK_LT(class_id, kNumClasses);<br>
PerClass *c = &per_class_[class_id];<br>
- if (c->cur == 0 || c->cur->count == SizeClassMap::MaxCached(class_id)) {<br>
- if (c->old)<br>
- allocator->DeallocateBatch(class_id, c->old);<br>
- c->old = c->cur;<br>
- if (class_id < SizeClassMap::kMinBatchClass)<br>
- c->cur = (Batch*)Allocate(allocator,<br>
- SizeClassMap::ClassID(sizeof(Batch)));<br>
- else<br>
- c->cur = (Batch*)p;<br>
- c->cur->count = 0;<br>
- }<br>
- c->cur->batch[c->cur->count++] = p;<br>
+ if (UNLIKELY(c->count == c->max_count))<br>
+ Drain(allocator, class_id);<br>
+ c->batch[c->count++] = p;<br>
}<br>
<br>
void Drain(SizeClassAllocator *allocator) {<br>
- for (uptr i = 0; i < kNumClasses; i++) {<br>
- PerClass *c = &per_class_[i];<br>
- if (c->cur) {<br>
- allocator->DeallocateBatch(i, c->cur);<br>
- c->cur = 0;<br>
- }<br>
- if (c->old) {<br>
- allocator->DeallocateBatch(i, c->old);<br>
- c->old = 0;<br>
- }<br>
+ for (uptr class_id = 0; class_id < kNumClasses; class_id++) {<br>
+ PerClass *c = &per_class_[class_id];<br>
+ while (c->count > 0)<br>
+ Drain(allocator, class_id);<br>
}<br>
}<br>
<br>
@@ -691,10 +671,49 @@<br>
typedef typename SizeClassAllocator::SizeClassMapT SizeClassMap;<br>
typedef typename SizeClassMap::TransferBatch Batch;<br>
struct PerClass {<br>
- Batch *cur;<br>
- Batch *old;<br>
+ uptr count;<br>
+ uptr max_count;<br>
+ void *batch[2 * SizeClassMap::kMaxNumCached];<br>
};<br>
PerClass per_class_[kNumClasses];<br>
+<br>
+ void InitCache() {<br>
+ if (per_class_[0].max_count)<br>
+ return;<br>
+ for (uptr i = 0; i < kNumClasses; i++) {<br>
+ PerClass *c = &per_class_[i];<br>
+ c->max_count = 2 * SizeClassMap::MaxCached(i);<br>
+ }<br>
+ }<br>
+<br>
+ void NOINLINE Refill(SizeClassAllocator *allocator, uptr class_id) {<br>
+ InitCache();<br>
+ PerClass *c = &per_class_[class_id];<br>
+ Batch *b = allocator->AllocateBatch(this, class_id);<br>
+ for (uptr i = 0; i < b->count; i++)<br>
+ c->batch[i] = b->batch[i];<br>
+ c->count = b->count;<br>
+ if (class_id < SizeClassMap::kMinBatchClass)<br>
+ Deallocate(allocator, SizeClassMap::ClassID(sizeof(Batch)), b);<br>
+ }<br>
+<br>
+ void NOINLINE Drain(SizeClassAllocator *allocator, uptr class_id) {<br>
+ InitCache();<br>
+ PerClass *c = &per_class_[class_id];<br>
+ Batch *b;<br>
+ if (class_id < SizeClassMap::kMinBatchClass)<br>
+ b = (Batch*)Allocate(allocator, SizeClassMap::ClassID(sizeof(Batch)));<br>
+ else<br>
+ b = (Batch*)c->batch[0];<br>
+ uptr cnt = Min(c->max_count / 2, c->count);<br>
+ for (uptr i = 0; i < cnt; i++) {<br>
+ b->batch[i] = c->batch[i];<br>
+ c->batch[i] = c->batch[i + c->max_count / 2];<br>
+ }<br>
+ b->count = cnt;<br>
+ c->count -= cnt;<br>
+ allocator->DeallocateBatch(class_id, b);<br>
+ }<br>
};<br>
<br>
// This class can (de)allocate only large chunks of memory using mmap/unmap.<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div></div>