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

Levente Uzonyi leves at elte.hu
Sun Apr 3 00:58:32 UTC 2011


On Sat, 2 Apr 2011, Nicolas Cellier wrote:

> 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

Great, thanks!


Levens

>
> 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