On Thu, 6 Feb 2014, Jan Hubicka wrote:
> Hi,
> I did some memory measurements for Firefox. We seems in shape in exception of
> linemaps that takes about 20% of memory and I also noticed that we produce a
> lot
> of garbage by copy_tree_r. Analyzing the reasons for copy_tree_r I found two
> about
> equally important. The first one is that gimple_get_virt_method_for_vtable
> lookup
> virtual method via fold_ctor_reference and this eventually calls unshare_expr
> on
> the resulting value (that is ADDR_EXPR of FUNCTION_DECL). We make copy of
> ADDR_EXPR
> and immediately throw it away in gimple_get_virt_method_for_vtable and care
> only about the decl.
>
> I always considered it stupid to do linear walk of fields here, when we can do
> just simple O(1) lookup, but considered it SEP. This patch implements that.
> The constructors are fully controlled by frontend (we verify that it is vtable
> by DECL_VIRTUAL flag first), so I think it is safe to use special purpose
> lookup
> code.
>
> Bootstrapped/regtested x86_64-linux, OK?
Ok.
Thanks,
Richard.
> Honza
>
> * gimple-fold.c (gimple_get_virt_method_for_vtable): Rewrite
> constructor lookup to be O(1).
> Index: gimple-fold.c
> ===================================================================
> --- gimple-fold.c (revision 207523)
> +++ gimple-fold.c (working copy)
> @@ -3179,6 +3180,8 @@ gimple_get_virt_method_for_vtable (HOST_
> {
> tree vtable = v, init, fn;
> unsigned HOST_WIDE_INT size;
> + unsigned HOST_WIDE_INT elt_size, access_index;
> + tree domain_type;
>
> /* First of all double check we have virtual table. */
> if (TREE_CODE (v) != VAR_DECL
> @@ -3202,10 +3205,30 @@ gimple_get_virt_method_for_vtable (HOST_
> offset *= BITS_PER_UNIT;
> offset += token * size;
>
> - /* Do not pass from_decl here, we want to know even about values we can
> - not use and will check can_refer_decl_in_current_unit_p ourselves. */
> - fn = fold_ctor_reference (TREE_TYPE (TREE_TYPE (v)), init,
> - offset, size, NULL);
> + /* Lookup the value in the constructor that is assumed to be array.
> + This is equivalent to
> + fn = fold_ctor_reference (TREE_TYPE (TREE_TYPE (v)), init,
> + offset, size, NULL);
> + but in a constant time. We expect that frontend produced a simple
> + array without indexed initializers. */
> +
> + gcc_checking_assert (TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE);
> + domain_type = TYPE_DOMAIN (TREE_TYPE (init));
> + gcc_checking_assert (integer_zerop (TYPE_MIN_VALUE (domain_type)));
> + elt_size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (init))));
> +
> + access_index = offset / BITS_PER_UNIT / elt_size;
> + gcc_checking_assert (offset % (elt_size * BITS_PER_UNIT) == 0);
> +
> + /* This code makes an assumption that there are no
> + indexed fileds produced by C++ FE, so we can directly index the array.
> */
> + if (access_index < CONSTRUCTOR_NELTS (init))
> + {
> + fn = CONSTRUCTOR_ELT (init, access_index)->value;
> + gcc_checking_assert (!CONSTRUCTOR_ELT (init, access_index)->index);
> + }
> + else
> + fn = NULL;
>
> /* For type inconsistent program we may end up looking up virtual method
> in virtual table that does not contain TOKEN entries. We may overrun
>
>
--
Richard Biener <[email protected]>
SUSE / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746
GF: Jeff Hawn, Jennifer Guild, Felix Imend"orffer