'From Cuis 2.3 of 22 March 2010 [latest update: #472] on 7 April 2010 at 11:07:30 am'!

!Decompiler commentStamp: '<historical>' 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
	method
	instVars
	tempVars
	constTable
	stack
	statements
	lastPc
	exit
	caseExits	- stack of exit addresses that have been seen in the branches of caseOf:'s
	lastJumpPc
	lastReturnPc
	limit
	hasValue
	blockStackBase
	numLocaltemps - number of temps local to a block; also a flag indicating decompiling a block!

!classDefinition: #MethodHighlightingTests category: #'Compiler-Tests'!
ClosureCompilerTest subclass: #MethodHighlightingTests
	instanceVariableNames: 'creator timeStamp duration tracks'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Compiler-Tests'!
!classDefinition: #BlockNode category: #'Compiler-ParseNodes'!
ParseNode subclass: #BlockNode
	instanceVariableNames: 'arguments statements returns nArgsNode size remoteCopyNode temporaries optimized actualScopeIfOptimized blockExtent remoteTempNode copiedValues closureCreationNode startOfLastStatement optimizedMessageNode '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Compiler-ParseNodes'!
!classDefinition: #OptimizedBlockLocalTempReadBeforeWrittenVisitor category: #'Compiler-Support'!
ParseNodeVisitor subclass: #OptimizedBlockLocalTempReadBeforeWrittenVisitor
	instanceVariableNames: 'inOptimizedBlock readBeforeWritten written'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Compiler-Support'!

!OptimizedBlockLocalTempReadBeforeWrittenVisitor commentStamp: '<historical>' prior: 0!
Answer the set of temporary variables that are read before they are written in the visited parse tree.  Used by the compiler to detect those block-local temporaries of blocks in optimized loops that require nilling to prevent a value from a previous iteration persisting into a subsequent one.!


!ClosureCompilerTest methodsFor: 'tests' stamp: 'eem 9/5/2009 17:33'!
testOptimizedBlockLocalNilling1
	"Whether a block is optimized or not a block-local temp
	 should be nil at the start of each evaluation of the block."

	1 to: 3 do: [:i| | j |
		self assert: j isNil.
		j := i + 1.
		self assert: j isNil not]! !

!ClosureCompilerTest methodsFor: 'tests' stamp: 'eem 9/5/2009 17:32'!
testOptimizedBlockLocalNilling2
	"Whether a block is optimized or not a block-local temp
	 should be nil at the start of each evaluation of the block."

	1 to: 6 do: [:i| | j k |
		self assert: j isNil.
		self assert: k isNil.
		i even
			ifTrue: [j := i + 2]
			ifFalse: [k := i + 1].
		self assert: (j isNil or: [k isNil]).
		self assert: (j isNil not or: [k isNil not])]! !


!ParseNode methodsFor: 'visiting' stamp: 'eem 9/6/2009 12:33'!
accept: aVisitor
	"Accept a visitor by double-dispatching to a type-specific method on the visitor, e.g. visitBlockNode:.
	 All such implementations under ParseNode should answer the result of the dispatch, e.g.
		^aVisitor visitBlockNode: self"
	^self subclassResponsibility! !

!ParseNode methodsFor: 'code generation' stamp: 'ar 10/2/2007 17:57'!
emitForBlockValue: stack on: aStream
	"Generate code for evaluating the last statement in a block"
	^self emitForValue: stack on: aStream! !

!ParseNode methodsFor: 'code generation' stamp: 'ar 10/2/2007 17:56'!
sizeForBlockValue: encoder
	"Answer the size for evaluating the last statement in a block"
	^self sizeForValue: encoder! !


!AssignmentNode methodsFor: 'visiting' stamp: 'eem 9/6/2009 12:33'!
accept: aVisitor
	^aVisitor visitAssignmentNode: self! !


!BlockNode methodsFor: 'visiting' stamp: 'eem 9/6/2009 12:33'!
accept: aVisitor
	^aVisitor visitBlockNode: self! !

!BlockNode methodsFor: 'code generation (closures)' stamp: 'eem 9/6/2009 13:36'!
nilReadBeforeWrittenTemps
	| visitor readBeforeWritten |
	self accept: (visitor := OptimizedBlockLocalTempReadBeforeWrittenVisitor new).
	readBeforeWritten := visitor readBeforeWritten.
	temporaries reverseDo:
		[:temp|
		((readBeforeWritten includes: temp)
		 and: [temp isRemote not]) ifTrue:
			[statements addFirst: (AssignmentNode new variable: temp value: NodeNil)]]! !

!BlockNode methodsFor: 'code generation (closures)' stamp: 'eem 9/6/2009 13:30'!
noteOptimizedIn: anOptimizedMessageNode
	optimized := true.
	optimizedMessageNode := anOptimizedMessageNode! !

!BlockNode methodsFor: 'code generation' stamp: 'ar 10/2/2007 18:05'!
emitForEvaluatedValue: stack on: aStream
	self emitExceptLast: stack on: aStream.
	statements last emitForBlockValue: stack on: aStream.
! !


!BraceNode methodsFor: 'visiting' stamp: 'eem 9/6/2009 12:33'!
accept: aVisitor
	^aVisitor visitBraceNode: self! !


!CascadeNode methodsFor: 'visiting' stamp: 'eem 9/6/2009 12:33'!
accept: aVisitor
	^aVisitor visitCascadeNode: self! !


!CommentNode methodsFor: 'visiting' stamp: 'eem 9/6/2009 12:33'!
accept: aVisitor
	^aVisitor visitCommentNode: self! !


!LiteralNode methodsFor: 'visiting' stamp: 'eem 9/6/2009 12:34'!
accept: aVisitor
	^aVisitor visitLiteralNode: self! !


!MessageNode methodsFor: 'visiting' stamp: 'eem 9/6/2009 12:35'!
accept: aVisitor
	^aVisitor visitMessageNode: self! !


!MethodNode methodsFor: 'visiting' stamp: 'eem 9/6/2009 12:35'!
accept: aVisitor
	^aVisitor visitMethodNode: self! !


!NewArrayNode methodsFor: 'visiting' stamp: 'eem 9/6/2009 12:35'!
accept: aVisitor
	^aVisitor visitNewArrayNode: self! !


!ParseNodeVisitor methodsFor: 'visiting' stamp: 'eem 9/5/2009 20:08'!
visitMessageNode: aMessageNode
	aMessageNode receiver accept: self.
	"receiver notNil ifTrue: ''receiver is nil for cascades''
		[receiver accept: self]."
	aMessageNode selector accept: self.
	aMessageNode argumentsInEvaluationOrder do:
		[:argument| argument accept: self]! !


!OptimizedBlockLocalTempReadBeforeWrittenVisitor methodsFor: 'initialize-release' stamp: 'eem 9/5/2009 21:03'!
initialize
	inOptimizedBlock := false! !

!OptimizedBlockLocalTempReadBeforeWrittenVisitor methodsFor: 'accessing' stamp: 'eem 9/8/2008 14:30'!
readBeforeWritten
	^readBeforeWritten ifNil: [IdentitySet new]! !

!OptimizedBlockLocalTempReadBeforeWrittenVisitor methodsFor: 'visiting' stamp: 'eem 9/10/2008 15:28'!
visitAssignmentNode: anAssignmentNode
	anAssignmentNode value accept: self.
	anAssignmentNode variable isTemp
		ifTrue:
			[written ifNil: [written := IdentitySet new].
			 written add: anAssignmentNode variable]
		ifFalse:
			[anAssignmentNode variable accept: self]! !

!OptimizedBlockLocalTempReadBeforeWrittenVisitor methodsFor: 'visiting' stamp: 'eem 9/5/2009 22:09'!
visitBlockNode: aBlockNode
	| savedWritten |
	"If we're in the optimized block in one side of an optimized ifTrue:ifFalse: et al
	 leave it to the enclosing visitMessageNode: activation to handle merging written."
	inOptimizedBlock ifTrue:
		[^super visitBlockNode: aBlockNode].
	"If we're not then don't update written because without evaluating the guard(s)
	 we can't tell if the block is evaluated or not, and we must avoid false positives."
	savedWritten := written copy.
	super visitBlockNode: aBlockNode.
	written := savedWritten! !

!OptimizedBlockLocalTempReadBeforeWrittenVisitor methodsFor: 'visiting' stamp: 'eem 9/5/2009 22:03'!
visitMessageNode: aMessageNode
	| savedWritten writtenPostFirstArm |
	(aMessageNode isOptimized
	 and: [#(ifTrue:ifFalse: ifFalse:ifTrue: ifNil:ifNotNil: ifNotNil:ifNil:) includes: aMessageNode selector key]) ifFalse:
		[^super visitMessageNode: aMessageNode].
	aMessageNode receiver accept: self.
	aMessageNode selector accept: self.
	savedWritten := written copy.
	aMessageNode argumentsInEvaluationOrder
		do: [:argument|
			argument isBlockNode
				ifTrue: [| savedIOB |
					savedIOB := inOptimizedBlock.
					inOptimizedBlock := true.
					[argument accept: self]
						ensure: [inOptimizedBlock := savedIOB]]
				ifFalse: [argument accept: self]]
		separatedBy:
			[writtenPostFirstArm := written.
			 written := savedWritten].
	(written notNil
	 and: [writtenPostFirstArm notNil]) ifTrue:
		[written := written intersection: writtenPostFirstArm]! !

!OptimizedBlockLocalTempReadBeforeWrittenVisitor methodsFor: 'visiting' stamp: 'eem 9/8/2008 14:43'!
visitTempVariableNode: aTempVariableNode
	(aTempVariableNode isArg
	 or: [written notNil
		and: [written includes: aTempVariableNode]]) ifTrue:
		[^self].
	readBeforeWritten ifNil:
		[readBeforeWritten := IdentitySet new].
	readBeforeWritten add: aTempVariableNode! !


!ReturnNode methodsFor: 'visiting' stamp: 'eem 9/6/2009 12:35'!
accept: aVisitor
	^aVisitor visitReturnNode: self! !


!SelectorNode methodsFor: 'visiting' stamp: 'eem 9/6/2009 12:34'!
accept: aVisitor
	^aVisitor visitSelectorNode: self! !


!VariableNode methodsFor: 'visiting' stamp: 'eem 9/6/2009 12:34'!
accept: aVisitor
	^aVisitor visitVariableNode: self! !


!InstanceVariableNode methodsFor: 'visiting' stamp: 'eem 9/6/2009 12:34'!
accept: aVisitor
	^aVisitor visitInstanceVariableNode: self! !


!LiteralVariableNode methodsFor: 'visiting' stamp: 'eem 9/6/2009 12:34'!
accept: aVisitor
	^aVisitor visitLiteralVariableNode: self! !


!TempVariableNode methodsFor: 'visiting' stamp: 'eem 9/6/2009 12:34'!
accept: aVisitor
	^aVisitor visitTempVariableNode: self! !


!RemoteTempVectorNode methodsFor: 'visiting' stamp: 'eem 9/6/2009 12:34'!
accept: aVisitor
	^aVisitor visitRemoteTempVectorNode: self! !

!classDefinition: #BlockNode category: #'Compiler-ParseNodes'!
ParseNode subclass: #BlockNode
	instanceVariableNames: 'arguments statements returns nArgsNode size remoteCopyNode temporaries optimized optimizedMessageNode actualScopeIfOptimized blockExtent remoteTempNode copiedValues closureCreationNode startOfLastStatement'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Compiler-ParseNodes'!
