Problem understanding #cannotInterpret

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Problem understanding #cannotInterpret

Mariano Martinez Peck
 
Hi. There is something I don't understand about #cannotInterpret and maybe you can help me. Since I am not sure if this is more image side or vm, I did a cross post, sorry for that.
Context: I am implementing proxies for classes. Since I want that a proxy loads back the original object when receiving the message #class, I have removed from the compiler the shortcut bytecode for class, with this:

(ParseNode classVarNamed:  'StdSelectors') removeKey: #class ifAbsent: [].

Now, my testcase is something like this:

    | inst proxy |
    "This is the simplest test that does the less assert as possible."
    inst := ClassWith1Var new.
    self assert: inst foo = 'foo'.
    proxy := ClassProxyInstVar new.
    proxy become: ClassWith1Var.
    "here I can send any message, it is just to load back the original class"
    inst basicIdentityHash.
    self assert: (inst class == ClassWith1Var).
    self assert: inst foo = 'foo'.


ProtoObject subclass: #ClassProxyInstVar
    instanceVariableNames: 'superclass methodDict format actualClass'
    classVariableNames: ''
    poolDictionaries: ''
    category: 'Proxies'


ClassProxyInstVar >> initialize
    super initialize.
    superclass := ProxySuperclass.
    methodDict := nil.
    actualClass := self


So...with this i can use an instance of ClassProxyInstVar like a class. When an instance of the class receives a message, the methodDict will be in nil, and then the VM will send the #cannotInterpret. and there I want to put back the original class. Then I do:

ProxySuperclass >> cannotInterpret: aMessage
    Transcript cr;
        show: 'cannotInterpret:';
        space;
        show: aMessage selector..
    self class restore.
    ^aMessage sendTo: self

Now, this is working, but there is something I DO NOT UNSERSTAND. When I try to do the "inst basicIdentityHash" the VM will send the #cannotInterpret to ProxySuperclass because the methodDict was nil in ClassProxyInstVar. Ok, perfect. What I don't understand is how the method #cannotInterptet can be run perfeclty in this case, since I am doing a "self class restore" there. Remember I removed the shortcut bytecode, so #class is sent like any normal message. So, my question is, when sending "self class", why the VM doesn't call #cannotInterpter again like it did it when I did "   inst basicIdentityHash."  ?  in other words...why the VM isn't entering in a loop ?   There is something I am not seeing.

Thanks for any help in advance,

Mariano
Reply | Threaded
Open this post in threaded view
|

Re: Problem understanding #cannotInterpret

Igor Stasenko

AFAIK, #cannotInterpret: is sent to super

On 16 January 2011 11:50, Mariano Martinez Peck <[hidden email]> wrote:

>
> Hi. There is something I don't understand about #cannotInterpret and maybe you can help me. Since I am not sure if this is more image side or vm, I did a cross post, sorry for that.
> Context: I am implementing proxies for classes. Since I want that a proxy loads back the original object when receiving the message #class, I have removed from the compiler the shortcut bytecode for class, with this:
>
> (ParseNode classVarNamed:  'StdSelectors') removeKey: #class ifAbsent: [].
>
> Now, my testcase is something like this:
>
>     | inst proxy |
>     "This is the simplest test that does the less assert as possible."
>     inst := ClassWith1Var new.
>     self assert: inst foo = 'foo'.
>     proxy := ClassProxyInstVar new.
>     proxy become: ClassWith1Var.
>     "here I can send any message, it is just to load back the original class"
>     inst basicIdentityHash.
>     self assert: (inst class == ClassWith1Var).
>     self assert: inst foo = 'foo'.
>
>
> ProtoObject subclass: #ClassProxyInstVar
>     instanceVariableNames: 'superclass methodDict format actualClass'
>     classVariableNames: ''
>     poolDictionaries: ''
>     category: 'Proxies'
>
>
> ClassProxyInstVar >> initialize
>     super initialize.
>     superclass := ProxySuperclass.
>     methodDict := nil.
>     actualClass := self
>
>
> So...with this i can use an instance of ClassProxyInstVar like a class. When an instance of the class receives a message, the methodDict will be in nil, and then the VM will send the #cannotInterpret. and there I want to put back the original class. Then I do:
>
> ProxySuperclass >> cannotInterpret: aMessage
>     Transcript cr;
>         show: 'cannotInterpret:';
>         space;
>         show: aMessage selector..
>     self class restore.
>     ^aMessage sendTo: self
>
> Now, this is working, but there is something I DO NOT UNSERSTAND. When I try to do the "inst basicIdentityHash" the VM will send the #cannotInterpret to ProxySuperclass because the methodDict was nil in ClassProxyInstVar. Ok, perfect. What I don't understand is how the method #cannotInterptet can be run perfeclty in this case, since I am doing a "self class restore" there. Remember I removed the shortcut bytecode, so #class is sent like any normal message. So, my question is, when sending "self class", why the VM doesn't call #cannotInterpter again like it did it when I did "   inst basicIdentityHash."  ?  in other words...why the VM isn't entering in a loop ?   There is something I am not seeing.
>

check the bytecode of method. A special sends, which shortcutted using
different bytecode.

To avoid self sends, which will lead to infinite loop, you can use the
message's lookupClass to send message to class side:

aMessage lookupClass restore.

> Thanks for any help in advance,
>
> Mariano
>
>



--
Best regards,
Igor Stasenko AKA sig.
Reply | Threaded
Open this post in threaded view
|

Re: Problem understanding #cannotInterpret

Mariano Martinez Peck
 


On Sun, Jan 16, 2011 at 1:26 PM, Igor Stasenko <[hidden email]> wrote:

AFAIK, #cannotInterpret: is sent to super

yes, I know, this is why in my case I implemented that in the superclass.
 


>
> Now, this is working, but there is something I DO NOT UNSERSTAND. When I try to do the "inst basicIdentityHash" the VM will send the #cannotInterpret to ProxySuperclass because the methodDict was nil in ClassProxyInstVar. Ok, perfect. What I don't understand is how the method #cannotInterptet can be run perfeclty in this case, since I am doing a "self class restore" there. Remember I removed the shortcut bytecode, so #class is sent like any normal message. So, my question is, when sending "self class", why the VM doesn't call #cannotInterpter again like it did it when I did "   inst basicIdentityHash."  ?  in other words...why the VM isn't entering in a loop ?   There is something I am not seeing.
>

check the bytecode of method. A special sends, which shortcutted using
different bytecode.

Yes, but I disable them, by evaluating: "(ParseNode classVarNamed:  'StdSelectors') removeKey: #class ifAbsent: []."
 

To avoid self sends, which will lead to infinite loop, you can use the
message's lookupClass to send message to class side:

aMessage lookupClass restore.


This is a good trick!!!  This was really helpful Igor.

Anyway, now I found which was my problem. I mean, I understood why it was not causing a loop and was working instead. The thing is that I evaluated "(ParseNode classVarNamed:  'StdSelectors') removeKey: #class ifAbsent: []."  but then I check the the implemenation of #cannotInterpret and it was still using the shortcut bytecode for #class. Why ?  because I forget a Compiler recompileAll!!!!   hehehehe :)

thanks

Mariano
 

> Thanks for any help in advance,
>
> Mariano
>
>



--
Best regards,
Igor Stasenko AKA sig.