On Wed, Jan 9, 2019 at 5:05 AM Pavel Labath <pa...@labath.sk> wrote:

> On 08/01/2019 21:57, Jonas Devlieghere wrote:
> > Before I got around to coding this up I realized you can't take the
> > address of constructors in C++, so the function address won't work as an
> > identifier.
> >
> You gave up way too easily. :P

I counted on you having something in mind, it sounded too obvious for you
to have missed.  ;-)

I realized that constructors are going to be tricky, but I didn't want
> to dive into those details until I knew if you liked the general idea.
> The most important thing to realize here is that for the identifier
> thingy to work, you don't actually need to use the address of that
> method/constructor as the identifier. It is sufficient to have something
> that can be deterministically computed from the function. Then you can
> use the address of *that* as the identifier.

I was thinking about that yesterday. I still feel like it would be better
to have this mapping all done at compile time. I was considering some kind
of constexpr hashing but that sounded overkill.

> I've created a very simple prototype <https://godbolt.org/z/_xDt5r>,
> where I do just that. The way I handle constructors there is that I
> create a special class template (construct), whose instantiations are
> going to be unique for each constructor (I achieve that by making the
> class name and the constructor argument types the template parameters of
> that function). Then I can take the address of the static member
> function inside this class (&construct<class, arguments...>::doit), and
> use *that* as the ID.


As a nice side-effect, the "doit" method actually does invoke the
> constructor in question, so I can also use that in the replay code to
> treat constructors like any other method that returns an object.

This is really neat.

> I also do the same thing for (non-static) member functions via the
> "invoke" template, because even though it is possible to take the
> address of those, it is very hard to do anything else with the retrieved
> pointer. So the effect of this that in the rest of the code, I only have
> to work with free functions, as both constructors and member functions
> are converted into equivalent free functions. I haven't tried to handle
> destructors yet, but I don't think those should pose any problems that
> we haven't encountered already.
> The example also show how you can use templates to automatically
> generate replay code for "simple" (i.e. those where you can
> (de)serialize each argument independently) functions, and then uses that
> to record/replay a very simple API.
> You can see it in action like this:
> $ g++ a.cc  # compile
> $ ./a.out 2>/tmp/recording # generate the recording
> SBFoo 47 42
> Method 1 2
> Static 10 11
> $ cat /tmp/recording
> 0  # ID of the constructor
> 47 # constructor arg 1
> 42 # constructor arg 2
> 0x7ffd74d9a0f7 # constructor result
> 1  # id of SBFoo::Method
> 0x7ffd74d9a0f7 # this
> 1  # arg 1
> 2  # arg 2
> 2  # id of SBFoo::Static
> 10 # arg 1
> 11 # arg 2
> $ ./a.out 1 < /tmp/recording # replay the recording
> SBFoo 47 42
> SBFoo 42 47
> Method 1 2
> Static 10 11
> Note that when replaying the SBFoo constructor is called twice. This is
> because this code does not attempt to track the object instances in any
> way... it just creates a new one each time. This obviously needs to be
> fixed, but that's independent of the function ID issue.
> hope you find that useful,
> pl

Definitely, thank you for taking the time to code up a prototype.

lldb-dev mailing list

Reply via email to