[squeak-dev] Re: [Pharo-project] Prune stack serialization
Mariano Martinez Peck
marianopeck at gmail.com
Fri Dec 9 23:01:48 UTC 2011
Hi guys. When we implemented this possibility of pruning the closures when
they were clean, one of our crazy tests started to fail. It is not that the
test is very important, but I am interested in trying to understand why it
fails. The test (simplied) is:
| aSortedCollection materialized |
instanceVariableForTesting := false.
aSortedCollection := SortedCollection sortBlock: [:a :b |
instanceVariableForTesting
ifTrue: [ a <= b ]
ifFalse: [ a >= b ] ].
materialized := self resultOfSerializeAndMaterialize: aSortedCollection.
materialized addAll: #(2 3 1).
aSortedCollection addAll: #(2 3 1).
Well, the thing is that the materialized SortedCollection, it is sortBLock,
the closure is quite crazy and the 'instanceVariableForTesting' doesn't
have the boolean but instead a #Processor WTF?? So then the #addAll:
fails with a MustBeBoolean.
Do you think there is something I should check for this closure? I think
it may have to be related with the instanceVariable...
Just for the record, what we are doing is something like:
serializeReferencesOf: aBlockClosure with: aSerialization
1 to: aBlockClosure basicSize do: [ :index |
aSerialization encodeReferenceTo: (aBlockClosure basicAt: index) ].
aBlockClosure isClean
ifTrue: [
aSerialization stream nextPut: 1.
aSerialization encodeReferenceTo: aBlockClosure method.
aSerialization encodeReferenceTo: aBlockClosure receiver.
]
ifFalse: [
aSerialization stream nextPut: 0.
aSerialization encodeReferenceTo: aBlockClosure outerContext.
].
aSerialization encodeReferenceTo: aBlockClosure startpc.
aSerialization encodeReferenceTo: aBlockClosure numArgs.
-----
materializeReferencesOf: aBlockClosure with: aMaterialization
| methodOrContext method context |
1 to: aBlockClosure basicSize do: [ :index |
aBlockClosure basicAt: index put: (aMaterialization
nextEncodedReference).
].
(aMaterialization stream next = 1)
ifTrue: [ " it was a clean BlockClosure, otherwise it should have
been 0"
method := aMaterialization nextEncodedReference.
aBlockClosure
outerContext: (MethodContext
sender: nil
receiver: aMaterialization
nextEncodedReference
method: method
arguments: #() )
startpc: aMaterialization nextEncodedReference
numArgs: aMaterialization nextEncodedReference.
]
ifFalse: [
context := aMaterialization nextEncodedReference.
aBlockClosure
outerContext: context
startpc: aMaterialization nextEncodedReference
numArgs: aMaterialization nextEncodedReference].
-----
Thanks in advance!
On Sun, Dec 4, 2011 at 8:33 PM, Mariano Martinez Peck <marianopeck at gmail.com
> wrote:
> Thanks Juan. With the latest version of Eliot, the following are failing:
>
>
> self deny: [ | outerBlockTemp | [ outerBlockTemp printString ] isClean ]
> value.
> self deny: [ | outerBlockTemp | [ outerBlockTemp :=7 ] isClean ] value.
> self deny: [ tempVar + 1 ] isClean.
> self deny: [ tempVar := 1 ] isClean.
> self deny: [ ClassVar + 1 ] isClean.
> self deny: [ ClassVar := 1 ] isClean.
>
> Thanks
>
>
> On Sat, Dec 3, 2011 at 3:01 AM, Juan Vuletich <juan at jvuletich.org> wrote:
>
>> Eliot Miranda wrote:
>>
>>
>>>
>>> On Fri, Dec 2, 20Tha11 at 4:01 PM, Juan Vuletich <juan at jvuletich.org<mailto:
>>> juan at jvuletich.org>> wrote:
>>>
>>> Eliot Miranda wrote:
>>>
>>> Hi Juan,
>>>
>>> ...
>>>
>>>
>>>
>>> I can say that it does indeed work. But I'd be really
>>> grateful if
>>> Eliot took a good look at that code!
>>>
>>>
>>> There is a much better way, using
>>> InstructionStream>>**interpreetNextInstructionFor: which
>>> abstracts away from the bytecode encoding and allows one to
>>> simply use messages. e.g. look at
>>>
>>> and (SortedCollection sortBlock: [:a :b| a compare: b
>>> caseSensitive: false]) sortBlock abstractBytecodes evaluates to
>>>
>>> an OrderedCollection(#**pushTemporaryVariable:
>>> #pushTemporaryVariable: #pushConstant: #send:super:numArgs:)
>>>
>>> So a check for clean blocks would check for a block's
>>> abstractBytecodes not including some particular set of banned
>>> messages (which I *think* is pushReceiver
>>> pushReceiverVariable: popIntoReceiverVariable:
>>> storeIntoReceiverVariable: methodReturnConstant:
>>> methodReturnReceiver methodReturnTop).
>>>
>>> e.g.
>>>
>>> isClean
>>> ^(self abstractBytecodes intersection: #(pushReceiver
>>> pushReceiverVariable: popIntoReceiverVariable:
>>> storeIntoReceiverVariable: methodReturnConstant:
>>> methodReturnReceiver methodReturnTop)) isEmpty
>>>
>>>
>>> Cheers,
>>> Juan Vuletich
>>>
>>>
>>>
>>>
>>> -- best,
>>> Eliot
>>>
>>>
>>> Thanks Eliot. However, it looks to me that this needs more tweaking.
>>>
>>> <blush>Damn right :) I've done zero testing. It was just an
>>> example</blush>
>>>
>>> For instance, your method answers true for
>>> [ xx size ] isClean
>>> and
>>> [ ^ nil ] isClean
>>> while mine answers false for both. Maybe we could serialize non
>>> local returns using the Compiler (although we won't be able to
>>> return anywhere), but external variable acess is a problem.
>>>
>>> Will keep playing with this for a while...
>>>
>>>
>>> Can you (can I??) write some tests? What's xx in the above? Ah! [^nil]
>>> isn't clean in my code since it should be pc <= end, not pc < end!! Try
>>> the attached...
>>>
>>
>> This is a start:
>>
>> testIsClean
>> "
>> ClosureTests new testIsClean
>> "
>> | tempVar |
>> tempVar := 1.
>> self assert: [ 3 + 4 ] isClean.
>> self assert: [ :a | a * 2 ] isClean.
>> self assert: [ Smalltalk size ] isClean.
>> self assert: [ :blockArg | blockArg printString ] isClean.
>> self assert: [ | blockTemp | blockTemp printString ] isClean.
>> self assert: [ | blockTemp | blockTemp :=7 ] isClean.
>> self deny: [ | outerBlockTemp | [ outerBlockTemp printString ] isClean
>> ] value.
>> self deny: [ | outerBlockTemp | [ outerBlockTemp :=7 ] isClean ] value.
>> self deny: [ tempVar + 1 ] isClean.
>> self deny: [ tempVar := 1 ] isClean.
>> self deny: [ ivar + 1 ] isClean.
>> self deny: [ ivar := 1 ] isClean.
>> self deny: [ ^ true ] isClean.
>> self deny: [ self printString ] isClean.
>> self deny: [ ^ self ] isClean.
>> self deny: [ ClassVar + 1 ] isClean.
>> self deny: [ ClassVar := 1 ] isClean.
>>
>> This test passes with my implementation.
>>
>>
>>
>>>
>>> Cheers,
>>> Juan Vuletich
>>>
>>>
>>>
>>>
>>> --
>>> best,
>>> Eliot
>>>
>>>
>> Cheers,
>> Juan Vuletich
>>
>>
>
>
> --
> Mariano
> http://marianopeck.wordpress.com
>
>
--
Mariano
http://marianopeck.wordpress.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20111210/545ada0c/attachment.htm
More information about the Squeak-dev
mailing list
|