gallium/util: Break recursion in pipe_resource_reference
authorMichel Dänzer <michel.daenzer@amd.com>
Tue, 13 Jun 2017 03:02:59 +0000 (12:02 +0900)
committerMichel Dänzer <michel@daenzer.net>
Thu, 15 Jun 2017 02:24:59 +0000 (11:24 +0900)
It calling itself recursively prevented it from being inlined, resulting
in a copy being generated in every compilation unit referencing it. This
bloated the text segment of the Gallium mega-driver *_dri.so by ~4%,
and might also have impacted performance.

Fixes: ecd6fce2611e ("mesa/st: support lowering multi-planar YUV")
v2:
* Add comment above pipe_resource_next_reference [Samuel Pitoiset]
v3:
* Use loop to unreference the full chain of resources referenced via
  the next members [Timothy Arceri]
v4:
* Stop chasing ->next chain at the first sub-resource which isn't
  destroyed [Nicolai Hähnle]

Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/gallium/auxiliary/util/u_inlines.h

index 6a3d5043cf20f46d702e9ca7c7add0d284cb1df8..4fc683a57451ab6b5792c880a2a3f51fe6607db1 100644 (file)
@@ -137,8 +137,14 @@ pipe_resource_reference(struct pipe_resource **ptr, struct pipe_resource *tex)
 
    if (pipe_reference_described(&(*ptr)->reference, &tex->reference, 
                                 (debug_reference_descriptor)debug_describe_resource)) {
-      pipe_resource_reference(&old_tex->next, NULL);
-      old_tex->screen->resource_destroy(old_tex->screen, old_tex);
+      /* Avoid recursion, which would prevent inlining this function */
+      do {
+         struct pipe_resource *next = old_tex->next;
+
+         old_tex->screen->resource_destroy(old_tex->screen, old_tex);
+         old_tex = next;
+      } while (pipe_reference_described(&old_tex->reference, NULL,
+                                        (debug_reference_descriptor)debug_describe_resource));
    }
    *ptr = tex;
 }