[squeak-dev] The Trunk: Compiler-nice.188.mcz

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Sun Feb 13 19:48:40 UTC 2011


2011/2/13 Levente Uzonyi <leves at elte.hu>:
> On Sun, 13 Feb 2011, Nicolas Cellier wrote:
>
>> Yep, little collision, sorry.
>> Could you redo it ?
>
> There's no collision, because I pushed my version to the Inbox. If you want
> me to add the postscript that decompiles the senders of #repeat, then I can
> do that.
>

Yes please, that's what I mean.
Or does merge handle postscripts ?

Nicolas

>
> Levente
>
>>
>> 2011/2/13 Levente Uzonyi <leves at elte.hu>:
>>>
>>> On Sun, 13 Feb 2011, commits at source.squeak.org wrote:
>>>
>>>> Nicolas Cellier uploaded a new version of Compiler to project The Trunk:
>>>> http://source.squeak.org/trunk/Compiler-nice.188.mcz
>>>
>>> Seems like you were a bit faster than me. I pushed my version to the
>>> Inbox,
>>> because if you recompile methods which send #repeat, then the
>>> DecompilerTests will fail with an error.
>>>
>>>
>>> Levente
>>>
>>>>
>>>> ==================== Summary ====================
>>>>
>>>> Name: Compiler-nice.188
>>>> Author: nice
>>>> Time: 13 February 2011, 7:39:55.07 pm
>>>> UUID: 66ccdff2-05b9-4294-9b3b-0bf2d84417fd
>>>> Ancestors: Compiler-nice.187, Compiler-fbs.183, Compiler-nice.186
>>>>
>>>> Merge fbs.183 nice.186 nice.187 coming from inbox
>>>>
>>>> =============== Diff against Compiler-nice.187 ===============
>>>>
>>>> Item was changed:
>>>>  InstructionStream subclass: #Decompiler
>>>> +       instanceVariableNames: 'constructor method instVars tempVars
>>>> constTable stack statements lastPc exit caseExits lastJumpPc
>>>> lastReturnPc
>>>> limit hasValue blockStackBase numLocalTemps blockStartsToTempVars
>>>> tempVarCount lastJumpIfPcStack'
>>>> -       instanceVariableNames: 'constructor method instVars tempVars
>>>> constTable stack statements lastPc exit caseExits lastJumpPc
>>>> lastReturnPc
>>>> limit hasValue blockStackBase numLocalTemps blockStartsToTempVars
>>>> tempVarCount'
>>>>        classVariableNames: 'ArgumentFlag CascadeFlag CaseFlag IfNilFlag'
>>>>        poolDictionaries: ''
>>>>        category: 'Compiler-Kernel'!
>>>>
>>>> + !Decompiler commentStamp: 'nice 2/3/2011 22:54' prior: 0!
>>>> - !Decompiler commentStamp: 'nice 3/1/2010 19:56' prior: 0!
>>>>  I decompile a method in three phases:
>>>>        Reverser: postfix byte codes -> prefix symbolic codes (nodes and
>>>> atoms)
>>>>        Parser: prefix symbolic codes -> node tree (same as the compiler)
>>>>        Printer: node tree -> text (done by the nodes)
>>>>
>>>>
>>>>  instance vars:
>>>>
>>>>        constructor <DecompilerConstructor> an auxiliary knowing how to
>>>> generate Abstract Syntax Tree (node tree)
>>>>        method <CompiledMethod> the method being decompiled
>>>>        instVars <Array of: String> the instance variables of the class
>>>> implementing method
>>>>        tempVars <String | (OrderedCollection of: String)> hold the names
>>>> of temporary variables (if known)
>>>>                NOTE: POLYMORPHISM WILL BE RESOLVED IN #initSymbols:
>>>>        constTable <Collection of: ParseNode> parse node associated with
>>>> byte encoded constants (nil true false 0 1 -1 etc...)
>>>>        stack <OrderedCollection of: (ParseNode | String | Integer) >
>>>> multipurpose...
>>>>        statements <OrderedCollection of: ParseNode> the statements of
>>>> the
>>>> method being decompiled
>>>>        lastPc <Integer>
>>>>        exit <Integer>
>>>>        caseExits <OrderedCollection of: Integer> - stack of exit
>>>> addresses
>>>> that have been seen in the branches of caseOf:'s
>>>>        lastJumpPc <Integer>
>>>>        lastReturnPc <Integer>
>>>>        limit <Integer>
>>>>        hasValue <Boolean>
>>>>        blockStackBase <Integer>
>>>>        numLocaltemps <Integer | Symbol> - number of temps local to a
>>>> block; also a flag indicating decompiling a block
>>>>        blockStartsToTempVars <Dictionary key: Integer value:
>>>> (OrderedCollection of: String)>
>>>> +       tempVarCount <Integer> number of temp vars used by the method
>>>> +       lastJumpIfPcStack <OrderedCollection of: Integer> the value of
>>>> program counter just before the last encountered conditional jumps!
>>>> -       tempVarCount <Integer> number of temp vars used by the method!
>>>>
>>>> Item was changed:
>>>>  ----- Method: Decompiler>>decompile:in:method:using: (in category
>>>> 'public
>>>> access') -----
>>>>  decompile: aSelector in: aClass method: aMethod using: aConstructor
>>>>
>>>>        | block node |
>>>>        constructor := aConstructor.
>>>>        method := aMethod.
>>>>        self initSymbols: aClass.  "create symbol tables"
>>>>        method isQuick
>>>>                ifTrue: [block := self quickMethod]
>>>>                ifFalse:
>>>>                        [stack := OrderedCollection new: method
>>>> frameSize.
>>>> +                       lastJumpIfPcStack := OrderedCollection new.
>>>>                        caseExits := OrderedCollection new.
>>>>                        statements := OrderedCollection new: 20.
>>>>                        numLocalTemps := 0.
>>>>                        super method: method pc: method initialPC.
>>>>                        "skip primitive error code store if necessary"
>>>>                        (method primitive ~= 0 and: [self willStore])
>>>> ifTrue:
>>>>                                [pc := pc + 2.
>>>>                                 tempVars := tempVars
>>>> asOrderedCollection].
>>>>                        block := self blockTo: method endPC + 1.
>>>>                        stack isEmpty ifFalse: [self error: 'stack not
>>>> empty']].
>>>>        node := constructor
>>>>                                codeMethod: aSelector
>>>>                                block: block
>>>>                                tempVars: tempVars
>>>>                                primitive: method primitive
>>>>                                class: aClass.
>>>>        method primitive > 0 ifTrue:
>>>>                [node removeAndRenameLastTempIfErrorCode].
>>>>        ^node preen!
>>>>
>>>> Item was changed:
>>>>  ----- Method: Decompiler>>interpretNextInstructionFor: (in category
>>>> 'private') -----
>>>>  interpretNextInstructionFor: client
>>>>
>>>>        | code varNames |
>>>>
>>>>  "Change false here will trace all state in Transcript."
>>>>  true ifTrue: [^ super interpretNextInstructionFor: client].
>>>>
>>>>        varNames := self class allInstVarNames.
>>>>        code := (self method at: pc) radix: 16.
>>>>        Transcript cr; cr; print: pc; space;
>>>> +               nextPutAll: '<' , code, '>'.
>>>> -               nextPutAll: '<' , (code copyFrom: 4 to: code size), '>'.
>>>>        8 to: varNames size do:
>>>>                [:i | i <= 10 ifTrue: [Transcript cr]
>>>>                                ifFalse: [Transcript space; space].
>>>>                Transcript nextPutAll: (varNames at: i);
>>>>                                nextPutAll: ': '; print: (self instVarAt:
>>>> i)].
>>>>        Transcript endEntry.
>>>>        ^ super interpretNextInstructionFor: client!
>>>>
>>>> Item was changed:
>>>>  ----- Method: Decompiler>>jump: (in category 'instruction decoding')
>>>> -----
>>>>  jump: dist
>>>> +       | blockBody destPc nextPC |
>>>> +       destPc := pc + dist.
>>>> +       (lastJumpIfPcStack isEmpty or: [dist < 0 and: [destPc >
>>>> lastJumpIfPcStack last]])
>>>> +               ifTrue:
>>>> +                       ["Rule: aBackward jump not crossing a Bfp/Btp
>>>> must
>>>> be a repeat"
>>>> +                       nextPC := pc.
>>>> +                       pc := destPc.
>>>> +                       blockBody := self statementsTo: lastPc.
>>>> +                       blockBody size timesRepeat: [statements
>>>> removeLast].
>>>> +                       pc := nextPC.
>>>> +                       statements addLast:
>>>> +                               (constructor
>>>> +                                       codeMessage: (constructor
>>>> codeBlock: blockBody returns: false)
>>>> +                                       selector: (constructor
>>>> +
>>>> codeSelector: #repeat
>>>> +                                                               code:
>>>> #macro)
>>>> +                                       arguments: #()).
>>>> +                       ]
>>>> +               ifFalse:
>>>> +                       [exit := destPc.
>>>> +                       lastJumpPc := lastPc]!
>>>> -
>>>> -       exit := pc + dist.
>>>> -       lastJumpPc := lastPc!
>>>>
>>>> Item was changed:
>>>>  ----- Method: Decompiler>>jump:if: (in category 'instruction decoding')
>>>> -----
>>>>  jump: dist if: condition
>>>>
>>>>        | savePc sign elsePc elseStart end cond ifExpr thenBlock
>>>> elseBlock
>>>>          thenJump elseJump condHasValue isIfNil saveStack blockBody |
>>>> +       lastJumpIfPcStack addLast: lastPc.
>>>> +       stack last == CascadeFlag ifTrue: [^ [self case: dist] ensure:
>>>> [lastJumpIfPcStack removeLast]].
>>>> -       stack last == CascadeFlag ifTrue: [^ self case: dist].
>>>>        elsePc := lastPc.
>>>>        elseStart := pc + dist.
>>>>        end := limit.
>>>>        "Check for bfp-jmp to invert condition.
>>>>        Don't be fooled by a loop with a null body."
>>>>        sign := condition.
>>>>        savePc := pc.
>>>>        self interpretJump ifNotNil:
>>>>                [:elseDist|
>>>>                 (elseDist >= 0 and: [elseStart = pc]) ifTrue:
>>>>                         [sign := sign not.  elseStart := pc +
>>>> elseDist]].
>>>>        pc := savePc.
>>>>        ifExpr := stack removeLast.
>>>>        (isIfNil := stack size > 0 and: [stack last == IfNilFlag])
>>>> ifTrue:
>>>>                [stack removeLast].
>>>>        saveStack := stack.
>>>>        stack := OrderedCollection new.
>>>>        thenBlock := self blockTo: elseStart.
>>>>        condHasValue := hasValue or: [isIfNil].
>>>>        "ensure jump is within block (in case thenExpr returns)"
>>>>        thenJump := exit <= end ifTrue: [exit] ifFalse: [elseStart].
>>>>        "if jump goes back, then it's a loop"
>>>>        thenJump < elseStart
>>>>                ifTrue:
>>>>                        ["Must be a while loop...
>>>>                          thenJump will jump to the beginning of the
>>>> while
>>>> expr.  In the case of while's
>>>>                          with a block in the condition, the while expr
>>>> should include more than just
>>>>                          the last expression: find all the statements
>>>> needed by re-decompiling."
>>>>                        stack := saveStack.
>>>>                        pc := thenJump.
>>>>                        blockBody := self statementsTo: elsePc.
>>>>                        "discard unwanted statements from block"
>>>>                        blockBody size - 1 timesRepeat: [statements
>>>> removeLast].
>>>>                        statements addLast:
>>>>                                (constructor
>>>>                                        codeMessage: (constructor
>>>> codeBlock: blockBody returns: false)
>>>>                                        selector: (constructor
>>>>
>>>>  codeSelector: (sign
>>>>
>>>>                      ifTrue: [#whileFalse:]
>>>>
>>>>                      ifFalse: [#whileTrue:])
>>>>                                                                code:
>>>> #macro)
>>>>                                        arguments: { thenBlock }).
>>>>                        pc := elseStart.
>>>>                        self convertToDoLoop]
>>>>                ifFalse:
>>>>                        ["Must be a conditional..."
>>>>                        elseBlock := self blockTo: thenJump.
>>>>                        elseJump := exit.
>>>>                        "if elseJump is backwards, it is not part of the
>>>> elseExpr"
>>>>                        elseJump < elsePc ifTrue:
>>>>                                [pc := lastPc].
>>>>                        cond := isIfNil
>>>>                                                ifTrue:
>>>>                                                        [constructor
>>>>
>>>>  codeMessage: ifExpr ifNilReceiver
>>>>                                                                selector:
>>>> (constructor
>>>>
>>>>              codeSelector: (sign ifTrue: [#ifNotNil:] ifFalse:
>>>> [#ifNil:])
>>>>
>>>>              code: #macro)
>>>>
>>>>  arguments:
>>>> (Array with: thenBlock)]
>>>>                                                ifFalse:
>>>>                                                        [constructor
>>>>
>>>>  codeMessage: ifExpr
>>>>                                                                selector:
>>>> (constructor codeSelector: #ifTrue:ifFalse: code: #macro)
>>>>
>>>>  arguments:
>>>>      (sign
>>>>
>>>>                      ifTrue: [{elseBlock. thenBlock}]
>>>>
>>>>                      ifFalse: [{thenBlock. elseBlock}])].
>>>>                        stack := saveStack.
>>>>                        condHasValue
>>>>                                ifTrue: [stack addLast: cond]
>>>> +                               ifFalse: [statements addLast: cond]].
>>>> +       lastJumpIfPcStack removeLast.!
>>>> -                               ifFalse: [statements addLast: cond]]!
>>>>
>>>> Item was changed:
>>>>  ----- Method: MessageNode class>>initialize (in category 'class
>>>> initialization') -----
>>>> + initialize
>>>> +       "MessageNode initialize"
>>>> - initialize            "MessageNode initialize"
>>>>        MacroSelectors :=
>>>>                #(      ifTrue: ifFalse: ifTrue:ifFalse: ifFalse:ifTrue:
>>>>                        and: or:
>>>>                        whileFalse: whileTrue: whileFalse whileTrue
>>>>                        to:do: to:by:do:
>>>>                        caseOf: caseOf:otherwise:
>>>> +                       ifNil: ifNotNil:  ifNil:ifNotNil:
>>>> ifNotNil:ifNil:
>>>> +                       repeat ).
>>>> -                       ifNil: ifNotNil:  ifNil:ifNotNil:
>>>> ifNotNil:ifNil:).
>>>>        MacroTransformers :=
>>>>                #(      transformIfTrue: transformIfFalse:
>>>> transformIfTrueIfFalse: transformIfFalseIfTrue:
>>>>                        transformAnd: transformOr:
>>>>                        transformWhile: transformWhile: transformWhile:
>>>> transformWhile:
>>>>                        transformToDo: transformToDo:
>>>>                        transformCase: transformCase:
>>>> +                       transformIfNil: transformIfNil:
>>>>  transformIfNilIfNotNil: transformIfNotNilIfNil:
>>>> +                       transformRepeat: ).
>>>> -                       transformIfNil: transformIfNil:
>>>>  transformIfNilIfNotNil: transformIfNotNilIfNil:).
>>>>        MacroEmitters :=
>>>>                #(      emitCodeForIf:encoder:value:
>>>> emitCodeForIf:encoder:value:
>>>>                        emitCodeForIf:encoder:value:
>>>> emitCodeForIf:encoder:value:
>>>>                        emitCodeForIf:encoder:value:
>>>> emitCodeForIf:encoder:value:
>>>>                        emitCodeForWhile:encoder:value:
>>>> emitCodeForWhile:encoder:value:
>>>>                        emitCodeForWhile:encoder:value:
>>>> emitCodeForWhile:encoder:value:
>>>>                        emitCodeForToDo:encoder:value:
>>>> emitCodeForToDo:encoder:value:
>>>>                        emitCodeForCase:encoder:value:
>>>> emitCodeForCase:encoder:value:
>>>>                        emitCodeForIfNil:encoder:value:
>>>> emitCodeForIfNil:encoder:value:
>>>> +                       emitCodeForIf:encoder:value:
>>>> emitCodeForIf:encoder:value:
>>>> +                       emitCodeForRepeat:encoder:value:).
>>>> -                       emitCodeForIf:encoder:value:
>>>> emitCodeForIf:encoder:value:).
>>>>        MacroSizers :=
>>>>                #(      sizeCodeForIf:value: sizeCodeForIf:value:
>>>> sizeCodeForIf:value: sizeCodeForIf:value:
>>>>                        sizeCodeForIf:value: sizeCodeForIf:value:
>>>>                        sizeCodeForWhile:value: sizeCodeForWhile:value:
>>>> sizeCodeForWhile:value: sizeCodeForWhile:value:
>>>>                        sizeCodeForToDo:value: sizeCodeForToDo:value:
>>>>                        sizeCodeForCase:value: sizeCodeForCase:value:
>>>> +                       sizeCodeForIfNil:value: sizeCodeForIfNil:value:
>>>> sizeCodeForIf:value: sizeCodeForIf:value:
>>>> +                       sizeCodeForRepeat:value:).
>>>> -                       sizeCodeForIfNil:value: sizeCodeForIfNil:value:
>>>> sizeCodeForIf:value: sizeCodeForIf:value:).
>>>>        MacroPrinters :=
>>>>                #(      printIfOn:indent: printIfOn:indent:
>>>> printIfOn:indent: printIfOn:indent:
>>>>                        printIfOn:indent: printIfOn:indent:
>>>>                        printWhileOn:indent: printWhileOn:indent:
>>>> printWhileOn:indent: printWhileOn:indent:
>>>>                        printToDoOn:indent: printToDoOn:indent:
>>>>                        printCaseOn:indent: printCaseOn:indent:
>>>> +                       printIfNil:indent: printIfNil:indent:
>>>> printIfNilNotNil:indent: printIfNilNotNil:indent:
>>>> +                       printRepeatOn:indent:)!
>>>> -                       printIfNil:indent: printIfNil:indent:
>>>> printIfNilNotNil:indent: printIfNilNotNil:indent:)!
>>>>
>>>> Item was added:
>>>> + ----- Method: MessageNode>>emitCodeForRepeat:encoder:value: (in
>>>> category
>>>> 'code generation') -----
>>>> + emitCodeForRepeat: stack encoder: encoder value: forValue
>>>> +       " L1: ... Jmp(L1)"
>>>> +       | loopSize |
>>>> +       loopSize := sizes at: 1.
>>>> +       receiver emitCodeForEvaluatedEffect: stack encoder: encoder.
>>>> +       self emitCodeForJump: 0 - loopSize encoder: encoder.
>>>> +       forValue ifTrue: [encoder genPushSpecialLiteral: nil. stack
>>>> push:
>>>> 1]!
>>>>
>>>> Item was added:
>>>> + ----- Method: MessageNode>>printRepeatOn:indent: (in category
>>>> 'printing') -----
>>>> + printRepeatOn: aStream indent: level
>>>> +
>>>> +       self printReceiver: receiver on: aStream indent: level.
>>>> +
>>>> +       ^self printKeywords: selector key
>>>> +               arguments: (Array new)
>>>> +               on: aStream indent: level!
>>>>
>>>> Item was added:
>>>> + ----- Method: MessageNode>>sizeCodeForRepeat:value: (in category 'code
>>>> generation') -----
>>>> + sizeCodeForRepeat: encoder value: forValue
>>>> +       "L1: ... Jmp(L1) nil (nil for value only);"
>>>> +       | loopSize |
>>>> +       loopSize := (receiver sizeCodeForEvaluatedEffect: encoder) +
>>>> (encoder sizeJumpLong: 1).
>>>> +       sizes := Array with: loopSize.
>>>> +       ^loopSize + (forValue ifTrue: [encoder sizePushSpecialLiteral:
>>>> nil] ifFalse: [0])!
>>>>
>>>> Item was added:
>>>> + ----- Method: MessageNode>>transformRepeat: (in category 'macro
>>>> transformations') -----
>>>> + transformRepeat: encoder
>>>> +       "answer true if this #repeat message can be optimized"
>>>> +
>>>> +       ^(self checkBlock: receiver as: 'receiver' from: encoder)
>>>> +          and: [receiver noteOptimizedIn: self.
>>>> +                       true]!
>>>>
>>>> Item was removed:
>>>> - ----- Method: VariableNode>>canBeSpecialArgument (in category
>>>> 'testing')
>>>> -----
>>>> - canBeSpecialArgument
>>>> -       "Can I be an argument of (e.g.) ifTrue:?"
>>>> -
>>>> -       ^code < LdNil!
>>>>
>>>>
>>>>
>>>
>>>
>>
>
>
>
>



More information about the Squeak-dev mailing list