Hi!
I'm trying to shrink a 3.7-5989 image a little bit. Well, everything goes fine until I want to quit the image. Then I get the following error message on the console window:
Recursive not understood error encountered
1098846384 [] in CommandHistory class>forgetAllGrabCommandsFrom: 1098845824 BlockContext>on:do: 1098845356 BlockContext>ifError: 1098844784 CommandHistory class>forgetAllGrabCommandsFrom: 1098844600 CommandHistory class>resetAllHistory 1098844196 CommandHistory class>DoIt 1098826088 Compiler>evaluate:in:to:notifying:ifFail:logged: 1098826576 [] in ParagraphEditor>evaluateSelection 1098825892 BlockContext>on:do: 1098825156 ParagraphEditor>evaluateSelection 1098825064 ParagraphEditor>doIt 1098825340 [] in ParagraphEditor>doIt: [...]
I examined the #forgetAllGrabCommandsFrom: method. It has an error handler. I added "self halt." to it. But this does not bring up the debugger nor does it change anything else. So what can I do to find the culprit?
By the way, why do we iterate over all objects here instead of using Morph allSubInstancesDo: [...]?
Martin
Hi!
This is actually a followup to my message "Error in CommandHistory>>#forgetAllGrabCommandsFrom:Am Wednesday". I'm still trying to find out what's going on. What I can say is that I can reliably create an object that is somehow broken. Maybe my usage of Object>>becomeForward: is wrong? After removing some classes I do:
Smalltalk obsoleteClasses do: [ :c | c allInstancesDo: [ :i | i becomeForward: nil ] ]. Smalltalk obsoleteClasses do: [ :c | c becomeForward: nil ].
After that the image is broken. I tried with 3.7 and 3.8beta. The effect is always the same.
I tried to start the VM simulation to inspect the situation when the error occurs. But when I start the simulation I always get the following error (regardless of the image I use):
Error: subscript is out of bounds: 0
Array(Object)>>errorSubscriptBounds: Array(Object)>>at: InterpreterSimulatorLSB(Interpreter)>>functionPointerFor:inClass: InterpreterSimulatorLSB(Interpreter)>>addNewMethodToCache InterpreterSimulatorLSB(Interpreter)>>internalFindNewMethod InterpreterSimulatorLSB(Interpreter)>>commonSend InterpreterSimulatorLSB(Interpreter)>>normalSend InterpreterSimulatorLSB(Interpreter)>>secondExtendedSendBytecode InterpreterSimulatorLSB(InterpreterSimulator)>>dispatchOn:in: InterpreterSimulatorLSB(InterpreterSimulator)>>test
Any help is welcome.
Martin
10 November 2004 15:16 schrieb Martin Kuball:
Hi!
I'm trying to shrink a 3.7-5989 image a little bit. Well, everything goes fine until I want to quit the image. Then I get the following error message on the console window:
Recursive not understood error encountered
1098846384 [] in CommandHistory class>forgetAllGrabCommandsFrom: 1098845824 BlockContext>on:do: 1098845356 BlockContext>ifError: 1098844784 CommandHistory class>forgetAllGrabCommandsFrom: 1098844600 CommandHistory class>resetAllHistory 1098844196 CommandHistory class>DoIt 1098826088 Compiler>evaluate:in:to:notifying:ifFail:logged: 1098826576 [] in ParagraphEditor>evaluateSelection 1098825892 BlockContext>on:do: 1098825156 ParagraphEditor>evaluateSelection 1098825064 ParagraphEditor>doIt 1098825340 [] in ParagraphEditor>doIt: [...]
I examined the #forgetAllGrabCommandsFrom: method. It has an error handler. I added "self halt." to it. But this does not bring up the debugger nor does it change anything else. So what can I do to find the culprit?
By the way, why do we iterate over all objects here instead of using Morph allSubInstancesDo: [...]?
Martin
Am 12.11.2004 um 21:42 schrieb Martin Kuball:
I tried to start the VM simulation to inspect the situation when the error occurs. But when I start the simulation I always get the following error (regardless of the image I use):
Error: subscript is out of bounds: 0
Array(Object)>>errorSubscriptBounds: Array(Object)>>at: InterpreterSimulatorLSB(Interpreter)>>functionPointerFor:inClass: InterpreterSimulatorLSB(Interpreter)>>addNewMethodToCache InterpreterSimulatorLSB(Interpreter)>>internalFindNewMethod InterpreterSimulatorLSB(Interpreter)>>commonSend InterpreterSimulatorLSB(Interpreter)>>normalSend InterpreterSimulatorLSB(Interpreter)>>secondExtendedSendBytecode InterpreterSimulatorLSB(InterpreterSimulator)>>dispatchOn:in: InterpreterSimulatorLSB(InterpreterSimulator)>>test
Any help is welcome.
The vm simulator is broken for some time now. This is a known problem, and I think that Dan and Ian have fixed the simulator for the 64bit Squeak project. So as soon as that is folded back in the main line, we will have a working simulator again.
Marcus
Hi!
Still working on this image shrinking problem I reported.
After changing all instances of all obsolete classes to nil, some of those classes are gone. When I try to "nil" the remaining obsolete classes, the follwoing two
AnObsoleteAlignmentMorphBob1 AnObsoleteEventMessageSet
result in a corrupted object memory when I send them a becomeForward: nil message. Maybe I should not send such a message to a class object? But than, how do I get rid of these obsolete classes?
Martin
Martin Kuball MartinKuball@web.de wrote:
After changing all instances of all obsolete classes to nil, some of those classes are gone. When I try to "nil" the remaining obsolete classes, the follwoing two
AnObsoleteAlignmentMorphBob1 AnObsoleteEventMessageSet
result in a corrupted object memory when I send them a becomeForward: nil message. Maybe I should not send such a message to a class object? But than, how do I get rid of these obsolete classes?
It's not good that you get a memory corruption in this case but it's very not-good to try to get rid of objects by any sort of become trickery. Find the objects pointing to them and use an inspector (or even send messages! What a concept :-) to nil out those pointers. The offending unwanted objects will then disappear.
If you provide some code to illustrate how the OM gets corrupted we can try to debug it. I recently did soem work on stopping objectA become: objectA crashes and it's conceivable this is related.
tim -- Tim Rowledge, tim@sumeru.stanford.edu, http://sumeru.stanford.edu/tim Useful random insult:- Brain like a hard drive with no read/write head.
Am Thursday 18 November 2004 22:54 schrieb Tim Rowledge:
Martin Kuball MartinKuball@web.de wrote:
After changing all instances of all obsolete classes to nil, some of those classes are gone. When I try to "nil" the remaining obsolete classes, the follwoing two
AnObsoleteAlignmentMorphBob1 AnObsoleteEventMessageSet
result in a corrupted object memory when I send them a becomeForward: nil message. Maybe I should not send such a message to a class object? But than, how do I get rid of these obsolete classes?
It's not good that you get a memory corruption in this case but it's very not-good to try to get rid of objects by any sort of become trickery. Find the objects pointing to them and use an inspector (or even send messages! What a concept :-) to nil out those pointers. The offending unwanted objects will then disappear.
If you provide some code to illustrate how the OM gets corrupted we can try to debug it. I recently did soem work on stopping objectA become: objectA crashes and it's conceivable this is related.
Well easy. Take a fresh 3.7 image and open a Workspace. Execute the folowing:
SystemOrganization removeCategoriesMatching: 'Morphic-Experimental'. Smalltalk obsoleteClasses do: [ :c | c allInstancesDo: [ :i | i becomeForward: nil ] ]. (Smalltalk obsoleteClasses at: 2) becomeForward: nil.
Now try save+quit the image. It will fail. Or you can do this:
object := true someObject. [0 == object] whileFalse: [object := object nextObject].
This will trigger the error.
Martin
martin I did not check carefully so I may totally wrong but in VW x become: nil was a documented mistake
x become: String new was suggested. else everything was pointing to nil :)
Now the becomeForward: of squeak has different sematnics than the become of visualworks and is equivalent to oneWayBecome:
Stef
On 20 nov. 04, at 13:27, Martin Kuball wrote:
Am Thursday 18 November 2004 22:54 schrieb Tim Rowledge:
Martin Kuball MartinKuball@web.de wrote:
After changing all instances of all obsolete classes to nil, some of those classes are gone. When I try to "nil" the remaining obsolete classes, the follwoing two
AnObsoleteAlignmentMorphBob1 AnObsoleteEventMessageSet
result in a corrupted object memory when I send them a becomeForward: nil message. Maybe I should not send such a message to a class object? But than, how do I get rid of these obsolete classes?
It's not good that you get a memory corruption in this case but it's very not-good to try to get rid of objects by any sort of become trickery. Find the objects pointing to them and use an inspector (or even send messages! What a concept :-) to nil out those pointers. The offending unwanted objects will then disappear.
If you provide some code to illustrate how the OM gets corrupted we can try to debug it. I recently did soem work on stopping objectA become: objectA crashes and it's conceivable this is related.
Well easy. Take a fresh 3.7 image and open a Workspace. Execute the folowing:
SystemOrganization removeCategoriesMatching: 'Morphic-Experimental'. Smalltalk obsoleteClasses do: [ :c | c allInstancesDo: [ :i | i becomeForward: nil ] ]. (Smalltalk obsoleteClasses at: 2) becomeForward: nil.
Now try save+quit the image. It will fail. Or you can do this:
object := true someObject. [0 == object] whileFalse: [object := object nextObject].
This will trigger the error.
Martin
Am Sunday 21 November 2004 19:41 schrieb stéphane ducasse:
martin I did not check carefully so I may totally wrong but in VW x become: nil was a documented mistake
I do not know VW. And I can't remember where I read about this becomeForward trick to get rid of unwanted stuff. But I agree that it is actually the wrong way to deal with the problem of unwanted references.
x become: String new was suggested. else everything was pointing to nil
:)
Now the becomeForward: of squeak has different sematnics than the become of visualworks and is equivalent to oneWayBecome:
Which means?
Martin
On 22 nov. 04, at 11:31, Martin Kuball wrote:
Am Sunday 21 November 2004 19:41 schrieb stéphane ducasse:
martin I did not check carefully so I may totally wrong but in VW x become: nil was a documented mistake
Because in VW after xxx become: nil all the xxx would refer to nil and in that case will not be garbaged anymore and all the variables pointing to nil will then point to xxx.
I do not know VW. And I can't remember where I read about this becomeForward trick to get rid of unwanted stuff. But I agree that it is actually the wrong way to deal with the problem of unwanted references.
x become: String new was suggested. else everything was pointing to nil
:)
Now the becomeForward: of squeak has different sematnics than the become of visualworks and is equivalent to oneWayBecome:
VW become is symetric this is a real atomic swap of reference. VWOneway is similar to becomeForward: because only the the arg reference.
Stef
After some investigation I'm pretty convinced that this isn't a problem with become*. What happens is that doing a becomeForward: nil on any class with an instance will cause trouble for pretty obvious reasons; you send said instance a message - any message - and the vm will find no possible method. Then it tries to send #doesNotUnderstand: to the object, finds no possible method and exits because of a recursive doesNotUnderstand.
For example in an image with the VMMaker stuff installed I did |foo| foo := CArray new. CArray becomeForward: nil. foo and printIt, which obviously sends a message to foo to print. KAboom. The vm error log shows a recursive dNU as expected.
In the particular case of Martin's problem I think we get the second order effect - an obsolete class has an obsolete super class that just happens to be the one nillified and so sending any message to that obsolete class (which means it has an empty methodDict) involves sending to its superclass, which is now nil, and thus the cycle of desperation begins.
Could we do anything to prevent this? I suppose one might do sometinhg demented like making thevm decide that a nil class means 'treat as protoObject' but personally I say the proper response is 'dont do that'. #become: is dangerous. #becomeForward: is just plain idiotic. At least nobody has done #becomeBackward: - so far.
tim -- Tim Rowledge, tim@sumeru.stanford.edu, http://sumeru.stanford.edu/tim Strange OpCodes: BFM: Branch on Full Moon
After some investigation I'm pretty convinced that this isn't a problem with become*. What happens is that doing a becomeForward: nil on any class with an instance will cause trouble for pretty obvious reasons; you send said instance a message - any message - and the vm will find no possible method. Then it tries to send #doesNotUnderstand: to the object, finds no possible method and exits because of a recursive doesNotUnderstand.
I was recently writing some tests for becomeForward: because we will present it in a lecture and I noticed after some experimentations that the image was getting really slow. So may be this is related. In my case I trashed the image and reloaded my good (without strange experiences).
For example in an image with the VMMaker stuff installed I did |foo| foo := CArray new. CArray becomeForward: nil. foo and printIt, which obviously sends a message to foo to print. KAboom. The vm error log shows a recursive dNU as expected.
In the particular case of Martin's problem I think we get the second order effect - an obsolete class has an obsolete super class that just happens to be the one nillified and so sending any message to that obsolete class (which means it has an empty methodDict) involves sending to its superclass, which is now nil, and thus the cycle of desperation begins.
Could we do anything to prevent this? I suppose one might do sometinhg demented like making thevm decide that a nil class means 'treat as protoObject' but personally I say the proper response is 'dont do that'. #become: is dangerous. #becomeForward: is just plain idiotic. At least nobody has done #becomeBackward: - so far.
tim
Tim Rowledge, tim@sumeru.stanford.edu, http://sumeru.stanford.edu/tim Strange OpCodes: BFM: Branch on Full Moon
This is getting very ugly. The fix to the vm to make the become prims fail if atempting to do a become a cause the a becomeForward a to also fails - and that stops the SM (re)loading problem reported elsewhere.
I'm a bit surprised that a becomeForward a works - or that anyone would try it even - but the IamgeSegment loading code seems to rely on it. That makes this a quite important bug.
Just for fun, consider {a. a} become {b. b} and {a. a} becomeForward {b. b}.
Some of the problems could be solved in methods but that would leave older images in danger; though no worse of than now. Some could be fixed in the vm. All of them are pretty mind mangling to trace through to work out what is going on...
tim -- Tim Rowledge, tim@sumeru.stanford.edu, http://sumeru.stanford.edu/tim Everybody needs a little love sometime; stop hacking and fall in love!
Hello Tim,
Thursday, November 25, 2004, 4:59:20 PM, you wrote:
TR> All of them are pretty mind mangling to trace through to TR> work out what is going on...
Yes, it is so hard to work when distinctions are created out of nothing or are destroyed forever. Humans don't like that one bit.
Andres.
Hokay, after some head-scratching, debugging and experimenting I have an explanation of why 'a become a' will blow the VM, why 'a forwardBecome a' is ok and a plausible fix.
The key problem is that building the forwarding blocks used (along with the compaction phase of the garbage collector) is not idempotent - the first time it is done for an object _corrupts_ that object and stores restoration info in the forwarding block. That's how the compaction works. However, refer to the same object in a become so that you need to build another forwarding block and you're violatin' th'law, boy. You end up with the poor object owning a forwarding block with a completely evil set of bits. When it comes to the compacting code's turn to do its job the excrement impacts the rotating impeller since insted of a nice object header word it stumbles over a mangled pointer with extra fries, err, flags.
So now we can see why 'a become 'a fails - two forwarding blocks for one object, and why 'a forwardBecome a' is ok - only one block is built per forwared object. Note that we will also get into trouble if any attempt is made to do {a.b} become {b.a} because of two forwarding blocks for both a & b. Likewise, expect problems with {a. a} becomeForward {b. c}. I doubt anyone would deliberately write either case but code using the become facility might easily end up doing so; for example ImageSegment loading seems to often do 'a becomeForward a' type mutations. If it happens that an object is refered to twice in that process, ka-boom.
The initial VM fix for the failure of 'a become a' was to fail the prim but that stopped SqueakMap from loading because of the ImageSegment issue mentioned above. My revised suggestion works somewhat better and simply skips the a=>a pairs in the become prim loop. This means that there is some time 'wasted' in such cases but at least it is cpu time and not frustrated user time. The fix DOES NOT prevent problems such as {a. a} becomeForward {b. c}. which I strongly think would be better caught upfront in the image. In general I don't see any meaningful reason to allow things like {a.b} become {b.a}
tim -- Tim Rowledge, tim@sumeru.stanford.edu, http://sumeru.stanford.edu/tim Strange OpCodes: JSP: Jump on Sexy Programmer
squeak-dev@lists.squeakfoundation.org