Hi folks. I am trying to do something and I found a VM crash. Suppose I want to swap out a class, do a become with a proxy (that with the DNU will load the class back). In addition, I have instances of the swapped class. Example of code (will crash in the last line): o := MyObject new. o foo: 123. p := ClassProxy new. p become: MyObject. o == nil. o foo. My Object just extends Object, has an instVar 'foo', and implements the accessors. ClassProxy implements: become: aClass className := aClass name. aClass fileOut. super become: aClass and doesNotUnderstand: aMessage | reloadedClass | (FileStream fileNamed: className, '.st') fileIn. reloadedClass := Smalltalk at: className. self becomeForward: reloadedClass. ^aMessage sendTo: reloadedClass So....does someone know why the crash? how can I solve it ? Thanks in advance Mariano |
On 28.09.2010, at 22:29, Mariano Martinez Peck wrote: Hi folks. I am trying to do something and I found a VM crash. Suppose I want to swap out a class, do a become with a proxy (that with the DNU will load the class back). In addition, I have instances of the swapped class. Looks like o's class pointer does not point to a class after the become. When the VM tries to lookup #foo in o's class it crashes. how can I solve it ? I'd say you cannot get rid of a class if there are still instances of it. You can stub out the class however. If the method dict is nil, the VM will send cannotInterpret: if you send a message to an instance. You should be able to use that instead of #doesNotUnderstand:. - Bert - |
Here it is. Just be aware, that its not intercepting all messages. Some messages like #== or #class is early bound by compiler/VM, so even if you redefine them, their behavior won't be changed. (I forgot where to get the list of these exceptional selectors). Smalltalk specialSelectors seems like not the same thing. On 28 September 2010 23:48, Bert Freudenberg <[hidden email]> wrote: > > > On 28.09.2010, at 22:29, Mariano Martinez Peck wrote: > > Hi folks. I am trying to do something and I found a VM crash. Suppose I want to swap out a class, do a become with a proxy (that with the DNU will load the class back). In addition, I have instances of the swapped class. > > Example of code (will crash in the last line): > > o := MyObject new. > o foo: 123. > p := ClassProxy new. > p become: MyObject. > o == nil. > o foo. > > > My Object just extends Object, has an instVar 'foo', and implements the accessors. > > ClassProxy implements: > > become: aClass > className := aClass name. > aClass fileOut. > super become: aClass > > and > > doesNotUnderstand: aMessage > | reloadedClass | > (FileStream fileNamed: className, '.st') fileIn. > reloadedClass := Smalltalk at: className. > self becomeForward: reloadedClass. > ^aMessage sendTo: reloadedClass > > > So....does someone know why the crash? > > Looks like o's class pointer does not point to a class after the become. When the VM tries to lookup #foo in o's class it crashes. > > how can I solve it ? > > I'd say you cannot get rid of a class if there are still instances of it. You can stub out the class however. If the method dict is nil, the VM will send cannotInterpret: if you send a message to an instance. You should be able to use that instead of #doesNotUnderstand:. > - Bert - > > > -- Best regards, Igor Stasenko AKA sig. MessageCatchingProxy.st (1K) Download Attachment |
In reply to this post by Mariano Martinez Peck
On Tue, Sep 28, 2010 at 1:29 PM, Mariano Martinez Peck <[hidden email]> wrote:
I'm not sure but here are some possible reasons...
1. you didn't flush the method lookup cache after doing the becomeForward: and the perform in sentTo: found a stale method and boom. 2. you became from a class with N inst vars to one with N+M inst vars and the methods of the new class accessed inst vars > N which are off the end of your instance, causing the VM to read invalid oops and boom.
So a) always flush the method lookup cache and b) /never/ cause the VM to read past an object by changing the class underneath an object such that the class accesses more inst vars than the instance has.
|
On Wed, Sep 29, 2010 at 3:42 AM, Eliot Miranda <[hidden email]> wrote:
Thanks Eliot. I was checking the code of the become in #primitiveArrayBecome and it seems that in #mapPointersInObjectsFrom: self startOfMemory to: they do the "self flushMethodCacheFrom: memStart to: memEnd." Anyway, I tried it with | o p | o := MyClass new. o foo: 123. p := ClassProxy new. p become: MyClass. MyClass flushCache. ClassProxy flushCache. o == nil. Transcript show: o class name; cr. o foo. but same results. Now, something interesting is that "Transcript show: o class name; cr." prints "MyClass". Is this correct?
My case is even more complicated. I want to become from a CLASS to an INSTANCE. I mean, I want to become the class MyClass with AN INSTANCE of PROXY CLASS. Then the proxy class uses te DNU to bring the other back. Now I was thinking that maybe the proxy class should not extend from ProtoObject but from Behavior or similar? But I want smaller objects...I don't want to spend instances in "uperclass methodDict format'" since the only thing I have to do is with DNU bring back other object. Finally, I have a question. I tried to look at the #become but I didn't get it... When I do a become from a class to an object for example, if there were (normal) pointers (slots in other objects) to that class, then they are updated and point to the other object. However, what happens with the instances of that class? is the class pointer in their object header consider like a normal pointer? are those piointers updated also by the #become? Maybe they are not and this is why "Transcript show: o class name; cr." prints "MyClass" ? Sorry for the newbie question...I am learning all this... Cheers Mariano
|
Grrrrr no, sorry, that's not true...can you believe there was a " Transcript cr; show: self name. " in the fileout code ? heheheh Now I changed the proxy to extends Class (to see if it works) and at least it doesn't crash. "Transcript show: o class name; cr. " prints "a subclass of Object" and after the evaluation of the code, I get the error: MessageNotUnderstood: a subclass of Object>>foo mmmmm I will continue investigating....
|
On Wed, Sep 29, 2010 at 2:25 PM, Mariano Martinez Peck <[hidden email]> wrote:
Something interesting is that after evaluating that code, and recieving the error, MyClass which was: Object subclass: #MyClass instanceVariableNames: 'foo' classVariableNames: '' poolDictionaries: '' category: 'Proxies' now it is: Object subclass: 'a subclass of Object' instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'nil' weird.... thanks! mariano
|
In reply to this post by Igor Stasenko
On Tue, Sep 28, 2010 at 11:12 PM, Igor Stasenko <[hidden email]> wrote:
Thanks Igor. I am trying to understand your code. Now...how I should use MessageCatchingProxy ? how can I adapt this code to use your proxy? | o p | o := MyClass new. o foo: 123. p := ClassProxy3 new. p become: MyClass. MyClass flushCache. ClassProxy3 flushCache. o == nil. Transcript show: o class name; cr. o foo. thanks a lot mariano (I forgot where to get the list of these exceptional selectors).
|
In reply to this post by Igor Stasenko
On Tue, Sep 28, 2010 at 11:12 PM, Igor Stasenko <[hidden email]> wrote:
Thanks Igor. I am trying to understand your code. Now...how I should use MessageCatchingProxy ? how can I adapt this code to use your proxy? | o p | o := MyClass new. o foo: 123. p := ClassProxy3 new. MessageCatchingProxy wrap_ p become: MyClass. MyClass flushCache. ClassProxy3 flushCache. o == nil. Transcript show: o class name; cr. o foo. (I forgot where to get the list of these exceptional selectors). I would love to know this as well. Thanks Mariano
|
In reply to this post by Mariano Martinez Peck
On 29 September 2010 16:12, Mariano Martinez Peck <[hidden email]> wrote: > > > > On Tue, Sep 28, 2010 at 11:12 PM, Igor Stasenko <[hidden email]> wrote: >> >> >> Here it is. >> Just be aware, that its not intercepting all messages. >> Some messages like #== or #class is early bound by compiler/VM, >> so even if you redefine them, their behavior won't be changed. >> > > Thanks Igor. I am trying to understand your code. > Now...how I should use MessageCatchingProxy ? > > how can I adapt this code to use your proxy? > where you can send a message to other object or do something else. Then you can wrap some object with it: wrapped := MyProxy wrap: myclass. > | o p | > o := MyClass new. > o foo: 123. > p := ClassProxy3 new. > p become: MyClass. > MyClass flushCache. > ClassProxy3 flushCache. > o == nil. > Transcript show: o class name; cr. > o foo. > > > thanks a lot > > mariano > > >> >> (I forgot where to get the list of these exceptional selectors). >> Smalltalk specialSelectors seems like not the same thing. > > > > >> >> On 28 September 2010 23:48, Bert Freudenberg <[hidden email]> wrote: >> > >> > >> > On 28.09.2010, at 22:29, Mariano Martinez Peck wrote: >> > >> > Hi folks. I am trying to do something and I found a VM crash. Suppose I want to swap out a class, do a become with a proxy (that with the DNU will load the class back). In addition, I have instances of the swapped class. >> > >> > Example of code (will crash in the last line): >> > >> > o := MyObject new. >> > o foo: 123. >> > p := ClassProxy new. >> > p become: MyObject. >> > o == nil. >> > o foo. >> > >> > >> > My Object just extends Object, has an instVar 'foo', and implements the accessors. >> > >> > ClassProxy implements: >> > >> > become: aClass >> > className := aClass name. >> > aClass fileOut. >> > super become: aClass >> > >> > and >> > >> > doesNotUnderstand: aMessage >> > | reloadedClass | >> > (FileStream fileNamed: className, '.st') fileIn. >> > reloadedClass := Smalltalk at: className. >> > self becomeForward: reloadedClass. >> > ^aMessage sendTo: reloadedClass >> > >> > >> > So....does someone know why the crash? >> > >> > Looks like o's class pointer does not point to a class after the become. When the VM tries to lookup #foo in o's class it crashes. >> > >> > how can I solve it ? >> > >> > I'd say you cannot get rid of a class if there are still instances of it. You can stub out the class however. If the method dict is nil, the VM will send cannotInterpret: if you send a message to an instance. You should be able to use that instead of #doesNotUnderstand:. >> > - Bert - >> > >> > >> > >> >> >> >> -- >> Best regards, >> Igor Stasenko AKA sig. >> > > > -- Best regards, Igor Stasenko AKA sig. |
Free forum by Nabble | Edit this page |