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