<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>