re PR libstdc++/80721 (Sorting/Merging of free EH-emergency buffer may wrong or uncom...
authorRichard Biener <rguenther@suse.de>
Fri, 2 Jun 2017 08:10:48 +0000 (08:10 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 2 Jun 2017 08:10:48 +0000 (08:10 +0000)
2017-06-02  Richard Biener  <rguenther@suse.de>
Markus Eisenmann  <meisenmann.lba@fh-salzburg.ac.at>

PR libstdc++/80721
* libsupc++/eh_alloc.cc (pool::free): Keep list properly
sorted and add missing freelist item merging cases.

Co-Authored-By: Markus Eisenmann <meisenmann.lba@fh-salzburg.ac.at>
From-SVN: r248816

libstdc++-v3/ChangeLog
libstdc++-v3/libsupc++/eh_alloc.cc

index dbbba5a17cb09784afeaa8360f2cdf004f328a1c..d347561534c931222cc52325b0a3c13b6069c2b5 100644 (file)
@@ -1,3 +1,10 @@
+2017-06-02  Richard Biener  <rguenther@suse.de>
+       Markus Eisenmann  <meisenmann.lba@fh-salzburg.ac.at>
+
+       PR libstdc++/80721
+       * libsupc++/eh_alloc.cc (pool::free): Keep list properly
+       sorted and add missing freelist item merging cases.
+
 2017-06-01  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        (GLIBCXX_CROSSCONFIG): Handle *-solaris* like *-linux* etc.
index d03cbcef9b0f24181b5b645973fc9b18be364e1f..4b38f98845ae972c2fac14a99f66ba707f784b6b 100644 (file)
@@ -162,7 +162,7 @@ namespace
       allocated_entry *x;
       if ((*e)->size - size >= sizeof (free_entry))
        {
-         // Slit block if it is too large.
+         // Split block if it is too large.
          free_entry *f = reinterpret_cast <free_entry *>
              (reinterpret_cast <char *> (*e) + size);
          std::size_t sz = (*e)->size;
@@ -194,13 +194,17 @@ namespace
       allocated_entry *e = reinterpret_cast <allocated_entry *>
        (reinterpret_cast <char *> (data) - offsetof (allocated_entry, data));
       std::size_t sz = e->size;
-      if (!first_free_entry)
+      if (!first_free_entry
+         || (reinterpret_cast <char *> (e) + sz
+             < reinterpret_cast <char *> (first_free_entry)))
        {
-         // If the free list is empty just put the entry there.
+         // If the free list is empty or the entry is before the
+         // first element and cannot be merged with it add it as
+         // the first free entry.
          free_entry *f = reinterpret_cast <free_entry *> (e);
          new (f) free_entry;
          f->size = sz;
-         f->next = NULL;
+         f->next = first_free_entry;
          first_free_entry = f;
        }
       else if (reinterpret_cast <char *> (e) + sz
@@ -224,9 +228,17 @@ namespace
                   > reinterpret_cast <char *> (e) + sz);
               fe = &(*fe)->next)
            ;
+         // If we can merge the next block into us do so and continue
+         // with the cases below.
+         if (reinterpret_cast <char *> (e) + sz
+             == reinterpret_cast <char *> ((*fe)->next))
+           {
+             sz += (*fe)->next->size;
+             (*fe)->next = (*fe)->next->next;
+           }
          if (reinterpret_cast <char *> (*fe) + (*fe)->size
              == reinterpret_cast <char *> (e))
-           /* Merge with the freelist entry.  */
+           // Merge with the freelist entry.
            (*fe)->size += sz;
          else
            {