[PATCH] Intercept allocation to skim allocated types

Douglas Gregor dgregor at apple.com
Thu Jan 31 10:53:54 PST 2013


On Jan 31, 2013, at 9:22 AM, Dai MIKURUBE <dmikurube at acm.org> wrote:

> Thank you for the comments, John and Richard.
> 
> At first, I don't stick to this design and implementation (I'm saying not to make misunderstanding).  I'd just like to solve the following problem.
> 
> 1) Capture allocated types of as most objects as possible.
> 2) No need to change almost all the existing code.  Just adding some code.
> 3) Capture objects allocated by both global and in-class operator new.  (Many projects naturally have many in-class operator new.)
> 4) Capture objects allocated by placement new.  (Placement new is used for malloc() memory allocation in some projects.)
> 5) Actually, capturing object deallocation is less required for our purpose.  (But, it's more required in general.)
> 
> If we can solve this problem in another better way, I'm so positive to switch to the way.  Do you have any ideas?  It's useless without (3) and (4) as I discussed in the previous comment and the document.
> 

John has sketched out of potential scheme:

	Perhaps it would be better to replace operator new, record return addresses, and then somehow map those back to source code?

Basically, the idea here is to associate the type of a particular "new" expression with the address at which the call to operator new occurs (DWARF does this sort of thing), so when we're emitting IR for

	new A

the type of A is associated with the address of the associated call instruction. 

Then, you replace operator new with whatever function interposition approach is right for your platform (LD_PRELOAD, DYLD_INSERT_LIBRARIES, whatever). The replacement operator new sniffs out its return address, then matches that up with the corresponding call site to get type information. If it can't find the type information (because the call site wasn't compiled with it), at least you're still catching the allocation.

There are several advantages to John's suggestion over your current approach. For one, it requires no changes to semantic analysis or the AST, so turning this feature on isn't going to change the meaning of your source code, and the implementation can be limited to Clang's lowering + some work on the LLVM side. Second, the type information can be recorded off to the side (e.g., like DWARF exception tables), so they don't have an impact on how the code executes. Because of this and the fact that one can interpose operator new/operator delete at run time, it means that one could emit this information as part of the build and then decide at run time whether to interpose or not, so it becomes just another debugging/profiling aid that one could generate with the rest of the debug info.

	- Doug

> 
> 2013/1/31 Richard Smith <richard at metafoo.co.uk>
> On Wed, Jan 30, 2013 at 10:27 AM, John McCall <rjmccall at apple.com> wrote:
> > On Jan 30, 2013, at 2:42 AM, Dai MIKURUBE <dmikurube at acm.org> wrote:
> >>  Hello, what do you think about it, John and Richard?
> >
> > To be frank, the more I look at it, the more this seems like a very questionable language extension.  It adds a lot of linguistic and implementation complexity to some already-quite-complex parts of the language and implementation, all to benefit the approximately 0% of users that will know about and enable the feature.
> >
> I agree that it's complex.  (It's the reason why we still welcome other ideas.)
> 
> > My understanding is that you'd just like to be able to track what types are being allocated.  Perhaps it would be better to replace operator new, record return addresses, and then somehow map those back to source code?
> 
> I may not understand your idea well, but does it apply for in-class operator new effectively?  ( == Don't we need to add another operator new for *every* in-class operator new?)  I think it's the way we've already tried.  In-class new is the main reason why we chose intercepting as discussed in the doc.
> 
> 
> My biggest concern here is that this extension won't do what you want,
> and won't be helpful for anyone else either. That's because it assumes
> that new and delete expressions are paired, which is simply false
> (even for a leak-free program), because it instruments placement new
> and class-specific operator new/delete. For instance:
> 
>   {
>     char buffer[4];
>     new (&buffer) int;
>     // no corresponding operator delete call
>   }
> 
> This will be overwhelmingly common within containers.
> 
> Yeah, that's a problem.  That's the point that I said "to be a good piece to profile each project in its customized way" above.
> 
> For example in Chromium and WebKit, we chose to get together with malloc's memory profiling.  We count only intercepted objects whose addresses are allocated by malloc.
> 
> Since the intercepting functions can be implemented for each project, developers can use it as a piece of their own profiling.
> 
> If you were suggesting a mechanism to implicitly pass a type_info
> object to a global operator new, and to prefer that operator new in
> overload resolution, I think I would find that simple and useful
> enough to support. But the proposed approach does not seem generally
> useful.
> I guess it has the same issue as above.  Does it apply for in-class operator new?  (If I understand your idea correctly, we've already tried it.)
> 
> -- 
> Dai MIKURUBE
>    dmikurube at acm.org




More information about the cfe-commits mailing list