On 05.08.2009, at 12:08, Stéphane Ducasse wrote:
I did that in pharo 211 and it worked.
Yes, that was before closures.
MethodContext allInstances size 2309
with the blockClosures, creation of method contexts happes far more frequently than it used to. (as both closures and methods use the same context objects)
It of course could be a sign that it happens actually too much.
I stopped in the image that did not crash yet at a couple of billions :)
Yes, but not "too much" in this sense. When creating new instances while counting them, the case "no problem" and "endless loop" are very close together... a very tiny increase, or even just a change in context-creation behavior could trigger the case that it creates too many contexts. This is one possbility: the change in creation pattern cause the problem, nothing to worry about. So let see. It used to be that block-context where created by sending blockCopy: to thiscontext: 13 <89> pushThisContext: 14 <75> pushConstant: 0 15 <C8> send: blockCopy: 16 <A4 02> jumpTo: 20 18 <73> pushConstant: nil 19 <7D> blockReturn 20 <87> pop 21 <78> returnSelf Now, the same code reads like this: 13 <8F 00 00 02> closureNumCopied: 0 numArgs: 0 bytes 17 to 18 17 <73> pushConstant: nil 18 <7D> blockReturn 19 <87> pop 20 <78> returnSelf and the closureNumCopied bytecode creates a BlockClosure object which is *not* the context. The context is later created when evaluating the Closure. So the time *when* an allocation of a new context may happen changed fundamtally. If we now look at the code for getting allinstances: allInstances "Answer a collection of all current instances of the receiver." | all | all := OrderedCollection new. self allInstancesDo: [:x | x == all ifFalse: [all add: x]]. ^ all asArray (allInstancesDo: is carefully written to not use any real blocks, just inlined ones). So the context for the block was created just once, before calling #llInstancesDo: Bytecode: 29 <40> pushLit: OrderedCollection 30 <CC> send: new 31 <68> popIntoTemp: 0 32 <70> self 33 <89> pushThisContext: 34 <76> pushConstant: 1 35 <C8> send: blockCopy: 36 <A4 0B> jumpTo: 49 .... and so on. Now with the Closures, it evaluates the closure in allInstancesDo:, leading for the closure VM to a potential allocation of a context in the execution of allInstancesDo: (and for each eval, it´s a loop). So we now have potentiall allocations of new instances of methodcontext when iterating over the existing ones. --> race condition. Marcus -- Marcus Denker - http://marcusdenker.de PLEIAD Lab - Computer Science Department (DCC) - University of Chile