[PATCH] D48889: [demangler] Ensure proper alignment in BumpPointerAllocator

Serge Pavlov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 3 11:51:02 PDT 2018


sepavloff created this revision.
sepavloff added a reviewer: erik.pilkington.

This change slightly modifies algorithm of `BumpPointerAllocator` so that it
provides alignment of allocated memory blocks in runtime without specific
compiler support. It allows getting rid of the specifier `alignas(16)` in the
declaration of `BumpPointerAllocator::InitialBuffer`. Object of the class
`BumpPointerAllocator` is created as a part of another object allocated in heap,
so this specifier actually cannot guarantee proper alignment. Microsoft
compiler emits a warning in this case.

It fixes https://bugs.llvm.org/show_bug.cgi?id=37944.


Repository:
  rL LLVM

https://reviews.llvm.org/D48889

Files:
  lib/Demangle/ItaniumDemangle.cpp


Index: lib/Demangle/ItaniumDemangle.cpp
===================================================================
--- lib/Demangle/ItaniumDemangle.cpp
+++ lib/Demangle/ItaniumDemangle.cpp
@@ -1945,40 +1945,53 @@
   struct BlockMeta {
     BlockMeta* Next;
     size_t Current;
+
+    BlockMeta(BlockMeta *N) : Next(N),
+      Current(Alignment -
+              (reinterpret_cast<size_t>(this + 1) & (Alignment - 1))) { }
+    void *getTail() { return reinterpret_cast<char*>(this + 1) + Current; }
   };
 
+  static constexpr size_t Alignment = 16;
   static constexpr size_t AllocSize = 4096;
-  static constexpr size_t UsableAllocSize = AllocSize - sizeof(BlockMeta);
+  static constexpr size_t UsableAllocSize = AllocSize - sizeof(BlockMeta) -
+                                            Alignment;
 
-  alignas(16) char InitialBuffer[AllocSize];
+  char InitialBuffer[AllocSize];
   BlockMeta* BlockList = nullptr;
 
   void grow() {
     char* NewMeta = new char[AllocSize];
-    BlockList = new (NewMeta) BlockMeta{BlockList, 0};
+    BlockList = new (NewMeta) BlockMeta(BlockList);
   }
 
   void* allocateMassive(size_t NBytes) {
-    NBytes += sizeof(BlockMeta);
-    BlockMeta* NewMeta = reinterpret_cast<BlockMeta*>(new char[NBytes]);
-    BlockList->Next = new (NewMeta) BlockMeta{BlockList->Next, 0};
-    return static_cast<void*>(NewMeta + 1);
+    size_t AllocSz = NBytes + sizeof(BlockMeta) + Alignment;
+    char *Mem = new char[AllocSz];
+    BlockList->Next = new (Mem) BlockMeta(BlockList->Next);
+    void *Result = BlockList->getTail();
+    BlockList->Current += NBytes;
+    return Result;
+  }
+
+  static constexpr size_t getAlignedSize(size_t Sz) {
+    return (Sz + (Alignment - 1)) & ~(Alignment - 1);
   }
 
 public:
   BumpPointerAllocator()
-      : BlockList(new (InitialBuffer) BlockMeta{nullptr, 0}) {}
+      : BlockList(new (InitialBuffer) BlockMeta(nullptr)) {}
 
   void* allocate(size_t N) {
-    N = (N + 15u) & ~15u;
+    N = getAlignedSize(N);
     if (N + BlockList->Current >= UsableAllocSize) {
       if (N > UsableAllocSize)
         return allocateMassive(N);
       grow();
     }
+    void *Result = BlockList->getTail();
     BlockList->Current += N;
-    return static_cast<void*>(reinterpret_cast<char*>(BlockList + 1) +
-                              BlockList->Current - N);
+    return Result;
   }
 
   void reset() {
@@ -1988,7 +2001,7 @@
       if (reinterpret_cast<char*>(Tmp) != InitialBuffer)
         delete[] reinterpret_cast<char*>(Tmp);
     }
-    BlockList = new (InitialBuffer) BlockMeta{nullptr, 0};
+    BlockList = new (InitialBuffer) BlockMeta(nullptr);
   }
 
   ~BumpPointerAllocator() { reset(); }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D48889.153949.patch
Type: text/x-patch
Size: 2671 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180703/e24aed4b/attachment.bin>


More information about the llvm-commits mailing list