This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB 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: how to handle mutable types in varobj?


On 12/29/2011 11:10 AM, Joel Brobecker wrote:
I'd like to discuss how mutable types should be handled in varobj.

It turns out to be a little simpler than I thought, assuming my understanding of the GDB/MI varobj interface is right:

If a varobj mutated, whether a root varobj or not, it should be
listed in the change list as a "type_changed".  However, all its
children varobjs are simply destroyed without further ado, and
they will not be listed in the change list. This means that we
expect the front-end to understand that children varobjs of
a varobj that has mutated are invalid, and thus automatically
destroyed.

With the attached prototype, this is what I get.

(1) First, creating the varobj and listing its children:

   | -var-create v * v
   | ^done,name="v",numchild="4",value="{...}",type="pck.variant",has_more="0"
   | (gdb)
   | -var-list-children 1 v
   | ^done,numchild="4",children=[child={name="v.disc",exp="disc",numchild="0",value="true",type="boolean"},[snip]],has_more="0"
   | (gdb)

   (2) Second, doing an update after some changes in the value, but
       no mutation (only field "a" in our variant record changed):

   | -var-update v
   | ^done,changelist=[{name="v.a",in_scope="true",type_changed="false",has_more="0"}]
   | (gdb)

   (3) Lastly, doing an update after the value mutated. This time,
       we see that varobj simply reports that the value has mutated
       (type_changed="true"), and just provides the number number of
       children:

   |  -var-update v
   |  ^done,changelist=[{name="v",in_scope="true",type_changed="true",new_type="pck.variant",new_num_children="3",has_more="0"}]
   |  (gdb)

The prototype cannot be applied as is, as it needs to be applied
on top of some other changes that are work-in-progress.  But it
should give a good idea of how I proceeded.

The good thing is that this is fairly localized. I'm also wondering
whether this might be done without a language-dependent hook (see
the first FIXME of ada_varobj_value_has_mutated's description).
Perhaps create_child_with_value could solve my practical problem?
I haven't gone that far yet. I also tried testing the case where
it's a child rather than the root that mutates, but for some reason
the child is not properly described (in a sense similar to what
c_describe_child does), and thus I miss the mutation. So that
feature is untested, but it's just because of a bug I will chase
ASAP.

The unfortunate part, though, is that this is done somewhat in
parallel of the work done to handle pretty-printers. I think it
kind of makes sense that pretty-printers should take precedence
over this treatment. So, I'm somewhat thinking that it's better
that way. I haven't had time to verify that precedence is respected,
however. I just wanted to send the patch for comment...

The careful reader will also notice that I'm having trouble with
figuring out some invariants regarding the `from' and `to' fields
with respect to the `num_children' field... More stuff to be figured
out later...

Thanks,


This (the problem being addressed, not the solution) sounds similar to
a change I wrote for tracepoints -- augment -var-list-children to list
only children that have been partially or completely collected.

But instead of always deleting children, I taught varobjs to handle
the case of new children appearing at an index before other children,
compared to the previous update.  E.g.,
with 'struct { int a; int b; } g;', if at first, only g.b was
available, but the next traceframe contains both g.a and g.b, that
is detected, and g.a is shown as a new child in a
"-var-update".  While working on it, I realized
that varobj's that are filtering some of the children only, aren't
that different from pretty-printed dynamic varobj's.  That is, we needed
a method to get at the "next" available child; we have no random access
to children.  The "num_child" field isn't always trustable as
consequence.  We want to be able to tell the frontend that the number
of children changed --- the existing "new_num_children" output field
(invented for python varobjs) (*) of -var-update fit the bill
perfectly.  In terms of code, I was ending up mirroring the python
pretty-printed varobjs code in a lot of places, e.g.,
update_dynamic_varobj_children, and the more I fixed my code, the
more I realized that the new code I was adding should be exactly
like the python dynamic varobjs code.

So, I factored out the "listing dynamic varobj's
children" code behind a common interface, making use of a new
iterator "virtual" object (struct varobj_iter), and reimplemented
both pretty-printing varobjs and available-children-only varobjs using
that same interface.

I think that was the right decision. Frontends don't need to
learn anything anew, if they already support pretty-printed
dynamic varobjs (other than knowing to request a listing of only collected fields, rather than the whole object). And a bunch of code is shared between those varobj kinds, reducing maintenance burden.


(*) Note that the "new_num_children" attribute being output
indicates that the children list changed.  The manual says:

"@item new_num_children
For a dynamic varobj, if the number of children changed, or if the
type changed, this will be the new number of children.

The @samp{numchild} field in other varobj responses is generally not
valid for a dynamic varobj -- it will show the number of children that
@value{GDBN} knows about, but because dynamic varobjs lazily
instantiate their children, this will not reflect the number of
children which may be available.

The @samp{new_num_children} attribute only reports changes to the
number of children known by @value{GDBN}.  This is the only way to
                                           ^^^^^^^^^^^^^^^^^^^^^^^
detect whether an update has removed children (which necessarily can
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
only happen at the end of the update range)."
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


Implementing Ada mutable types support through this would mean mutable varobjs would be exposed as dynamic=1 varobjs. I'm not sure that'd be a problem? With frontends that currently support dynamic varobjs, things should simply work. Non dynamic varobjs were kind of a mistake anyway (a !dynamic varobj that is bound to an 10000000 element array is wholly fetched in gdb memory at once...). That said, if you don't want to go that way, it's fine with me. Just putting it out there..


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