This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC] Marking C++ new operator as malloc?


On 9/9/07, Mark Mitchell <mark@codesourcery.com> wrote:
> Richard Guenther wrote:
>
> >> Probably the most common use of a custom new is to allocate memory from
> >> a user-controlled pool instead of the standard free store. Somewhere in
> >> the program there will be a pointer to the complete pool, which aliases
> >> every pointer returned by that version of new. Any such pool-based new
> >> doesn't meet the requirements of the malloc attribute.
> >
> > That doesn't matter.  What matters is object lifetime, which is properly
> > preserved by a conforming pool allocator.
>
> We have some terminology issues here.  The definition of the malloc
> attribute is:
>
> > The `malloc' attribute is used to tell the compiler that a function
> >      may be treated as if any non-`NULL' pointer it returns cannot
> >      alias any other pointer valid when the function returns.  This
> >      will often improve optimization.
>
> The term "cannot alias" is not fully defined.  It could mean "cannot
> have the same value as any other pointer of the same type".  It could
> mean "cannot have the same value as any other pointer, when both
> pointers are cast to `void *'".  It could mean, a la "restrict", that
> "no store through an expression based on this pointer can modify the
> value read from via any expression based on any other pointer".

It actually means that all accesses based on the returned pointer do
not alias accesses based on other pointers that are not derived.  In
particular,

  int *p;
  int * __attribute__((malloc)) my_malloc() { return p; }

  void foo(void)
  {
    int *q = my_malloc();
    *p = 1;
    *q = 0;
    return *p;
  }

will be optimized to return 1 if my_malloc is not inlined and 0 otherwise.

> In the case of "malloc", and assuming that all of the machinery for
> malloc is hidden away in some piece of the program we're not talking
> about, all three definitions apply.  Each pointer returned by malloc is
> an island unto itself; there's no conforming way to get there except by
> using the pointer just returned.
>
> For, operator new, the same is true -- but we're more often able to see
> the machinery for the allocator.  For example:
>
> char pool[N];
> size_t next;
>
> /* Never mind that the return memory isn't properly aligned here;
>    fixing the implementation is left to the reader.  */
> void *operator new(size_t s) {
>    void *p = pool + next;
>    next += s;
>    return p;
> }
>
> bool f() {
>   char *c = new char;
>   return (c == pool);
> }
>
> Now, I don't think we should allow the compiler to optimize the return
> statement in "f" to "return false"?  If operator new has attribute
> malloc, then it may in fact do so -- even though the value returned
> might be "pool" itself.

Yes, at least the first case would give different results based on inlining
decisions.  But only for undefined cases I believe.

> The same issue occurs if you call malloc from within the file that
> defines malloc; the malloc attribute is saying something about what you
> can do *if you cannot see the pool out of which the allocation is
> occurring*.  For malloc, which is fully squirreled away in libc
> somewhere, this is probably safe in practice -- until LTO.

Which brings back the fact that you cannot implement malloc in C
(you certainly remember the discussions about C++ placement new
handling wrt aliasing).  To re-use the machinery we invented there
we would need to place a CHANGE_DYNAMIC_TYPE_EXPR for
the pointer assignment resulting from inlining a function with
attribute malloc set.  As you say, unless we are inlining such functions
we are safe in practice.

> For operator
> new, it's a little dicier, since people do tend more often to replace it
> in their own programs, and to put those replacements in inline functions
> in header files where the compiler is liable to see more about what's
> going on.
>
> This seems like a useful optimization to me, and I understand that it
> will work 99.99% of the time, and it's in the spirit of the standard --
> but how do we actually make it safe?  If the attribute only applied to
> other values returned from the same function, then it would be safe --
> but less useful.  Can we do better?

See above - inlining an allocator function produces the need to change
the dynamic type of the pointed-to memory as we are basically exposing
a "placement new" operation to the optimizers.

Richard.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]