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

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Sat Apr 2 12:56:21 UTC 2011


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