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
_______________________________________________
Pharo-project mailing list
[email protected]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project