EyeInspector with subclasses of ProtoObject
I'm dealing with the MessageArchiver of GLORP which is a subclass of ProtoObject and handles the "transparent" creation of expressions vÃa a DNU resolution. The problem I'm facing is that the EyeInspector expects the value in its value holder to respond to #basicSize, and because MessageArchiver inherits from ProtoObject it doesn't understand it. The problem is here: EyeInspector>>#variableFieldsToShow "Answers the indexes of the variable fields of the object to show. Shorten the list for very long collection (cf limit1 and limit2)" |bSize| bSize := self objectVariableSize. ^ bSize <= (self limit1 + self limit2) ifTrue: [1 to: bSize] ifFalse: [(1 to: self limit1) , (bSize - self limit2 + 1 to: bSize)]. If I implement #basicSize in MessageArchiver things go bananas. If I doesn't, and because #objectVariableSize is sent to MessageAchiver "proxy", bSize ends up with an instance of the MessageArchiver instead of an integer. I implemented #inspectorClass in MessageArchiver class to return EyeBasicInspector, but it is the same. Question: Is it documented what I should define/override in my classes to support EyeInspector? Regards, Esteban A. Maringolo pd: Stack trace =========== UndefinedObject(Object)>>error: MessageArchiver>>mustBeBoolean EyeBasicInspector(EyeInspector)>>variableFieldsToShow EyeBasicInspector(EyeInspector)>>addVariableFields: EyeBasicInspector(EyeInspector)>>generateElements EyeBasicInspector(EyeInspector)>>updateList EyeBasicInspector(EyeInspector)>>objectChanged [ self objectChanged ] in EyeBasicInspector(EyeAbstractInspector)>>initializePresenter in Block: [ self objectChanged ] BlockClosure>>cull: BlockClosure>>cull:cull: BlockClosure>>cull:cull:cull: BlockClosure>>cull:cull:cull:cull:
Hi Esteban, I think EyeInspector needs to handle classes that don't inherit from Object specially. Instead of asking the instance it should ask the class. You should be able to use the Context methods for mirror primitives to extract state without sending messages to the instance. Then the special version of EyeInspector for ProtoObject subclasses can ask this like (thisContext objectClass: object) isIndexable ifTrue: [size := thisContext objectSize: object] Basically both the Inspector and the Debugger's execution simulation machinery need to treat encapsulators such as MessageArchiver with kid gloves. One *must not* cause inspecting or debugging to send messages through the encapsulator. Instead, all access to the object should be through primitives that don't send messages to the objects. HTH On Tue, Nov 17, 2015 at 7:05 AM, Esteban A. Maringolo <emaringolo@gmail.com> wrote:
I'm dealing with the MessageArchiver of GLORP which is a subclass of ProtoObject and handles the "transparent" creation of expressions vÃa a DNU resolution.
The problem I'm facing is that the EyeInspector expects the value in its value holder to respond to #basicSize, and because MessageArchiver inherits from ProtoObject it doesn't understand it.
The problem is here: EyeInspector>>#variableFieldsToShow "Answers the indexes of the variable fields of the object to show. Shorten the list for very long collection (cf limit1 and limit2)" |bSize| bSize := self objectVariableSize. ^ bSize <= (self limit1 + self limit2) ifTrue: [1 to: bSize] ifFalse: [(1 to: self limit1) , (bSize - self limit2 + 1 to: bSize)].
If I implement #basicSize in MessageArchiver things go bananas. If I doesn't, and because #objectVariableSize is sent to MessageAchiver "proxy", bSize ends up with an instance of the MessageArchiver instead of an integer.
I implemented #inspectorClass in MessageArchiver class to return EyeBasicInspector, but it is the same.
Question: Is it documented what I should define/override in my classes to support EyeInspector?
Regards,
Esteban A. Maringolo
pd: Stack trace ===========
UndefinedObject(Object)>>error: MessageArchiver>>mustBeBoolean EyeBasicInspector(EyeInspector)>>variableFieldsToShow EyeBasicInspector(EyeInspector)>>addVariableFields: EyeBasicInspector(EyeInspector)>>generateElements EyeBasicInspector(EyeInspector)>>updateList EyeBasicInspector(EyeInspector)>>objectChanged [ self objectChanged ] in EyeBasicInspector(EyeAbstractInspector)>>initializePresenter in Block: [ self objectChanged ] BlockClosure>>cull: BlockClosure>>cull:cull: BlockClosure>>cull:cull:cull: BlockClosure>>cull:cull:cull:cull:
-- _,,,^..^,,,_ best, Eliot
Inspector: a surgery tool to see inside the objects Debugger: a surgery tool to see inside the processes - or maybe to see how the object live from the inside ;) 2015-11-17 18:37 GMT+01:00 Eliot Miranda <eliot.miranda@gmail.com>:
Hi Esteban,
I think EyeInspector needs to handle classes that don't inherit from Object specially. Instead of asking the instance it should ask the class. You should be able to use the Context methods for mirror primitives to extract state without sending messages to the instance. Then the special version of EyeInspector for ProtoObject subclasses can ask this like
(thisContext objectClass: object) isIndexable ifTrue: [size := thisContext objectSize: object]
Basically both the Inspector and the Debugger's execution simulation machinery need to treat encapsulators such as MessageArchiver with kid gloves. One *must not* cause inspecting or debugging to send messages through the encapsulator. Instead, all access to the object should be through primitives that don't send messages to the objects.
HTH
On Tue, Nov 17, 2015 at 7:05 AM, Esteban A. Maringolo < emaringolo@gmail.com> wrote:
I'm dealing with the MessageArchiver of GLORP which is a subclass of ProtoObject and handles the "transparent" creation of expressions vÃa a DNU resolution.
The problem I'm facing is that the EyeInspector expects the value in its value holder to respond to #basicSize, and because MessageArchiver inherits from ProtoObject it doesn't understand it.
The problem is here: EyeInspector>>#variableFieldsToShow "Answers the indexes of the variable fields of the object to show. Shorten the list for very long collection (cf limit1 and limit2)" |bSize| bSize := self objectVariableSize. ^ bSize <= (self limit1 + self limit2) ifTrue: [1 to: bSize] ifFalse: [(1 to: self limit1) , (bSize - self limit2 + 1 to: bSize)].
If I implement #basicSize in MessageArchiver things go bananas. If I doesn't, and because #objectVariableSize is sent to MessageAchiver "proxy", bSize ends up with an instance of the MessageArchiver instead of an integer.
I implemented #inspectorClass in MessageArchiver class to return EyeBasicInspector, but it is the same.
Question: Is it documented what I should define/override in my classes to support EyeInspector?
Regards,
Esteban A. Maringolo
pd: Stack trace ===========
UndefinedObject(Object)>>error: MessageArchiver>>mustBeBoolean EyeBasicInspector(EyeInspector)>>variableFieldsToShow EyeBasicInspector(EyeInspector)>>addVariableFields: EyeBasicInspector(EyeInspector)>>generateElements EyeBasicInspector(EyeInspector)>>updateList EyeBasicInspector(EyeInspector)>>objectChanged [ self objectChanged ] in EyeBasicInspector(EyeAbstractInspector)>>initializePresenter in Block: [ self objectChanged ] BlockClosure>>cull: BlockClosure>>cull:cull: BlockClosure>>cull:cull:cull: BlockClosure>>cull:cull:cull:cull:
-- _,,,^..^,,,_ best, Eliot
2015-11-17 14:37 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com>:
Hi Esteban,
I think EyeInspector needs to handle classes that don't inherit from Object specially. Instead of asking the instance it should ask the class. You should be able to use the Context methods for mirror primitives to extract state without sending messages to the instance. Then the special version of EyeInspector for ProtoObject subclasses can ask this like
Yes, an special inspector for ProtoObject subclasses would be required, but I couldn't find one already suited for this purpose.
(thisContext objectClass: object) isIndexable ifTrue: [size := thisContext objectSize: object]
I don't know if your code was meant to be accurate or just a guideline of how this could be implemented, but Context doesn't implement #objectClass: nor #objectSize:
Basically both the Inspector and the Debugger's execution simulation machinery need to treat encapsulators such as MessageArchiver with kid gloves. One *must not* cause inspecting or debugging to send messages through the encapsulator. Instead, all access to the object should be through primitives that don't send messages to the objects.
I know that dealing with Proxies and similar objects is tricky, I had to deal with my own subclasses of ProtoObject in Dolphin, but there the class implemented all that was needed to interact with the environment tools. Hiwever, to me all this is a kind of black magic, I read the blue book years ago and can understand it, but I do understand it as I understand the mechanics of my car, however when it breaks down I take it to the specialist :) Esteban A. Maringolo
Hi Esteban, On Tue, Nov 17, 2015 at 1:37 PM, Esteban A. Maringolo <emaringolo@gmail.com> wrote:
2015-11-17 14:37 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com>:
Hi Esteban,
I think EyeInspector needs to handle classes that don't inherit from Object specially. Instead of asking the instance it should ask the class. You should be able to use the Context methods for mirror primitives to extract state without sending messages to the instance. Then the special version of EyeInspector for ProtoObject subclasses can ask this like
Yes, an special inspector for ProtoObject subclasses would be required, but I couldn't find one already suited for this purpose.
(thisContext objectClass: object) isIndexable ifTrue: [size := thisContext objectSize: object]
I don't know if your code was meant to be accurate or just a guideline of how this could be implemented, but Context doesn't implement #objectClass: nor #objectSize:
Find attached. I think you'll find they are in the Spur version. You might think of back-porting their use in Context form Spur; that'll make the debugger able to handle proxies.
Basically both the Inspector and the Debugger's execution simulation
machinery need to treat encapsulators such as MessageArchiver with kid gloves. One *must not* cause inspecting or debugging to send messages through the encapsulator. Instead, all access to the object should be through primitives that don't send messages to the objects.
I know that dealing with Proxies and similar objects is tricky, I had to deal with my own subclasses of ProtoObject in Dolphin, but there the class implemented all that was needed to interact with the environment tools.
Hiwever, to me all this is a kind of black magic, I read the blue book years ago and can understand it, but I do understand it as I understand the mechanics of my car, however when it breaks down I take it to the specialist :)
Well, the thing to think of is that inside the VM objects are just a sequence of words, and the VM, while it sends messages, doesn't send messages to objects to update their state; it just accesses the state directly. So in an execution simulation method such as Context methods for instruction decoding pushReceiverVariable: offset self push: (receiver instVarAt: offset + 1) that will send the message instVarAt: to the receiver, and if the receiver is a proxy, that will go through the proixie's doesNotUnderstand: method and send instVarAt: the the object the proxy wraps, which won't do the right thing at all. Instead it needs to be written Context methods for instruction decoding pushReceiverVariable: offset self push: (self object: receiver instVarAt: offset + 1) which reaches into the object without sending any messages to it. I understand that this will appear in Spur, because I made it part of the bootstrap, but if I were you I would integrate these changes into the current version asap. The debugger won't work properly with proxies, encapsulators etc otherwise. _,,,^..^,,,_ best, Eliot
Hello, This is known and was discussed on the bug tracker. The problem is that currently Pharo has many tools and classes: EyeInspector in the debugger, GTInspector outside, the debugger itself, the in-image interpreter in the Context class ... that need to be changed to support debugging objects that basically cannot receive any message. We are aware of the solution but fixing it for all the toolkits and classes is quite some work. In addition, if not tested, someone will break it because he won't understand that an inspected object can't receive any message because the expected behavior of an object with no DNU behavior and no methods inherited from Object is to freeze the system. It's a lot of fun doing that though. Clement 2015-11-17 21:39 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com>:
Hi Esteban,
On Tue, Nov 17, 2015 at 1:37 PM, Esteban A. Maringolo < emaringolo@gmail.com> wrote:
2015-11-17 14:37 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com>:
Hi Esteban,
I think EyeInspector needs to handle classes that don't inherit from Object specially. Instead of asking the instance it should ask the class. You should be able to use the Context methods for mirror primitives to extract state without sending messages to the instance. Then the special version of EyeInspector for ProtoObject subclasses can ask this like
Yes, an special inspector for ProtoObject subclasses would be required, but I couldn't find one already suited for this purpose.
(thisContext objectClass: object) isIndexable ifTrue: [size := thisContext objectSize: object]
I don't know if your code was meant to be accurate or just a guideline of how this could be implemented, but Context doesn't implement #objectClass: nor #objectSize:
Find attached. I think you'll find they are in the Spur version. You might think of back-porting their use in Context form Spur; that'll make the debugger able to handle proxies.
Basically both the Inspector and the Debugger's execution simulation
machinery need to treat encapsulators such as MessageArchiver with kid gloves. One *must not* cause inspecting or debugging to send messages through the encapsulator. Instead, all access to the object should be through primitives that don't send messages to the objects.
I know that dealing with Proxies and similar objects is tricky, I had to deal with my own subclasses of ProtoObject in Dolphin, but there the class implemented all that was needed to interact with the environment tools.
Hiwever, to me all this is a kind of black magic, I read the blue book years ago and can understand it, but I do understand it as I understand the mechanics of my car, however when it breaks down I take it to the specialist :)
Well, the thing to think of is that inside the VM objects are just a sequence of words, and the VM, while it sends messages, doesn't send messages to objects to update their state; it just accesses the state directly. So in an execution simulation method such as
Context methods for instruction decoding pushReceiverVariable: offset self push: (receiver instVarAt: offset + 1)
that will send the message instVarAt: to the receiver, and if the receiver is a proxy, that will go through the proixie's doesNotUnderstand: method and send instVarAt: the the object the proxy wraps, which won't do the right thing at all. Instead it needs to be written
Context methods for instruction decoding pushReceiverVariable: offset self push: (self object: receiver instVarAt: offset + 1)
which reaches into the object without sending any messages to it. I understand that this will appear in Spur, because I made it part of the bootstrap, but if I were you I would integrate these changes into the current version asap. The debugger won't work properly with proxies, encapsulators etc otherwise.
_,,,^..^,,,_ best, Eliot
Iâd like to discuss also the possibility to add those low level operations on mirrors objects, that could be packaged separately from the kernel of the language. Adding them on a first step is easy, then making all tools use them is the hard/timeconsuming part, yes.
On 18 nov 2015, at 12:35 p.m., Clément Bera <bera.clement@gmail.com> wrote:
Hello,
This is known and was discussed on the bug tracker.
The problem is that currently Pharo has many tools and classes: EyeInspector in the debugger, GTInspector outside, the debugger itself, the in-image interpreter in the Context class ... that need to be changed to support debugging objects that basically cannot receive any message.
We are aware of the solution but fixing it for all the toolkits and classes is quite some work. In addition, if not tested, someone will break it because he won't understand that an inspected object can't receive any message because the expected behavior of an object with no DNU behavior and no methods inherited from Object is to freeze the system.
It's a lot of fun doing that though.
Clement
2015-11-17 21:39 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com <mailto:eliot.miranda@gmail.com>>: Hi Esteban,
On Tue, Nov 17, 2015 at 1:37 PM, Esteban A. Maringolo <emaringolo@gmail.com <mailto:emaringolo@gmail.com>> wrote: 2015-11-17 14:37 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com <mailto:eliot.miranda@gmail.com>>:
Hi Esteban,
I think EyeInspector needs to handle classes that don't inherit from Object specially. Instead of asking the instance it should ask the class. You should be able to use the Context methods for mirror primitives to extract state without sending messages to the instance. Then the special version of EyeInspector for ProtoObject subclasses can ask this like
Yes, an special inspector for ProtoObject subclasses would be required, but I couldn't find one already suited for this purpose.
(thisContext objectClass: object) isIndexable ifTrue: [size := thisContext objectSize: object]
I don't know if your code was meant to be accurate or just a guideline of how this could be implemented, but Context doesn't implement #objectClass: nor #objectSize:
Find attached. I think you'll find they are in the Spur version. You might think of back-porting their use in Context form Spur; that'll make the debugger able to handle proxies.
Basically both the Inspector and the Debugger's execution simulation machinery need to treat encapsulators such as MessageArchiver with kid gloves. One *must not* cause inspecting or debugging to send messages through the encapsulator. Instead, all access to the object should be through primitives that don't send messages to the objects.
I know that dealing with Proxies and similar objects is tricky, I had to deal with my own subclasses of ProtoObject in Dolphin, but there the class implemented all that was needed to interact with the environment tools.
Hiwever, to me all this is a kind of black magic, I read the blue book years ago and can understand it, but I do understand it as I understand the mechanics of my car, however when it breaks down I take it to the specialist :)
Well, the thing to think of is that inside the VM objects are just a sequence of words, and the VM, while it sends messages, doesn't send messages to objects to update their state; it just accesses the state directly. So in an execution simulation method such as
Context methods for instruction decoding pushReceiverVariable: offset self push: (receiver instVarAt: offset + 1)
that will send the message instVarAt: to the receiver, and if the receiver is a proxy, that will go through the proixie's doesNotUnderstand: method and send instVarAt: the the object the proxy wraps, which won't do the right thing at all. Instead it needs to be written
Context methods for instruction decoding pushReceiverVariable: offset self push: (self object: receiver instVarAt: offset + 1)
which reaches into the object without sending any messages to it. I understand that this will appear in Spur, because I made it part of the bootstrap, but if I were you I would integrate these changes into the current version asap. The debugger won't work properly with proxies, encapsulators etc otherwise.
_,,,^..^,,,_ best, Eliot
2015-11-18 8:43 GMT-03:00 Guillermo Polito <guillermopolito@gmail.com>:
Iâd like to discuss also the possibility to add those low level operations on mirrors objects, that could be packaged separately from the kernel of the language. Adding them on a first step is easy, then making all tools use them is the hard/timeconsuming part, yes.
All the needed operations already exist. You can put them on your mirror objects without any problem.
On 18 nov 2015, at 12:35 p.m., Clément Bera <bera.clement@gmail.com> wrote:
Hello,
This is known and was discussed on the bug tracker.
The problem is that currently Pharo has many tools and classes: EyeInspector in the debugger, GTInspector outside, the debugger itself, the in-image interpreter in the Context class ... that need to be changed to support debugging objects that basically cannot receive any message.
We are aware of the solution but fixing it for all the toolkits and classes is quite some work. In addition, if not tested, someone will break it because he won't understand that an inspected object can't receive any message because the expected behavior of an object with no DNU behavior and no methods inherited from Object is to freeze the system.
It's a lot of fun doing that though.
Clement
2015-11-17 21:39 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com>:
Hi Esteban,
On Tue, Nov 17, 2015 at 1:37 PM, Esteban A. Maringolo < emaringolo@gmail.com> wrote:
2015-11-17 14:37 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com>:
Hi Esteban,
I think EyeInspector needs to handle classes that don't inherit from Object specially. Instead of asking the instance it should ask the class. You should be able to use the Context methods for mirror primitives to extract state without sending messages to the instance. Then the special version of EyeInspector for ProtoObject subclasses can ask this like
Yes, an special inspector for ProtoObject subclasses would be required, but I couldn't find one already suited for this purpose.
(thisContext objectClass: object) isIndexable ifTrue: [size := thisContext objectSize: object]
I don't know if your code was meant to be accurate or just a guideline of how this could be implemented, but Context doesn't implement #objectClass: nor #objectSize:
Find attached. I think you'll find they are in the Spur version. You might think of back-porting their use in Context form Spur; that'll make the debugger able to handle proxies.
Basically both the Inspector and the Debugger's execution simulation
machinery need to treat encapsulators such as MessageArchiver with kid gloves. One *must not* cause inspecting or debugging to send messages through the encapsulator. Instead, all access to the object should be through primitives that don't send messages to the objects.
I know that dealing with Proxies and similar objects is tricky, I had to deal with my own subclasses of ProtoObject in Dolphin, but there the class implemented all that was needed to interact with the environment tools.
Hiwever, to me all this is a kind of black magic, I read the blue book years ago and can understand it, but I do understand it as I understand the mechanics of my car, however when it breaks down I take it to the specialist :)
Well, the thing to think of is that inside the VM objects are just a sequence of words, and the VM, while it sends messages, doesn't send messages to objects to update their state; it just accesses the state directly. So in an execution simulation method such as
Context methods for instruction decoding pushReceiverVariable: offset self push: (receiver instVarAt: offset + 1)
that will send the message instVarAt: to the receiver, and if the receiver is a proxy, that will go through the proixie's doesNotUnderstand: method and send instVarAt: the the object the proxy wraps, which won't do the right thing at all. Instead it needs to be written
Context methods for instruction decoding pushReceiverVariable: offset self push: (self object: receiver instVarAt: offset + 1)
which reaches into the object without sending any messages to it. I understand that this will appear in Spur, because I made it part of the bootstrap, but if I were you I would integrate these changes into the current version asap. The debugger won't work properly with proxies, encapsulators etc otherwise.
_,,,^..^,,,_ best, Eliot
2015-11-18 13:29 GMT-03:00 Clément Bera <bera.clement@gmail.com>:
2015-11-18 8:43 GMT-03:00 Guillermo Polito <guillermopolito@gmail.com>:
Iâd like to discuss also the possibility to add those low level operations on mirrors objects, that could be packaged separately from the kernel of the language. Adding them on a first step is easy, then making all tools use them is the hard/timeconsuming part, yes.
All the needed operations already exist. You can put them on your mirror objects without any problem.
Who takes the decision to put it either in EyeInspector or GtInspector? Regards!
Hi, Please tell me more specifically what needs to be done. Could you give me a concrete example of an object that cannot be inspected? Cheers, Tudor
On Nov 18, 2015, at 6:08 PM, Esteban A. Maringolo <emaringolo@gmail.com> wrote:
2015-11-18 13:29 GMT-03:00 Clément Bera <bera.clement@gmail.com>:
2015-11-18 8:43 GMT-03:00 Guillermo Polito <guillermopolito@gmail.com>:
Iâd like to discuss also the possibility to add those low level operations on mirrors objects, that could be packaged separately from the kernel of the language. Adding them on a first step is easy, then making all tools use them is the hard/timeconsuming part, yes.
All the needed operations already exist. You can put them on your mirror objects without any problem.
Who takes the decision to put it either in EyeInspector or GtInspector?
Regards!
-- www.tudorgirba.com "Be rather willing to give than demanding to get."
2015-11-19 15:31 GMT+01:00 Tudor Girba <tudor@tudorgirba.com>:
Hi,
Please tell me more specifically what needs to be done. Could you give me a concrete example of an object that cannot be inspected?
Try this code: GTInspector inspect: ProtoObject new Then you can try with instance of subclasses of ProtoObjects with different properties. For example: ProtoObject variableSubclass: #ProtoArray instanceVariableNames: '' classVariableNames: '' category: 'Kernel-Objects' GTInspector inspect: (ProtoArray new: 3) Lastly you can try the hard cases. For example run: ProtoArray superclass: nil. GTInspector inspect: (ProtoArray new: 3) The generic problem is that these objects cannot be expected to answer any message, as it can crash the VM, so inspection should happen without the object inspected receiving any message.
Cheers, Tudor
On Nov 18, 2015, at 6:08 PM, Esteban A. Maringolo <emaringolo@gmail.com> wrote:
2015-11-18 13:29 GMT-03:00 Clément Bera <bera.clement@gmail.com>:
2015-11-18 8:43 GMT-03:00 Guillermo Polito <guillermopolito@gmail.com>:
Iâd like to discuss also the possibility to add those low level
operations
on mirrors objects, that could be packaged separately from the kernel of the language. Adding them on a first step is easy, then making all tools use them is the hard/timeconsuming part, yes.
All the needed operations already exist. You can put them on your mirror objects without any problem.
Who takes the decision to put it either in EyeInspector or GtInspector?
Regards!
-- www.tudorgirba.com
"Be rather willing to give than demanding to get."
Yep. Got it. See my other mail about integrating the reflection methods in Context. This would be enough to get the GTInspector working properly (we already did it but we cannot commit because of missing Context methods). Cheers, Doru
On Nov 19, 2015, at 5:53 PM, Clément Bera <bera.clement@gmail.com> wrote:
2015-11-19 15:31 GMT+01:00 Tudor Girba <tudor@tudorgirba.com>: Hi,
Please tell me more specifically what needs to be done. Could you give me a concrete example of an object that cannot be inspected?
Try this code:
GTInspector inspect: ProtoObject new
Then you can try with instance of subclasses of ProtoObjects with different properties. For example:
ProtoObject variableSubclass: #ProtoArray instanceVariableNames: '' classVariableNames: '' category: 'Kernel-Objects'
GTInspector inspect: (ProtoArray new: 3)
Lastly you can try the hard cases. For example run:
ProtoArray superclass: nil. GTInspector inspect: (ProtoArray new: 3)
The generic problem is that these objects cannot be expected to answer any message, as it can crash the VM, so inspection should happen without the object inspected receiving any message.
Cheers, Tudor
On Nov 18, 2015, at 6:08 PM, Esteban A. Maringolo <emaringolo@gmail.com> wrote:
2015-11-18 13:29 GMT-03:00 Clément Bera <bera.clement@gmail.com>:
2015-11-18 8:43 GMT-03:00 Guillermo Polito <guillermopolito@gmail.com>:
Iâd like to discuss also the possibility to add those low level operations on mirrors objects, that could be packaged separately from the kernel of the language. Adding them on a first step is easy, then making all tools use them is the hard/timeconsuming part, yes.
All the needed operations already exist. You can put them on your mirror objects without any problem.
Who takes the decision to put it either in EyeInspector or GtInspector?
Regards!
-- www.tudorgirba.com
"Be rather willing to give than demanding to get."
-- www.tudorgirba.com "Problem solving efficiency grows with the abstractness level of problem understanding."
Hi, I looked at the problem with Esteban. Essentially, we would benefit a lot from the Context mirror methods that Eliot sent. We can still imagine a mirror object on top of that, but already they would provide a good enough support. Do we agree to add these methods to Pharo? Cheers, Doru
On Nov 19, 2015, at 3:31 PM, Tudor Girba <tudor@tudorgirba.com> wrote:
Hi,
Please tell me more specifically what needs to be done. Could you give me a concrete example of an object that cannot be inspected?
Cheers, Tudor
On Nov 18, 2015, at 6:08 PM, Esteban A. Maringolo <emaringolo@gmail.com> wrote:
2015-11-18 13:29 GMT-03:00 Clément Bera <bera.clement@gmail.com>:
2015-11-18 8:43 GMT-03:00 Guillermo Polito <guillermopolito@gmail.com>:
Iâd like to discuss also the possibility to add those low level operations on mirrors objects, that could be packaged separately from the kernel of the language. Adding them on a first step is easy, then making all tools use them is the hard/timeconsuming part, yes.
All the needed operations already exist. You can put them on your mirror objects without any problem.
Who takes the decision to put it either in EyeInspector or GtInspector?
Regards!
-- www.tudorgirba.com
"Be rather willing to give than demanding to get."
-- www.tudorgirba.com "Yesterday is a fact. Tomorrow is a possibility. Today is a challenge."
Hi, I created an issue for this: https://pharo.fogbugz.com/f/cases/17170/Context-missing-primitives Cheers, Doru
On Nov 19, 2015, at 3:31 PM, Tudor Girba <tudor@tudorgirba.com> wrote:
Hi,
Please tell me more specifically what needs to be done. Could you give me a concrete example of an object that cannot be inspected?
Cheers, Tudor
On Nov 18, 2015, at 6:08 PM, Esteban A. Maringolo <emaringolo@gmail.com> wrote:
2015-11-18 13:29 GMT-03:00 Clément Bera <bera.clement@gmail.com>:
2015-11-18 8:43 GMT-03:00 Guillermo Polito <guillermopolito@gmail.com>:
Iâd like to discuss also the possibility to add those low level operations on mirrors objects, that could be packaged separately from the kernel of the language. Adding them on a first step is easy, then making all tools use them is the hard/timeconsuming part, yes.
All the needed operations already exist. You can put them on your mirror objects without any problem.
Who takes the decision to put it either in EyeInspector or GtInspector?
Regards!
-- www.tudorgirba.com
"Be rather willing to give than demanding to get."
-- www.tudorgirba.com "Yesterday is a fact. Tomorrow is a possibility. Today is a challenge."
I know we can :) and I did some prototypes already as part of my thesis. The question is if that is a design we *want* or not.
On 18 nov 2015, at 5:29 p.m., Clément Bera <bera.clement@gmail.com> wrote:
2015-11-18 8:43 GMT-03:00 Guillermo Polito <guillermopolito@gmail.com <mailto:guillermopolito@gmail.com>>: Iâd like to discuss also the possibility to add those low level operations on mirrors objects, that could be packaged separately from the kernel of the language. Adding them on a first step is easy, then making all tools use them is the hard/timeconsuming part, yes.
All the needed operations already exist. You can put them on your mirror objects without any problem.
On 18 nov 2015, at 12:35 p.m., Clément Bera <bera.clement@gmail.com <mailto:bera.clement@gmail.com>> wrote:
Hello,
This is known and was discussed on the bug tracker.
The problem is that currently Pharo has many tools and classes: EyeInspector in the debugger, GTInspector outside, the debugger itself, the in-image interpreter in the Context class ... that need to be changed to support debugging objects that basically cannot receive any message.
We are aware of the solution but fixing it for all the toolkits and classes is quite some work. In addition, if not tested, someone will break it because he won't understand that an inspected object can't receive any message because the expected behavior of an object with no DNU behavior and no methods inherited from Object is to freeze the system.
It's a lot of fun doing that though.
Clement
2015-11-17 21:39 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com <mailto:eliot.miranda@gmail.com>>: Hi Esteban,
On Tue, Nov 17, 2015 at 1:37 PM, Esteban A. Maringolo <emaringolo@gmail.com <mailto:emaringolo@gmail.com>> wrote: 2015-11-17 14:37 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com <mailto:eliot.miranda@gmail.com>>:
Hi Esteban,
I think EyeInspector needs to handle classes that don't inherit from Object specially. Instead of asking the instance it should ask the class. You should be able to use the Context methods for mirror primitives to extract state without sending messages to the instance. Then the special version of EyeInspector for ProtoObject subclasses can ask this like
Yes, an special inspector for ProtoObject subclasses would be required, but I couldn't find one already suited for this purpose.
(thisContext objectClass: object) isIndexable ifTrue: [size := thisContext objectSize: object]
I don't know if your code was meant to be accurate or just a guideline of how this could be implemented, but Context doesn't implement #objectClass: nor #objectSize:
Find attached. I think you'll find they are in the Spur version. You might think of back-porting their use in Context form Spur; that'll make the debugger able to handle proxies.
Basically both the Inspector and the Debugger's execution simulation machinery need to treat encapsulators such as MessageArchiver with kid gloves. One *must not* cause inspecting or debugging to send messages through the encapsulator. Instead, all access to the object should be through primitives that don't send messages to the objects.
I know that dealing with Proxies and similar objects is tricky, I had to deal with my own subclasses of ProtoObject in Dolphin, but there the class implemented all that was needed to interact with the environment tools.
Hiwever, to me all this is a kind of black magic, I read the blue book years ago and can understand it, but I do understand it as I understand the mechanics of my car, however when it breaks down I take it to the specialist :)
Well, the thing to think of is that inside the VM objects are just a sequence of words, and the VM, while it sends messages, doesn't send messages to objects to update their state; it just accesses the state directly. So in an execution simulation method such as
Context methods for instruction decoding pushReceiverVariable: offset self push: (receiver instVarAt: offset + 1)
that will send the message instVarAt: to the receiver, and if the receiver is a proxy, that will go through the proixie's doesNotUnderstand: method and send instVarAt: the the object the proxy wraps, which won't do the right thing at all. Instead it needs to be written
Context methods for instruction decoding pushReceiverVariable: offset self push: (self object: receiver instVarAt: offset + 1)
which reaches into the object without sending any messages to it. I understand that this will appear in Spur, because I made it part of the bootstrap, but if I were you I would integrate these changes into the current version asap. The debugger won't work properly with proxies, encapsulators etc otherwise.
_,,,^..^,,,_ best, Eliot
On 19-11-15 10:33, Guillermo Polito wrote:
I know we can :) and I did some prototypes already as part of my thesis.
The question is if that is a design we *want* or not.
1 Is it an improvement on the current situation? 2 Is it blocking an improvement direction we want to take? 3 Can it be tested quickly? Stephan
2015-11-19 7:22 GMT-03:00 Stephan Eggermont <stephan@stack.nl>:
On 19-11-15 10:33, Guillermo Polito wrote:
I know we can :) and I did some prototypes already as part of my thesis.
The question is if that is a design we *want* or not.
1 Is it an improvement on the current situation?
Yes.
2 Is it blocking an improvement direction we want to take?
Debugging/Inspecting Proxies and other ProtoObjects is barely supported by the current tools.
3 Can it be tested quickly?
No idea. Esteban A. Maringolo
2015-11-19 10:33 GMT+01:00 Guillermo Polito <guillermopolito@gmail.com>:
I know we can :) and I did some prototypes already as part of my thesis.
The question is if that is a design we *want* or not.
There is a misunderstanding. I am not talking about prototypes. The operations are in the production VM and are stable. That's why I say you can use it. There is no need to implement additional VM support to debug this kind of objects as it's already done and stable.
On 18 nov 2015, at 5:29 p.m., Clément Bera <bera.clement@gmail.com> wrote:
2015-11-18 8:43 GMT-03:00 Guillermo Polito <guillermopolito@gmail.com>:
Iâd like to discuss also the possibility to add those low level operations on mirrors objects, that could be packaged separately from the kernel of the language. Adding them on a first step is easy, then making all tools use them is the hard/timeconsuming part, yes.
All the needed operations already exist. You can put them on your mirror objects without any problem.
On 18 nov 2015, at 12:35 p.m., Clément Bera <bera.clement@gmail.com> wrote:
Hello,
This is known and was discussed on the bug tracker.
The problem is that currently Pharo has many tools and classes: EyeInspector in the debugger, GTInspector outside, the debugger itself, the in-image interpreter in the Context class ... that need to be changed to support debugging objects that basically cannot receive any message.
We are aware of the solution but fixing it for all the toolkits and classes is quite some work. In addition, if not tested, someone will break it because he won't understand that an inspected object can't receive any message because the expected behavior of an object with no DNU behavior and no methods inherited from Object is to freeze the system.
It's a lot of fun doing that though.
Clement
2015-11-17 21:39 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com>:
Hi Esteban,
On Tue, Nov 17, 2015 at 1:37 PM, Esteban A. Maringolo < emaringolo@gmail.com> wrote:
2015-11-17 14:37 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com>:
Hi Esteban,
I think EyeInspector needs to handle classes that don't inherit from Object specially. Instead of asking the instance it should ask the class. You should be able to use the Context methods for mirror primitives to extract state without sending messages to the instance. Then the special version of EyeInspector for ProtoObject subclasses can ask this like
Yes, an special inspector for ProtoObject subclasses would be required, but I couldn't find one already suited for this purpose.
(thisContext objectClass: object) isIndexable ifTrue: [size := thisContext objectSize: object]
I don't know if your code was meant to be accurate or just a guideline of how this could be implemented, but Context doesn't implement #objectClass: nor #objectSize:
Find attached. I think you'll find they are in the Spur version. You might think of back-porting their use in Context form Spur; that'll make the debugger able to handle proxies.
Basically both the Inspector and the Debugger's execution simulation
machinery need to treat encapsulators such as MessageArchiver with kid gloves. One *must not* cause inspecting or debugging to send messages through the encapsulator. Instead, all access to the object should be through primitives that don't send messages to the objects.
I know that dealing with Proxies and similar objects is tricky, I had to deal with my own subclasses of ProtoObject in Dolphin, but there the class implemented all that was needed to interact with the environment tools.
Hiwever, to me all this is a kind of black magic, I read the blue book years ago and can understand it, but I do understand it as I understand the mechanics of my car, however when it breaks down I take it to the specialist :)
Well, the thing to think of is that inside the VM objects are just a sequence of words, and the VM, while it sends messages, doesn't send messages to objects to update their state; it just accesses the state directly. So in an execution simulation method such as
Context methods for instruction decoding pushReceiverVariable: offset self push: (receiver instVarAt: offset + 1)
that will send the message instVarAt: to the receiver, and if the receiver is a proxy, that will go through the proixie's doesNotUnderstand: method and send instVarAt: the the object the proxy wraps, which won't do the right thing at all. Instead it needs to be written
Context methods for instruction decoding pushReceiverVariable: offset self push: (self object: receiver instVarAt: offset + 1)
which reaches into the object without sending any messages to it. I understand that this will appear in Spur, because I made it part of the bootstrap, but if I were you I would integrate these changes into the current version asap. The debugger won't work properly with proxies, encapsulators etc otherwise.
_,,,^..^,,,_ best, Eliot
On 19 nov 2015, at 5:46 p.m., Clément Bera <bera.clement@gmail.com> wrote:
2015-11-19 10:33 GMT+01:00 Guillermo Polito <guillermopolito@gmail.com <mailto:guillermopolito@gmail.com>>: I know we can :) and I did some prototypes already as part of my thesis.
The question is if that is a design we *want* or not.
There is a misunderstanding.
Nope :) I understood you well. And yes, you misunderstood my answer :P. I know that the VM already provides the necessary primitives and I know how to use them ^^.
I am not talking about prototypes. The operations are in the production VM and are stable. That's why I say you can use it.
I meant prototypes of mirrors on the image side. I know and used the primitives. The questions are if we want to have a mirror library, if we want core tools (such as the inspector) to use it instead of delegating reflective operations to objects. Also there are many different mirror designs we can come up with. The design I have in mind is pretty much aligned with the idea of mirrors that Camille has in mind where there are low level mirrors to manipulate objects as the VM know them, and then high level mirrors implementing the language concerns AND application specific mirrors. But then this kind of mirror implementation is a beast in itself :) Also, answering Stephan Eggermont below:
1 Is it an improvement on the current situation?
I believe it is. Mirrors allow to extract the reflective behavior in separate objects. With them we would be able to inspect instances of classes that have no methods at all. Moreover, it would clean up objectsâ API because there will be no more meta-level methods in the base classes. This would avoid name clashes like #name in metaclasses that was discussed the other day.
2 Is it blocking an improvement direction we want to take?
I do not completely understand the question. I just can say that I think having mirrors is an interesting direction.
3 Can it be tested quickly?
A basic mirror implementation that only exposes VM internals could be easy to implement and test. Adapting the eye inspector to use a mirror instead of a normal object is also fairly easy, at lest for a first implementation. Of course the question always is doing it for real: I do not know how much time would it take to make all tools work as well.
There is no need to implement additional VM support to debug this kind of objects as it's already done and stable.
On 18 nov 2015, at 5:29 p.m., Clément Bera <bera.clement@gmail.com <mailto:bera.clement@gmail.com>> wrote:
2015-11-18 8:43 GMT-03:00 Guillermo Polito <guillermopolito@gmail.com <mailto:guillermopolito@gmail.com>>: Iâd like to discuss also the possibility to add those low level operations on mirrors objects, that could be packaged separately from the kernel of the language. Adding them on a first step is easy, then making all tools use them is the hard/timeconsuming part, yes.
All the needed operations already exist. You can put them on your mirror objects without any problem.
On 18 nov 2015, at 12:35 p.m., Clément Bera <bera.clement@gmail.com <mailto:bera.clement@gmail.com>> wrote:
Hello,
This is known and was discussed on the bug tracker.
The problem is that currently Pharo has many tools and classes: EyeInspector in the debugger, GTInspector outside, the debugger itself, the in-image interpreter in the Context class ... that need to be changed to support debugging objects that basically cannot receive any message.
We are aware of the solution but fixing it for all the toolkits and classes is quite some work. In addition, if not tested, someone will break it because he won't understand that an inspected object can't receive any message because the expected behavior of an object with no DNU behavior and no methods inherited from Object is to freeze the system.
It's a lot of fun doing that though.
Clement
2015-11-17 21:39 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com <mailto:eliot.miranda@gmail.com>>: Hi Esteban,
On Tue, Nov 17, 2015 at 1:37 PM, Esteban A. Maringolo <emaringolo@gmail.com <mailto:emaringolo@gmail.com>> wrote: 2015-11-17 14:37 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com <mailto:eliot.miranda@gmail.com>>:
Hi Esteban,
I think EyeInspector needs to handle classes that don't inherit from Object specially. Instead of asking the instance it should ask the class. You should be able to use the Context methods for mirror primitives to extract state without sending messages to the instance. Then the special version of EyeInspector for ProtoObject subclasses can ask this like
Yes, an special inspector for ProtoObject subclasses would be required, but I couldn't find one already suited for this purpose.
(thisContext objectClass: object) isIndexable ifTrue: [size := thisContext objectSize: object]
I don't know if your code was meant to be accurate or just a guideline of how this could be implemented, but Context doesn't implement #objectClass: nor #objectSize:
Find attached. I think you'll find they are in the Spur version. You might think of back-porting their use in Context form Spur; that'll make the debugger able to handle proxies.
Basically both the Inspector and the Debugger's execution simulation machinery need to treat encapsulators such as MessageArchiver with kid gloves. One *must not* cause inspecting or debugging to send messages through the encapsulator. Instead, all access to the object should be through primitives that don't send messages to the objects.
I know that dealing with Proxies and similar objects is tricky, I had to deal with my own subclasses of ProtoObject in Dolphin, but there the class implemented all that was needed to interact with the environment tools.
Hiwever, to me all this is a kind of black magic, I read the blue book years ago and can understand it, but I do understand it as I understand the mechanics of my car, however when it breaks down I take it to the specialist :)
Well, the thing to think of is that inside the VM objects are just a sequence of words, and the VM, while it sends messages, doesn't send messages to objects to update their state; it just accesses the state directly. So in an execution simulation method such as
Context methods for instruction decoding pushReceiverVariable: offset self push: (receiver instVarAt: offset + 1)
that will send the message instVarAt: to the receiver, and if the receiver is a proxy, that will go through the proixie's doesNotUnderstand: method and send instVarAt: the the object the proxy wraps, which won't do the right thing at all. Instead it needs to be written
Context methods for instruction decoding pushReceiverVariable: offset self push: (self object: receiver instVarAt: offset + 1)
which reaches into the object without sending any messages to it. I understand that this will appear in Spur, because I made it part of the bootstrap, but if I were you I would integrate these changes into the current version asap. The debugger won't work properly with proxies, encapsulators etc otherwise.
_,,,^..^,,,_ best, Eliot
Hi guillermo I read the code long time ago and I'm busy with something else right now. What is the API with Mirrors? What is the corresponding Object API? Do we remove the API of Object? We can talk about that tomorrow. Stef
I took the time today to dive into this part, so you could use me as well in the discussion. Cheers, Doru
On Nov 19, 2015, at 9:18 PM, stepharo <stepharo@free.fr> wrote:
Hi guillermo
I read the code long time ago and I'm busy with something else right now. What is the API with Mirrors? What is the corresponding Object API? Do we remove the API of Object?
We can talk about that tomorrow.
Stef
-- www.tudorgirba.com "Every thing has its own flow."
Hi Guille,
On Nov 19, 2015, at 9:11 AM, Guillermo Polito <guillermopolito@gmail.com> wrote:
On 19 nov 2015, at 5:46 p.m., Clément Bera <bera.clement@gmail.com> wrote:
2015-11-19 10:33 GMT+01:00 Guillermo Polito <guillermopolito@gmail.com>:
I know we can :) and I did some prototypes already as part of my thesis.
The question is if that is a design we *want* or not.
There is a misunderstanding.
Nope :) I understood you well. And yes, you misunderstood my answer :P. I know that the VM already provides the necessary primitives and I know how to use them ^^.
I am not talking about prototypes. The operations are in the production VM and are stable. That's why I say you can use it.
I meant prototypes of mirrors on the image side. I know and used the primitives. The questions are if we want to have a mirror library, if we want core tools (such as the inspector) to use it instead of delegating reflective operations to objects. Also there are many different mirror designs we can come up with. The design I have in mind is pretty much aligned with the idea of mirrors that Camille has in mind where there are low level mirrors to manipulate objects as the VM know them, and then high level mirrors implementing the language concerns AND application specific mirrors. But then this kind of mirror implementation is a beast in itself :)
Good question. Let's be clear there are two issues here. One, that shouldn't be in doubt, is that Pharo should use the simple mirror primitives I provided that are already in the VM asap both to provide low level inspectors for proxies and to make the debugger/execution simulator correct. Note that process termination, where a high-priority process terminates a lower one, and end up invoking the execution simulation machinery in getting to a point where unwind blocks can be executed, so the correctness issue can bite in the base system, not just when debugging. The other issue is your question, should there be a proper set of mirror objects as described by Gilad Bracha. The rationale for proper mirrors is security; to avoid making dangerous primitives like instVarAt: and object:instVarAt: (not to mention allInstances, allObjects, class itself, etc etc) generally available so people can write secure code. This is a great rationale, and makes sense, but the current system is a /long/ way away from that. A truly secure system (meaning a single Smalltalk system which could allow untrusted Smalltalk scripts to run within it and not provide these scripts with the ability to break (into) code in the system) would require much more work than merely providing proper mirrors. The whole system of object access, method access, class manipulation needs to be implemented in a secure manner. That's a great long term project, but just adding mirrors is very far from enough. Our experience at Cadence where we have used the newspeak mirror system in a non secure squeak host, is that mirrors introduce a lot of complexity and performance overhead and so we've been eliminating their use. Our application provides an SOC domain model that used to be manipulated by mirrors, but we're phasing that out because it costs so much in performance. So my considered opinion is that we should not add proper mirrors to current Pharo, because we will pay the performance and complexity penalties but not get the security reward. Instead, there should be research projects on small simple systems that attempt to architect a usable secure Smalltalk environment, and when that architecture demonstrates its viability to port the architecture into Pharo. I think that's years away. HTH
Also, answering Stephan Eggermont below:
1 Is it an improvement on the current situation?
I believe it is. Mirrors allow to extract the reflective behavior in separate objects. With them we would be able to inspect instances of classes that have no methods at all.
Moreover, it would clean up objectsâ API because there will be no more meta-level methods in the base classes. This would avoid name clashes like #name in metaclasses that was discussed the other day.
2 Is it blocking an improvement direction we want to take?
I do not completely understand the question. I just can say that I think having mirrors is an interesting direction.
3 Can it be tested quickly?
A basic mirror implementation that only exposes VM internals could be easy to implement and test. Adapting the eye inspector to use a mirror instead of a normal object is also fairly easy, at lest for a first implementation. Of course the question always is doing it for real: I do not know how much time would it take to make all tools work as well.
There is no need to implement additional VM support to debug this kind of objects as it's already done and stable.
On 18 nov 2015, at 5:29 p.m., Clément Bera <bera.clement@gmail.com> wrote:
2015-11-18 8:43 GMT-03:00 Guillermo Polito <guillermopolito@gmail.com>:
Iâd like to discuss also the possibility to add those low level operations on mirrors objects, that could be packaged separately from the kernel of the language. Adding them on a first step is easy, then making all tools use them is the hard/timeconsuming part, yes.
All the needed operations already exist. You can put them on your mirror objects without any problem.
On 18 nov 2015, at 12:35 p.m., Clément Bera <bera.clement@gmail.com> wrote:
Hello,
This is known and was discussed on the bug tracker.
The problem is that currently Pharo has many tools and classes: EyeInspector in the debugger, GTInspector outside, the debugger itself, the in-image interpreter in the Context class ... that need to be changed to support debugging objects that basically cannot receive any message.
We are aware of the solution but fixing it for all the toolkits and classes is quite some work. In addition, if not tested, someone will break it because he won't understand that an inspected object can't receive any message because the expected behavior of an object with no DNU behavior and no methods inherited from Object is to freeze the system.
It's a lot of fun doing that though.
Clement
2015-11-17 21:39 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com>:
Hi Esteban,
On Tue, Nov 17, 2015 at 1:37 PM, Esteban A. Maringolo <emaringolo@gmail.com> wrote: 2015-11-17 14:37 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com>:
Hi Esteban,
I think EyeInspector needs to handle classes that don't inherit from Object specially. Instead of asking the instance it should ask the class. You should be able to use the Context methods for mirror primitives to extract state without sending messages to the instance. Then the special version of EyeInspector for ProtoObject subclasses can ask this like
Yes, an special inspector for ProtoObject subclasses would be required, but I couldn't find one already suited for this purpose.
(thisContext objectClass: object) isIndexable ifTrue: [size := thisContext objectSize: object]
I don't know if your code was meant to be accurate or just a guideline of how this could be implemented, but Context doesn't implement #objectClass: nor #objectSize:
Find attached. I think you'll find they are in the Spur version. You might think of back-porting their use in Context form Spur; that'll make the debugger able to handle proxies.
Basically both the Inspector and the Debugger's execution simulation machinery need to treat encapsulators such as MessageArchiver with kid gloves. One *must not* cause inspecting or debugging to send messages through the encapsulator. Instead, all access to the object should be through primitives that don't send messages to the objects.
I know that dealing with Proxies and similar objects is tricky, I had to deal with my own subclasses of ProtoObject in Dolphin, but there the class implemented all that was needed to interact with the environment tools.
Hiwever, to me all this is a kind of black magic, I read the blue book years ago and can understand it, but I do understand it as I understand the mechanics of my car, however when it breaks down I take it to the specialist :)
Well, the thing to think of is that inside the VM objects are just a sequence of words, and the VM, while it sends messages, doesn't send messages to objects to update their state; it just accesses the state directly. So in an execution simulation method such as
Context methods for instruction decoding pushReceiverVariable: offset self push: (receiver instVarAt: offset + 1)
that will send the message instVarAt: to the receiver, and if the receiver is a proxy, that will go through the proixie's doesNotUnderstand: method and send instVarAt: the the object the proxy wraps, which won't do the right thing at all. Instead it needs to be written
Context methods for instruction decoding pushReceiverVariable: offset self push: (self object: receiver instVarAt: offset + 1)
which reaches into the object without sending any messages to it. I understand that this will appear in Spur, because I made it part of the bootstrap, but if I were you I would integrate these changes into the current version asap. The debugger won't work properly with proxies, encapsulators etc otherwise.
_,,,^..^,,,_ best, Eliot
Hi eliot
Good question. Let's be clear there are two issues here. One, that shouldn't be in doubt, is that Pharo should use the simple mirror primitives I provided that are already in the VM asap both to provide low level inspectors for proxies and to make the debugger/execution simulator correct. Note that process termination, where a high-priority process terminates a lower one, and end up invoking the execution simulation machinery in getting to a point where unwind blocks can be executed, so the correctness issue can bite in the base system, not just when debugging.
The other issue is your question, should there be a proper set of mirror objects as described by Gilad Bracha. The rationale for proper mirrors is security; to avoid making dangerous primitives like instVarAt: and object:instVarAt: (not to mention allInstances, allObjects, class itself, etc etc) generally available so people can write secure code. This is a great rationale, and makes sense, but the current system is a /long/ way away from that. A truly secure system (meaning a single Smalltalk system which could allow untrusted Smalltalk scripts to run within it and not provide these scripts with the ability to break (into) code in the system) would require much more work than merely providing proper mirrors. The whole system of object access, method access, class manipulation needs to be implemented in a secure manner. That's a great long term project, but just adding mirrors is very far from enough.
Our experience at Cadence where we have used the newspeak mirror system in a non secure squeak host, is that mirrors introduce a lot of complexity and performance overhead and so we've been eliminating their use. Our application provides an SOC domain model that used to be manipulated by mirrors, but we're phasing that out because it costs so much in performance.
So my considered opinion is that we should not add proper mirrors to current Pharo, because we will pay the performance and complexity penalties but not get the security reward. Instead, there should be research projects on small simple systems that attempt to architect a usable secure Smalltalk environment, and when that architecture demonstrates its viability to port the architecture into Pharo. I think that's years away. Interesting. I have two questions: - what is the complexity you mentioned? To have an hierarchy of mirrors and calling the right now instead of a method?
- for the speed cost: What was it exactly? Creating a mirror and sending a message that will then apply the primitive to the object? I imagine that they are some scenarios - like manipulating a remote object or a different space where the cost should be small compared to other operations At cadence what were the use of mirrors? Stef
Guillermo knows them and uses them in all his PhD. It is not his point. He has question about the design induced by the use of Mirrors. Stef
Hi Clement, Do you know which is the issue that covers this? I remember complaining about dealing with Proxies in the debugger a year ago and getting a similar response. How does this play with the new "slot based" variables? Regards! Esteban A. Maringolo 2015-11-18 8:35 GMT-03:00 Clément Bera <bera.clement@gmail.com>:
Hello,
This is known and was discussed on the bug tracker.
The problem is that currently Pharo has many tools and classes: EyeInspector in the debugger, GTInspector outside, the debugger itself, the in-image interpreter in the Context class ... that need to be changed to support debugging objects that basically cannot receive any message.
We are aware of the solution but fixing it for all the toolkits and classes is quite some work. In addition, if not tested, someone will break it because he won't understand that an inspected object can't receive any message because the expected behavior of an object with no DNU behavior and no methods inherited from Object is to freeze the system.
It's a lot of fun doing that though.
Clement
2015-11-17 21:39 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com>:
Hi Esteban,
On Tue, Nov 17, 2015 at 1:37 PM, Esteban A. Maringolo <emaringolo@gmail.com> wrote:
2015-11-17 14:37 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com>:
Hi Esteban,
I think EyeInspector needs to handle classes that don't inherit from Object specially. Instead of asking the instance it should ask the class. You should be able to use the Context methods for mirror primitives to extract state without sending messages to the instance. Then the special version of EyeInspector for ProtoObject subclasses can ask this like
Yes, an special inspector for ProtoObject subclasses would be required, but I couldn't find one already suited for this purpose.
(thisContext objectClass: object) isIndexable ifTrue: [size := thisContext objectSize: object]
I don't know if your code was meant to be accurate or just a guideline of how this could be implemented, but Context doesn't implement #objectClass: nor #objectSize:
Find attached. I think you'll find they are in the Spur version. You might think of back-porting their use in Context form Spur; that'll make the debugger able to handle proxies.
Basically both the Inspector and the Debugger's execution simulation machinery need to treat encapsulators such as MessageArchiver with kid gloves. One *must not* cause inspecting or debugging to send messages through the encapsulator. Instead, all access to the object should be through primitives that don't send messages to the objects.
I know that dealing with Proxies and similar objects is tricky, I had to deal with my own subclasses of ProtoObject in Dolphin, but there the class implemented all that was needed to interact with the environment tools.
Hiwever, to me all this is a kind of black magic, I read the blue book years ago and can understand it, but I do understand it as I understand the mechanics of my car, however when it breaks down I take it to the specialist :)
Well, the thing to think of is that inside the VM objects are just a sequence of words, and the VM, while it sends messages, doesn't send messages to objects to update their state; it just accesses the state directly. So in an execution simulation method such as
Context methods for instruction decoding pushReceiverVariable: offset self push: (receiver instVarAt: offset + 1)
that will send the message instVarAt: to the receiver, and if the receiver is a proxy, that will go through the proixie's doesNotUnderstand: method and send instVarAt: the the object the proxy wraps, which won't do the right thing at all. Instead it needs to be written
Context methods for instruction decoding pushReceiverVariable: offset self push: (self object: receiver instVarAt: offset + 1)
which reaches into the object without sending any messages to it. I understand that this will appear in Spur, because I made it part of the bootstrap, but if I were you I would integrate these changes into the current version asap. The debugger won't work properly with proxies, encapsulators etc otherwise.
_,,,^..^,,,_ best, Eliot
Hi Elliot, 2015-11-17 21:39 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com>:
Hi Esteban,
On Tue, Nov 17, 2015 at 1:37 PM, Esteban A. Maringolo <emaringolo@gmail.com> wrote:
(thisContext objectClass: object) isIndexable ifTrue: [size := thisContext objectSize: object]
I don't know if your code was meant to be accurate or just a guideline of how this could be implemented, but Context doesn't implement #objectClass: nor #objectSize:
Find attached. I think you'll find they are in the Spur version. You might think of back-porting their use in Context form Spur; that'll make the debugger able to handle proxies.
I added your methods to Context and created a EyeProtoInspector class which uses the mirror methods to access the object size and class. So far it works, or at least doesn't give me walkbalks, but if you do a little more than that you'll get fireworks :)
I know that dealing with Proxies and similar objects is tricky, I had to deal with my own subclasses of ProtoObject in Dolphin, but there the class implemented all that was needed to interact with the environment tools.
Well, the thing to think of is that inside the VM objects are just a sequence of words, and the VM, while it sends messages, doesn't send messages to objects to update their state; it just accesses the state directly. So in an execution simulation method such as
[snip]
which reaches into the object without sending any messages to it. I understand that this will appear in Spur, because I made it part of the bootstrap, but if I were you I would integrate these changes into the current version asap. The debugger won't work properly with proxies, encapsulators etc otherwise.
Yes, it doesn't right now, but not only for the debugger, but the problem as stated in other mails is with the tools, that seems to be designed without considering these special cases. Regards! Esteban A. Maringolo
participants (8)
-
Clément Bera -
Eliot Miranda -
Esteban A. Maringolo -
Guillermo Polito -
Nicolas Cellier -
Stephan Eggermont -
stepharo -
Tudor Girba