[squeak-dev] The Trunk: Compiler-nice.188.mcz
Levente Uzonyi
leves at elte.hu
Sun Feb 13 19:48:18 UTC 2011
On Sun, 13 Feb 2011, Levente Uzonyi wrote:
> 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.
I mean compiles, not decompiles.
Levente
>
>
> 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
|