[squeak-dev] Incomplete deoptimization of #ifNotNil: and #ifNotNil:ifNil:

J. Vuletich (mail lists) juanlists at jvuletich.org
Fri Feb 20 11:35:23 UTC 2015


Thanks Bert. Your fix works perfectly and is integrated into Cuis. I  
removed my previous change, allowing cascading of ifNil again.

Cheers,
Juan Vuletich

Quoting Bert Freudenberg <bert at freudenbergs.de>:

> Found the problem. Unlike the other optimizations, optimizing ifNil  
> replaces the original receiver of the MessageNode by {rcvr == nil}.  
> But it is not restored when deoptimizing.
>
> We can fix it easily by restoring the original receiver in  
> #ensureCanCascade:. I just did that in Compiler-bf.293.
>
> - Bert -
>
> On 19.02.2015, at 17:50, Bert Freudenberg <bert at freudenbergs.de> wrote:
>>
>> It looks like Eliot removed the check in 2011. Before that it read:
>>
>> canCascade
>> 	^(receiver == NodeSuper or: [special > 0]) not
>>
>> - Bert -
>>
>>> On 19.02.2015, at 17:35, J. Vuletich (mail lists)  
>>> <juanlists at jvuletich.org> wrote:
>>>
>>> Hi Levente,
>>>
>>> Thanks for raising this. I don't know how to fix it, but in Cuis,  
>>> I've just disabled these selectors in #canCascade (#ifNil: too,  
>>> even if not really needed). I recompiled the system afterwards  
>>> without error notifications. And I see no real value in this  
>>> coding style, so I see no downside in just disallowing it.
>>>
>>> Cheers,
>>> Juan Vuletich
>>>
>>> Quoting Levente Uzonyi <leves at elte.hu>:
>>>
>>>> Hi All,
>>>>
>>>> There's a bug in the compiler which should be easy to fix for  
>>>> someone familiar with the code.
>>>> The following expression returns #(nil nil true true) instead of  
>>>> #(nil nil nil nil):
>>>>
>>>> {
>>>> nil
>>>> 	ifNil: [ 1 ] ifNotNil: [ 2 ];
>>>> 	yourself.
>>>> nil
>>>> 	ifNil: [ 1 ];
>>>> 	yourself.
>>>> nil
>>>> 	ifNotNil: [ 2 ];
>>>> 	yourself.
>>>> nil
>>>> 	ifNotNil: [ 2 ] ifNil: [ 1 ];
>>>> 	yourself.
>>>> }
>>>>
>>>> The cause of the problem is that in case of #ifNotNil: and  
>>>> #ifNotNil:ifNil: the deoptimization doesn't clear all previously  
>>>> generated optimized bytecodes.
>>>> E.g. in case of #ifNotNil: instead of
>>>>
>>>> <73> pushConstant: nil
>>>> <88> dup
>>>> <8F 00 00 02> closureNumCopied: 0 numArgs: 0 bytes 33 to 34
>>>>   <76> pushConstant: 1
>>>>   <7D> blockReturn
>>>> <E0> send: ifNotNil:
>>>> <87> pop
>>>> <D1> send: yourself
>>>>
>>>> we get
>>>>
>>>> <73> pushConstant: nil
>>>> <73> pushConstant: nil
>>>> <C6> send: ==
>>>> <88> dup
>>>> <8F 00 00 02> closureNumCopied: 0 numArgs: 0 bytes 33 to 34
>>>>   <76> pushConstant: 1
>>>>   <7D> blockReturn
>>>> <E0> send: ifNotNil:
>>>> <87> pop
>>>> <D1> send: yourself
>>>>
>>>> It would be great to write some tests which cover all such cases  
>>>> (including other methods), but I'm not sure what form is the best  
>>>> for this. Simple tests which just verify some values? Or  
>>>> something that checks the generated bytecodes?
>>>>
>>>> Levente
>>
>>
>>
>>





More information about the Squeak-dev mailing list