[lldb-dev] https://reviews.llvm.org/D69273
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
Re: [lldb-dev] https://reviews.llvm.org/D69273
Thanks for the explanation. + Pavel & Adrian. On Thu, Oct 31, 2019 at 12:51 PM Jim Ingham via lldb-dev wrote: > > 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 ___ lldb-dev mailing list lldb-dev@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
Re: [lldb-dev] https://reviews.llvm.org/D69273
(Just writing to say that tomorrow is a public holiday in most of Europe, so I wont be able to meaningfully reply to this until monday/tuesday. But if, in the mean time, you want to revert this, or just limit the scope of that patch somehow, then that's fine with me.) On 31/10/2019 20:51, Jim Ingham via lldb-dev wrote: 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 ___ lldb-dev mailing list lldb-dev@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
Re: [lldb-dev] https://reviews.llvm.org/D69273
On Thu, Oct 31, 2019 at 1:06 PM Pavel Labath via lldb-dev wrote: > > (Just writing to say that tomorrow is a public holiday in most of > Europe, so I wont be able to meaningfully reply to this until > monday/tuesday. But if, in the mean time, you want to revert this, or > just limit the scope of that patch somehow, then that's fine with me.) > I don't see this as an urgent revert. We just cherry-picked the change in our branches and realized that it was creating some problems, so we raised the issue and started the discussion. Definitely it can wait a day or two. Thanks, -- Davide ___ lldb-dev mailing list lldb-dev@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev