[squeak-dev] The Trunk: Compiler-nice.188.mcz
Nicolas Cellier
nicolas.cellier.aka.nice at gmail.com
Sun Feb 13 19:27:13 UTC 2011
Yep, little collision, sorry.
Could you redo it ?
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
|