[squeak-dev] [Bug & design issue] Messages understood or not understood by ProtoObject

Eliot Miranda eliot.miranda at gmail.com
Fri Feb 14 17:34:18 UTC 2020



> On Feb 14, 2020, at 6:29 AM, David T. Lewis <lewis at mail.msen.com> wrote:
> 
> I think this observation is as much about "expected behavior" as
> it is about bugs or implementations :-)
> 
> ProtoObject actually does have a class, so without looking at the
> implementation it makes perfect sense that it should be able to
> answer its class. And given that it does have a class, it would
> be unexpected to me if it could not tell me what its class was.
> 
> On the other hand, if you poke at it too closely, you can indeed
> find some interesting oddities.
> 
> Object canUnderstand: #class ==> true
> Object new respondsTo: #class ==> true
> ProtoObject canUnderstand: #class ==> false
> ProtoObject new respondsTo: #class ==> DNU
> ProtoObject new class ==> ProtoObject
> 
> And if you step into #class in a debugger, you will lock up your
> image with infinite debuggers. Arguably, that part is a bug ;-)
> 
> I suspect that we are looking at a clever bit of implementation that
> addresses the following common use case:
> 
>   "Gee, I wonder what the class of ProtoObject is?"

To which the answer is “its own business”.  Finding out the real class of a ProtoObject or non-Object subclass of it must be something only privileged parts of the execution simulation, error reporting and inspection systems can do.  Otherwise, building truly transparent proxies is really tricky and full of unexpected edge cases.

Ideally we want to be able to build distributed IDEs for the cloud, etc, where we can have remote tools and distribute processing across many images.  Having very transparent proxies is at the heart of any such thing.

> 
> Dave
> 
>> On Fri, Feb 14, 2020 at 01:18:46PM +0000, Thiede, Christoph wrote:
>> Hi all! :-)
>> 
>> When we were fiddling around with some proxy implementations today, Marcel and I discovered an interesting set of issues regarding ProtoObjects.
>> 
>> Let's start with a concrete bug:
>> 
>> 
>> Code to reproduce <do it>:
>> 
>> ProtoObject new class.
>> 
>> 
>> Expected behavior:
>> 
>> DNU exception, because #class is implemented on Object only.
>> 
>> 
>> Actual behavior:
>> 
>> Outputs ProtoObject.
>> 
>> Even stranger: If you debug the method instead and simulate the #class send, you get a "simulated message class not understood" error.
>> 
>> If you subclass ProtoObject and override/forward #class, the results will deviate based on whether you are debugging or executing the code.
>> 
>> 
>> Some thoughts:
>> 
>> There are two options: Either to implement #class on ProtoObject (by moving the primitive definition up from Object), or to remove it from the specialObjectsArray so that a send to #class is not compiled differently than a send to any other regular message.
>> 
>> 
>> This leads us to the rather general question: What special messages should an instance of ProtoObject understand?
>> 
>> We don't answer this question completely consistent at the moment: For example, #instVarAt: is implemented on Object, but #instVarsInclude: is implemented on ProtoObject. Again, it is a bit weird that the implementation of #instVarsInclude: calls #class which is implemented on Object only. And so it goes on:
>> 
>>  *   #someObject is implemented on Object, but #nextObject is available in ProtoObject.
>>  *   #withArgs:executeMethod: is implemented on ProtoObject, whereas #perform:withArguments: is on Object.
>>  *   #ifNotNil: is implemented on ProtoObject; however, #ifNotNilDo: is implemented on Object. (btw: does the latter still have any raison d'?tre?)
>>  *   #flag: exists on ProtoObject, and #yourself exists on Object only. Isn't #yourself rather a syntactical element we would like to behave exactly the same way for every possible message receiver? (btw: Is there a good reason not to speed up #yourself via specialObjectsArray)?
>>  *   (I don't claim for completeness)
>> 
>> And just some other problems regarding to ProtoObject (just collecting them here instead of forgetting them forever):
>> 
>>  *   ObjectTracer is broken due to several reasons. Will fix this soon.
>>  *   Inspectors cannot inspect ProtoObjects correctly (for example: Inspector openOn: (ObjectTracer on: Display)). This is because #instVarAt: is implemented on Object only so this message is forwarded.
>> Maybe we should replace these critical calls from Inspector by something like #tryPrimitive:173withArgs:? But should we do so in Inspector or rather in a new subclass named ProtoInspector or similar? Hm, then we would need to implement #inspectorClass on ProtoObject, which is bad either ... We will keep investigating this issue.
>> 
>> However, the crucial question is: What special messages should an instance of ProtoObject understand? On the one hand, the idea of ProtoObjects is to work as total proxies with a maximum amount of forwarding potential, which implies a minimum number of methods. On the other hand, certain aspects such as accessing instvars or executing messages are really identity-related. Looking forward to your comments :-)
>> 
>> Best,
>> Christoph
> 
>> 
> 
> 


More information about the Squeak-dev mailing list