[squeak-dev] inlining repeat and the decompiler (Compiler-nice.186)

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Sat Apr 2 17:36:28 UTC 2011


I tried

fibonacciSequence
"Yields an infinite sequence of fibonacci numbers."
^ Generator on: [ :generator |
| a b |
a := 0. b := 1.
[ a := b + (b := a).
 generator yield: a ]
repeat; yourself ]

and it decompiled normally after Compiler-nice.205

It also works if I redefine

MessageNode>>transformRepeat: encoder
	"answer true if this #repeat message can be optimized"
	^false

then recompile and decompile fibonacciSequence

Nicolas

2011/4/2 Nicolas Cellier <nicolas.cellier.aka.nice at gmail.com>:
> Ah simple, ensureCanCascade did not deoptimize the receiver.
>
> Nicolas
>
> 2011/4/2 Nicolas Cellier <nicolas.cellier.aka.nice at gmail.com>:
>> However, this is strange because deOptimize is sent very soon in the
>> process (at parse time), and ensureClosureAnalysisDone is sent well
>> after at #generate: time, so a debug session will be necessary. Now I
>> must cut some grass before it grows too gigantic, so maybe this
>> evening...
>>
>> Nicolas
>>
>> 2011/4/2 Nicolas Cellier <nicolas.cellier.aka.nice at gmail.com>:
>>> That can happen only if
>>>    self generateAsClosure
>>> answer false in BlockNode.
>>>
>>> That can happen if (blockExtent == nil)
>>>
>>> Only #analyseTempsWithin:rootNode:assignmentPools: does fill this ivar.
>>> But it never do it if optimized.
>>>
>>> So probably, the block is deOptimize-d too late after the analyseTemps
>>> is performed...
>>>
>>> Nicolas
>>>
>>> 2011/4/2 Levente Uzonyi <leves at elte.hu>:
>>>> On Thu, 31 Mar 2011, Eliot Miranda wrote:
>>>>
>>>>> Hi All,
>>>>>
>>>>>   just a note that once Compiler-nice.186 is installed, which inlines
>>>>> #repeat, one needs to recompile all senders of repeat to avoid having the
>>>>> decompiler crap out on you, e.g. in the debugger.  For example the
>>>>
>>>> IMHO it's simply a decompiler bug. It should be able to decompile
>>>> non-inlined #repeat sends, because it's possible in the current system to
>>>> write code which yields such bytecodes. For example:
>>>>
>>>> [ ] repeat; yourself.
>>>>
>>>> Just tried the following which raises an interesting error:
>>>>
>>>> [ [ ] repeat; yourself ] decompile
>>>>
>>>> The error is:
>>>>
>>>> 'DecompilerConstructorForClosures(Object)>>error:
>>>> DecompilerConstructorForClosures(Object)>>primitiveFailed:
>>>> DecompilerConstructorForClosures(Object)>>primitiveFailed
>>>> DecompilerConstructorForClosures(Object)>>primitiveChangeClassTo:
>>>> Decompiler>>sawBlueBookBlock
>>>> Decompiler>>checkForBlockCopy:
>>>> Decompiler>>checkForBlock:selector:arguments:
>>>> Decompiler>>send:super:numArgs:
>>>> Decompiler(InstructionStream)>>interpretNextInstructionFor:
>>>> Decompiler>>interpretNextInstructionFor:
>>>> Decompiler>>statementsTo:
>>>> Decompiler>>blockTo:
>>>> Decompiler>>doClosureCopyCopiedValues:numArgs:blockSize:
>>>> Decompiler>>pushClosureCopyNumCopiedValues:numArgs:blockSize:
>>>> Decompiler(InstructionStream)>>interpretExtension:in:for:
>>>> Decompiler(InstructionStream)>>interpretNextInstructionFor:
>>>> Decompiler>>interpretNextInstructionFor:
>>>> Decompiler>>statementsTo:
>>>> Decompiler>>blockTo:
>>>> Decompiler>>decompile:in:method:using:
>>>> Decompiler>>decompile:in:method:
>>>> CompiledMethod>>getSourceFor:in:
>>>> CompiledMethod>>methodNode
>>>> CompiledMethod>>decompileWithTemps
>>>> Decompiler>>decompileBlock:
>>>> BlockClosure>>decompile
>>>> UndefinedObject>>DoIt
>>>> ...
>>>>
>>>> The source of the error is:
>>>>
>>>> Decompiler >> sawBlueBookBlock
>>>>        constructor isForClosures ifTrue:
>>>>                [constructor primitiveChangeClassTo: DecompilerConstructor
>>>> new]
>>>>
>>>> I guess the decompiler should never see a blue book block, so it seems to be
>>>> a compiler bug. The bytecodes for the CompiledMethod are:
>>>>
>>>> 25 <8F 00 00 0C> closureNumCopied: 0 numArgs: 0 bytes 29 to 40
>>>> 29      <89> pushThisContext:
>>>> 30      <75> pushConstant: 0
>>>> 31      <C8> send: blockCopy:
>>>> 32      <A4 02> jumpTo: 36
>>>> 34              <73> pushConstant: nil
>>>> 35              <7D> blockReturn
>>>> 36      <88> dup
>>>> 37      <D1> send: repeat
>>>> 38      <87> pop
>>>> 39      <D2> send: yourself
>>>> 40      <7D> blockReturn
>>>> 41 <D0> send: decompile
>>>> 42 <7C> returnTop
>>>>
>>>> Evaluating the following is also funny, it brings you back to the world of
>>>> BlockContexts:
>>>>
>>>> [ self halt ] repeat; yourself
>>>>
>>>>
>>>> Levente
>>>>
>>>>> compilation of
>>>>>
>>>>> GeneratorTest methods for generators
>>>>> fibonacciSequence
>>>>> "Yields an infinite sequence of fibonacci numbers."
>>>>> ^ Generator on: [ :generator |
>>>>> | a b |
>>>>> a := 0. b := 1.
>>>>> [ a := b + (b := a).
>>>>>  generator yield: a ]
>>>>> repeat ]
>>>>>
>>>>> with non-inlined repeat:
>>>>> pushLit: Generator
>>>>> closureNumCopied: 0 numArgs: 1 bytes 34 to 72
>>>>> pushConstant: nil
>>>>> push: (Array new: 2)
>>>>> popIntoTemp: 1
>>>>> pushConstant: 0
>>>>> popIntoTemp: 0 inVectorAt: 1
>>>>> pushConstant: 1
>>>>> popIntoTemp: 1 inVectorAt: 1
>>>>> pushTemp: 0
>>>>> pushTemp: 1
>>>>> closureNumCopied: 2 numArgs: 0 bytes 52 to 70
>>>>> pushTemp: 1 inVectorAt: 1
>>>>> pushTemp: 0 inVectorAt: 1
>>>>> storeIntoTemp: 1 inVectorAt: 1
>>>>> send: #+ (1 arg)
>>>>> popIntoTemp: 0 inVectorAt: 1
>>>>> pushTemp: 0
>>>>> pushTemp: 0 inVectorAt: 1
>>>>> send: #yield: (1 arg)
>>>>> blockReturn
>>>>> send: #repeat (0 args)
>>>>> blockReturn
>>>>> send: #on: (1 arg)
>>>>> returnTop
>>>>>
>>>>> with inlined repeat:
>>>>> pushLit: Generator
>>>>> closureNumCopied: 0 numArgs: 1 bytes 34 to 53
>>>>> pushConstant: nil
>>>>> pushConstant: nil
>>>>> pushConstant: 0
>>>>> popIntoTemp: 1
>>>>> pushConstant: 1
>>>>> popIntoTemp: 2
>>>>> L1:
>>>>> pushTemp: 2
>>>>> pushTemp: 1
>>>>> storeIntoTemp: 2
>>>>> send: #+ (1 arg)
>>>>> popIntoTemp: 1
>>>>> pushTemp: 0
>>>>> pushTemp: 1
>>>>> send: #yield: (1 arg)
>>>>> pop
>>>>> jumpTo: L1
>>>>> pushConstant: nil
>>>>> blockReturn
>>>>> send: #on: (1 arg)
>>>>> returnTop
>>>>>
>>>>>
>>>>> will cause the decompiler to fail horribly if the non-inlined result is
>>>>> decompiled with Compiler-nice.186 installed.  The fix is merely to
>>>>> recompile
>>>>> it (and other senders of #repeat).  The underlying problem is that if the
>>>>> is
>>>>> given temp names via a schematicTempNamesString then that string must
>>>>> match
>>>>> the temps in the method, and in the above if repeat is not inlined a and b
>>>>> are remote, and hence the schematicTempNamesString is [generator (a b)]
>>>>> but
>>>>> if repeat is inlined then they are local and the schematicTempNamesString
>>>>> is
>>>>> [generator a b].
>>>>>
>>>>> BTW, kudos to Nicholas for the newParser/newCompiler changes!
>>>>>
>>>>> best
>>>>> Eliot
>>>>>
>>>>
>>>>
>>>
>>
>



More information about the Squeak-dev mailing list