isl_*_list_add: do not modify lists in-place
authorSven Verdoolaege <skimo@kotnet.org>
Wed, 25 Sep 2013 10:38:33 +0000 (25 12:38 +0200)
committerSven Verdoolaege <skimo@kotnet.org>
Fri, 18 Oct 2013 12:53:50 +0000 (18 14:53 +0200)
isl_*_list_add calls isl_*_list_grow to ensure that there is room
for at least one more element and then directly modifies the
returned list.  If the original list was large enough already, then
isl_*_list_grow will simply return this list, even if there
is more than one reference to the list, resulting in
isl_*_list_add also modifying the other references to the original list.

We could just add a call to isl_*_list_cow in isl_*_list_add,
but that could result in the list getting copied twices.
Instead, we make sure that isl_*_list_grow always returns
a list with a single reference.

Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
isl_list_templ.c

index 71024ce..5d8d794 100644 (file)
@@ -89,6 +89,7 @@ __isl_give LIST(EL) *FN(LIST(EL),cow)(__isl_take LIST(EL) *list)
 }
 
 /* Make sure "list" has room for at least "n" more pieces.
+ * Always return a list with a single reference.
  *
  * If there is only one reference to list, we extend it in place.
  * Otherwise, we create a new LIST(EL) and copy the elements.
@@ -101,7 +102,7 @@ static __isl_give LIST(EL) *FN(LIST(EL),grow)(__isl_take LIST(EL) *list, int n)
 
        if (!list)
                return NULL;
-       if (list->n + n <= list->size)
+       if (list->ref == 1 && list->n + n <= list->size)
                return list;
 
        ctx = FN(LIST(EL),get_ctx)(list);
@@ -115,6 +116,9 @@ static __isl_give LIST(EL) *FN(LIST(EL),grow)(__isl_take LIST(EL) *list, int n)
                return res;
        }
 
+       if (list->n + n <= list->size && list->size < new_size)
+               new_size = list->size;
+
        res = FN(LIST(EL),alloc)(ctx, new_size);
        if (!res)
                return FN(LIST(EL),free)(list);