It looks like this change is causing problems with swift.  I was talking a 
little bit with Davide about this and it seems like it wasn't obvious how this 
was designed to work.  So here's what this was intended to do (apologies if 
this is at too basic a level and the issue was something deeper I missed, but 
anyway this might get us started...)

The lldb ValueObject system supports two fairly different kinds of values, live 
and frozen.  

The classic example of a live ValueObject is ValueObjectVariable.  That 
ValueObject is backed by an entity in the target, and knows when that entity is 
valid and not.  So it can always try to do "UpdateValueIfNeeded" and that will 
always return good values.  However, there's on complication with this, which 
is that we also want ValueObjectVariable to be able to answer "IsChanged".  
That's so in a UI you can mark values that change over a step in red, which is 
very helpful for following along in a debugging session.  So you have to copy 
the values into host memory, in order to have something to compare against when 
you stop again.  That's why there's this slightly complex dance between host 
and target memory for the live ValueObjects.

The example of a frozen object is the ValueObjectConstResult that is returned 
from expression evaluation.  That value is fixed to a StopID, so the backing 
entity is only known to be good at that stop id.  This is implemented by 
copying the value into Host memory and fetching it from there when requested.

The use case for this is for people like me who have a bad memory.  So I can 
stop somewhere and do:

(lldb) expr foo
struct baz $1 = {
  bar = 20
}

Then later on when I forget what foo.bar was at that time, I can do:

(lldb) expr $1.bar
bar = 20

At a first approximation, this leads to the statement that ConstValues should 
fetch what they fetch when made, and then not offer any information that wasn't 
gathered when the variable was fetched, and you certainly don't ever want these 
values to be updated.

A little complication arises because I might do:

(lldb) expr foo_which_has_a_pointer
$1 = ...
(lldb) expr *$1->the_pointer

If the StopID is the same between the first and second evaluation, then you 
should follow the pointer into target memory and fetch the value.  But if the 
StopID has changed, then trying to dereference a pointer should be an error.  
After all, you are now accessing an incoherent object, and if you try to do 
anything fancier with it than just print some memory (like asking the Swift 
Language Runtime what this value happens to be) you are very likely to get into 
trouble.

So it's clear we need two different behaviors w.r.t. how we treat live or 
frozen values.  Pavel's change was addressing a failure in ValueObjectChild, 
and the solution was to move the ValueObjectVariable behavior up to the 
ValueObject level.  But then that means that ValueObjectConstResults are no 
longer obeying the ConstResult rules.

But it seems like the problem really is that we have only one ValueObjectChild 
class, but child value objects can either be live or frozen, depending on the 
nature of their Root ValueObject.  And this is made a little more complicated 
by the fact that frozen values only freeze when the stop ID changes.

Jim


_______________________________________________
lldb-dev mailing list
lldb-dev@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev

Reply via email to