Hi Guille, Replies inline... On Wed, 18 Sep 2019 at 14:44, Guillermo Polito <guillermopolito@gmail.com> wrote:
Hi Alistair,
we are checking this with Pablo here, some questions inline
El 18 sept 2019, a las 11:04, Alistair Grant <akgrant0710@gmail.com> escribió:
Hi Everyone,
TraitedMetaclass stores methods in two different instance variables:
- methodDict (inherited from Behavior) - localMethods
And the same method can be different in each dictionary.
Yes, trais actually work by flattening the methods of traits into the user class. - localMethods defines the methods actually defined in the class - methodDict has the raw low-level flattened version the VM uses for the lookup
So methodDict and localMethods should always contain the same instance of CompiledMethod for a given selector, right?
Different browsers show different versions, i.e.:
- The System Browser uses the method in methodDict.
Which is this System browser? Calypso system browser?
Yep, as in World Menu -> Tools -> System Browser
- Calypso's "Senders of" browser uses localMethods.
and this is Calypso senders, right?
Yes, pressing the "Senders" button from the System Browser (Calypso).
- The Iceberg versions browser uses localMethods.
It appears that the method in methodDict is the one that is actually used when a message is sent, but it would be nice to get confirmation.
To reproduce this in a clean Pharo 8 image:
- Open the System Browser on LGitBuf class>>signature_free: (the methodDict version). - Open the system browser on TLGitCalloutTrait>>call:options: and then press "Senders". The resulting window will include LGitBuf class>>signature_free:, but the localMethods version.
In this example, #signature_free: isn't defined by the trait, and isn't overwritten, so I would expect that the method in both dictionaries should be the same or it should only be in one dictionary.
Can someone say what the intended behaviour is?
We are tracking this, it seems you have found two bugs :D.
1st bug) Calypso and the senders/implementors should be in sync and show the same (always the local methods for traited classes)
From what you've written above (and below), the two dictionaries should always have the same instance of CompiledMethod so it shouldn't matter where it comes from.
Moreover, (Iâm confirming this with Pablo on line right now) the local methods dictionary should be just a subset of the method dictionary. In other words, the invariant is that methods in localMethods should be included in the methoddict, they should not differ as they are differing there.
2nd bug) UFFI? seems to be messing with this invariant :)
When a UFFI binding is executed for the very first time, the ffi call definition gets compiled and a new compiled method is generated performing that call. When a session finishes (the image stops/restarts) ffi bindings are reset (because their compilation is platform dependent).
What we are seeing there is that somehow UFFI managed to reset a binding method and put a wrong one in the local method
Iâve seen this bug before but never got the insight of what was producing it (neither put too much time to dig on it either :P). Another possibility is that the culprit are the LibGit bindings, which extend UFFI binding compilation.
I haven't looked at this, but what I saw was the localMethods was correct and the methodDict was old: Redefine a base system method (LGitCommit>>commit_author:) using an extension method resulted in methodDict containing the original definition and the localMethods containing the overridden method. What I would expect is that the overridden method is what is used everywhere. I'm not sure if this is related to UFFI or not. I'm on Discord if you'd like to chat real-time (back around 15:25). Thanks! Alistair