[squeak-dev] The Trunk: Compiler-eem.165.mcz

commits at source.squeak.org commits at source.squeak.org
Tue Aug 17 21:41:03 UTC 2010


Eliot Miranda uploaded a new version of Compiler to project The Trunk:
http://source.squeak.org/trunk/Compiler-eem.165.mcz

==================== Summary ====================

Name: Compiler-eem.165
Author: eem
Time: 17 August 2010, 2:29:01.49 pm
UUID: f895af78-0bd4-4e18-94ba-0c69837d298e
Ancestors: Compiler-eem.164

Stage two cleanup of the old parse node sizers & emitters

Also:
Streamline Compiler>>#compile:in:classified:notifying:ifFail: .  requestor: send is unnecessary.
Fix comment typo inScanner>>scanAllTokenPositionsInto:

=============== Diff against Compiler-eem.164 ===============

Item was changed:
  ParseNode subclass: #MessageNode
  	instanceVariableNames: 'receiver selector precedence special arguments sizes equalNode caseErrorNode'
+ 	classVariableNames: 'MacroEmitters MacroPrinters MacroSelectors MacroSizers MacroTransformers StdTypers ThenFlag'
- 	classVariableNames: 'MacroEmitters MacroPrinters MacroSelectors MacroSizers MacroTransformers NewStyleMacroEmitters NewStyleMacroSizers StdTypers ThenFlag'
  	poolDictionaries: ''
  	category: 'Compiler-ParseNodes'!
  
  !MessageNode commentStamp: '<historical>' prior: 0!
  I represent a receiver and its message.
  	
  Precedence codes:
  	1 unary
  	2 binary
  	3 keyword
  	4 other
  	
  If special>0, I compile special code in-line instead of sending messages with literal methods as remotely copied contexts.!

Item was changed:
  ----- Method: MethodNode>>printWithClosureAnalysisOn: (in category 'printing') -----
  printWithClosureAnalysisOn: aStream 
+ 	self ensureClosureAnalysisDone.
- 
  	precedence = 1
  		ifTrue: 
  			[(self selector includesSubString: '()/')
  				ifTrue: [aStream nextPutAll: (self selector copyUpTo: $)).
  						arguments
  							do: [:arg| aStream nextPutAll: arg key]
  							separatedBy: [aStream nextPutAll: ', '].
  						aStream nextPut: $)]
  				ifFalse: [aStream nextPutAll: self selector]]  "no node for method selector"
  		ifFalse: 
  			[self selector keywords with: arguments do: 
  				[:kwd :arg | 
  				aStream nextPutAll: kwd; space.
  				arg printDefinitionForClosureAnalysisOn: aStream.
  				aStream space]].
  	comment == nil ifFalse: 
  			[aStream crtab: 1.
  			 self printCommentOn: aStream indent: 1].
  	temporaries size > 0 ifTrue: 
  			[aStream crtab: 1; nextPut: $|.
  			temporaries do: [:temp | 
  				aStream space.
  				temp printDefinitionForClosureAnalysisOn: aStream].
  			aStream space; nextPut: $|].
  	primitive > 0 ifTrue:
  		[(primitive between: 255 and: 519) ifFalse:  "Dont decompile quick prims  e.g, ^ self or ^instVar"
  			[aStream crtab: 1.
  			 self printPrimitiveOn: aStream]].
  	self printPropertiesOn: aStream.
  	self printPragmasOn: aStream.
  	aStream crtab: 1.
  	block printWithClosureAnalysisStatementsOn: aStream indent: 0!

Item was changed:
  ParseNode subclass: #MethodNode
  	instanceVariableNames: 'selectorOrFalse precedence arguments block primitive encoder temporaries properties sourceText locationCounter localsPool'
  	classVariableNames: ''
  	poolDictionaries: ''
  	category: 'Compiler-ParseNodes'!
  
+ !MethodNode commentStamp: 'eem 8/15/2010 10:49' prior: 0!
+ I am the root of the parse tree..
+ 
+ Instance Variables
+ 	arguments:			<SequenceableCollection>
+ 	block:				<BlockNode>
+ 	encoder:			<BytecodeEncoder>
+ 	localsPool:			<IdentitySet>
+ 	locationCounter:	<Integer>
+ 	precedence:		<Integer>
+ 	primitive:			<Integer>
+ 	properties:			<AdditionalMethodState|nil>
+ 	selectorOrFalse:	<Object>
+ 	sourceText:		<String|Text>
+ 	temporaries:		<SequenceableCollection>
+ 
+ arguments
+ 	- the collection of parsed or decompiled method arguments
+ 
+ block
+ 	- the BlockNode holding the method's statements
+ 
+ encoder
+ 	- the object that comprises the copiler's scope table, literal pool and back-end bytecode generator
+ 
+ localsPool
+ 	- a set used to determine the set of copied values for each block in the method
+ 
+ locationCounter
+ 	- an integer used to mark block scopes for the purposes of the closure transformation.  See BlockNode>>#analyseArguments:temporaries:rootNode:
+ 
+ precedence
+ 	- the precedence of the method's selector (see Symbol>>precedence)
+ 
+ primitive
+ 	- if non-zero this is the integer code of the method's primitive
+ 
+ properties
+ 	- the object used to accumulate method properties (a.k.a. pragmas)
+ 
+ selectorOrFalse
+ 	- the method's selector or false if this is a doit
+ 
+ sourceText
+ 	- the source test from which the method was compiled
+ 
+ temporaries
+ 	- the collection of parsed or decompiled method temporaries
+ !
- !MethodNode commentStamp: '<historical>' prior: 0!
- I am the root of the parse tree.!

Item was changed:
  ----- Method: MessageNode>>emitCodeForEffect:encoder: (in category 'code generation') -----
  emitCodeForEffect: stack encoder: encoder
  	"For #ifTrue:ifFalse: and #whileTrue: / #whileFalse: style messages, the pc is set to the jump instruction, so that mustBeBoolean exceptions can be shown correctly."
  	special > 0
  		ifTrue: 
  			[pc := 0.
+ 			self perform: (MacroEmitters at: special) with: stack with: encoder with: false]
- 			self perform: (NewStyleMacroEmitters at: special) with: stack with: encoder with: false]
  		ifFalse: 
  			[super emitCodeForEffect: stack encoder: encoder]!

Item was changed:
  ParseNodeVisitor subclass: #VariableScopeFinder
  	instanceVariableNames: 'theVariable'
  	classVariableNames: ''
  	poolDictionaries: ''
  	category: 'Compiler-Support'!
  
+ !VariableScopeFinder commentStamp: 'eem 8/14/2010 19:45' prior: 0!
+ A VariableScopeFinder is used to find the minimum enclosing scope of a variable in a method.  This is used when auto-declaring temporaries to find the smallest enclosing block in which to declare the temp.
- !VariableScopeFinder commentStamp: 'eem 8/12/2010 16:17' prior: 0!
- A VariableScopeFinder is used to find the minimum enclosing scope of a variable oin a method.  This is used when auto-declaring temporaries to find the smallest enclosing block in which to decare the temp.
  
  Instance Variables
  	theVariable:		<VariableNode>
  
  theVariable
  	- the varable whose scope is to be determined
  !

Item was changed:
  ----- Method: DecompilerConstructorForClosures>>codeMethod:block:tempVars:primitive:class: (in category 'constructor') -----
  codeMethod: selector block: block tempVars: vars primitive: primitive class: class
  
  	| blockNode selectorNode visibleTemps invisibleTemps arguments temporaries |
  	selectorNode := self codeSelector: selector code: nil.
  	tempVars := vars.
  	visibleTemps := OrderedCollection new.
  	invisibleTemps := OrderedCollection new.
  	tempVars do: [:t|
  				   ((t isIndirectTempVector or: [t scope >= 0])
  						ifTrue: [visibleTemps]
  						ifFalse: [invisibleTemps]) addLast: t].
  	arguments := visibleTemps copyFrom: 1 to: nArgs.
  	temporaries := visibleTemps copyFrom: nArgs + 1 to: visibleTemps size.
  	block
  		arguments: arguments;
  		temporaries: temporaries.
+ 	blockNode := MethodNode new
- 	blockNode := BytecodeAgnosticMethodNode new
  		selector: selectorNode
  		arguments: arguments
  		precedence: selector precedence
  		temporaries: temporaries
  		block: block
  		encoder: (EncoderForV3PlusClosures new initScopeAndLiteralTables
  					temps: visibleTemps, invisibleTemps
  					literals: literalValues
  					class: class)
  		primitive: primitive
  		properties: method properties copy.
  	blockNode properties method: blockNode.
  	^blockNode!

Item was changed:
  ----- Method: MethodNode>>properties (in category 'code generation') -----
  properties
+ 	^properties!
- 	^ properties!

Item was changed:
  ----- Method: MethodNode>>generate: (in category 'code generation') -----
  generate: trailer 
+ 	"The receiver is the root of a parse tree. Answer a CompiledMethod.
+ 	 The argument, trailer, is arbitrary but is typically either the reference
+ 	 to the source code that is stored with every CompiledMethod, or an
+ 	 encoding of the method's temporary names."
- 	"The receiver is the root of a parse tree. Answer a CompiledMethod. The
- 	argument, trailer, is the references to the source code that is stored with 
- 	every CompiledMethod."
  
+ 	| primErrNode blkSize nLits literals stack method |
+ 	self generate: trailer ifQuick:
+ 			[:m |
+ 			  m	literalAt: 2 put: encoder associationForClass;
+ 				properties: properties.
+ 			^m].
- 	| literals blkSize method nArgs nLits primErrNode stack strm |
- 	self generate: trailer ifQuick: 
- 		[:m |
- 		literals := encoder allLiterals.
- 		(nLits := literals size) > 255 ifTrue:
- 			[^self error: 'Too many literals referenced'].
- 		1 to: nLits do: [:lit | m literalAt: lit put: (literals at: lit)].
- 		m properties: properties.
- 		^m].
  	primErrNode := self primitiveErrorVariableName ifNotNil:
  						[encoder fixTemp: self primitiveErrorVariableName].
+ 	encoder supportsClosureOpcodes ifTrue:
+ 		[self ensureClosureAnalysisDone.
+ 		 encoder rootNode: self. "this is for BlockNode>>sizeCodeForClosureValue:"].
+ 	blkSize := (block sizeCodeForEvaluatedValue: encoder)
+ 				+ (primErrNode
+ 					ifNil: [0]
+ 					ifNotNil: [primErrNode sizeCodeForStore: encoder "The VM relies on storeIntoTemp: (129)"]).
+ 	method := CompiledMethod
- 	nArgs := arguments size.
- 	blkSize := (block sizeForEvaluatedValue: encoder)
- 				+ (primErrNode ifNil: [0] ifNotNil: [2 "We force store-long (129)"]).
- 	(nLits := (literals := encoder allLiterals) size) > 255 ifTrue:
- 		[^self error: 'Too many literals referenced'].
- 	method := CompiledMethod	"Dummy to allocate right size"
  				newBytes: blkSize
  				trailerBytes: trailer 
+ 				nArgs: arguments size
+ 				nTemps: (encoder supportsClosureOpcodes
+ 							ifTrue: [| locals |
+ 									locals := arguments,
+ 											  temporaries,
+ 											  (primErrNode
+ 												ifNil: [#()]
+ 												ifNotNil: [{primErrNode}]).
+ 									encoder
+ 										noteBlockExtent: block blockExtent
+ 										hasLocals: locals.
+ 									locals size]
+ 							ifFalse: [encoder maxTemp])
- 				nArgs: nArgs
- 				nTemps: encoder maxTemp
  				nStack: 0
+ 				nLits: (nLits := (literals := encoder allLiterals) size)
- 				nLits: nLits
  				primitive: primitive.
+ 	nLits > 255 ifTrue:
+ 		[^self error: 'Too many literals referenced'].
+ 	1 to: nLits do: [:lit | method literalAt: lit put: (literals at: lit)].
+ 	encoder streamToMethod: method.
- 	strm := ReadWriteStream with: method.
- 	strm position: method initialPC - 1.
  	stack := ParseStack new init.
+ 	primErrNode ifNotNil: [primErrNode emitCodeForStore: stack encoder: encoder].
+ 	stack position: method numTemps.
+ 	block emitCodeForEvaluatedValue: stack encoder: encoder.
+ 	stack position ~= (method numTemps + 1) ifTrue:
- 	primErrNode ifNotNil: [primErrNode emitStore: stack on: strm].
- 	block emitForEvaluatedValue: stack on: strm.
- 	stack position ~= 1 ifTrue:
  		[^self error: 'Compiler stack discrepancy'].
+ 	encoder methodStreamPosition ~= (method size - trailer size) ifTrue:
- 	strm position ~= (method size - trailer size) ifTrue:
  		[^self error: 'Compiler code size discrepancy'].
+ 	method needsFrameSize: stack size - method numTemps.
- 	method needsFrameSize: stack size.
- 	1 to: nLits do: [:lit | method literalAt: lit put: (literals at: lit)].
  	method properties: properties.
  	^method!

Item was changed:
  ----- Method: MessageNode>>sizeCodeForEffect: (in category 'code generation') -----
  sizeCodeForEffect: encoder
  
  	special > 0 
+ 		ifTrue: [^self perform: (MacroSizers at: special) with: encoder with: false].
- 		ifTrue: [^self perform: (NewStyleMacroSizers at: special) with: encoder with: false].
  	^super sizeCodeForEffect: encoder!

Item was changed:
  ----- Method: Compiler>>compile:in:classified:notifying:ifFail: (in category 'public access') -----
  compile: textOrStream in: aClass classified: aCategory notifying: aRequestor ifFail: failBlock 
  	"Answer a MethodNode for the argument, textOrStream. If the 
  	MethodNode can not be created, notify the argument, aRequestor; if 
  	aRequestor is nil, evaluate failBlock instead. The MethodNode is the root 
  	of a parse tree. It can be told to generate a CompiledMethod to be 
  	installed in the method dictionary of the argument, aClass."
+ 
- 	
- 	| methodNode |
  	self from: textOrStream
  		class: aClass
  		classified: aCategory 
  		context: nil
  		notifying: aRequestor.
+ 	^self
+ 		translate: sourceStream
+ 		noPattern: false
+ 		ifFail: failBlock
- 	methodNode := self translate: sourceStream noPattern: false ifFail: failBlock.
- 	methodNode encoder requestor: requestor.
- 	^methodNode.
  !

Item was changed:
  ----- Method: MessageNode class>>initialize (in category 'class initialization') -----
  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:).
  	MacroTransformers := 
  		#(	transformIfTrue: transformIfFalse: transformIfTrueIfFalse: transformIfFalseIfTrue:
  			transformAnd: transformOr:
  			transformWhile: transformWhile: transformWhile: transformWhile:
  			transformToDo: transformToDo:
  			transformCase: transformCase:
  			transformIfNil: transformIfNil:  transformIfNilIfNotNil: transformIfNotNilIfNil:).
+ 	MacroEmitters := 
- 	MacroEmitters := NewStyleMacroEmitters := 
  		#(	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:).
+ 	MacroSizers := 
- 	MacroSizers := NewStyleMacroSizers := 
  		#(	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:).
  	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:)!

Item was changed:
  ----- Method: Scanner>>scanAllTokenPositionsInto: (in category 'expression types') -----
  scanAllTokenPositionsInto: aBlock
  	"Evaluate aBlock with the start and end positions of all separate non-white-space tokens, including comments."
  
  	| lastMark |
  	lastMark := 1.
  	[currentComment notNil ifTrue:
  		[currentComment do:
  			[:cmnt| | idx |
  			 idx := source originalContents indexOfSubCollection: cmnt startingAt: lastMark.
  			 (idx > 0 and: [idx < mark]) ifTrue:
  				[aBlock value: idx - 1 value: (lastMark := idx + cmnt size)]].
  		 currentComment := nil].
  	mark notNil ifTrue:
  		[(token == #- 
  		  and: [(self typeTableAt: hereChar) = #xDigit]) ifTrue:
  			[| savedMark |
  			 savedMark := mark.
  			 self scanToken.
  			 token := token negated.
  			 mark := savedMark].
  		"Compensate for the fact that the parser uses two character lookahead.  Normally we must
+ 		  remove the extra two characters.  But this mustn't happen for the last token at the end of stream."
- 		  remove the extra two chaacters.  But this mustn't happen for the last token at the end of stream."
  		 aBlock
  			value: mark
  			value: (source atEnd
  					ifTrue: [tokenType := #doIt. "to cause an immediate ^self" source position]
  					ifFalse: [source position - 2])].
  	 (tokenType = #rightParenthesis
  	  or: [tokenType == #doIt]) ifTrue:
  		[^self].
  	tokenType = #leftParenthesis
  		ifTrue: 
  			[self scanToken; scanAllTokenPositionsInto: aBlock]
  		ifFalse: 
  			[(tokenType = #word or: [tokenType = #keyword or: [tokenType = #colon]])
  				ifTrue: 
  					[self scanLitWord.
  					 token = #true ifTrue: [token := true].
  					 token = #false ifTrue: [token := false].
  					 token = #nil ifTrue: [token := nil]]
  				ifFalse:
  					[(token == #- 
  					  and: [(self typeTableAt: hereChar) = #xDigit])
  						ifTrue: 
  							[self scanToken.
  							 token := token negated]]].
  		self scanToken.
  	true] whileTrue!

Item was changed:
  ----- Method: MessageNode>>sizeCodeForValue: (in category 'code generation') -----
  sizeCodeForValue: encoder
  	| total |
  	special > 0 
+ 		ifTrue: [^self perform: (MacroSizers at: special) with: encoder with: true].
- 		ifTrue: [^self perform: (NewStyleMacroSizers at: special) with: encoder with: true].
  	receiver == NodeSuper
  		ifTrue: [selector := selector copy "only necess for splOops"].
  	total := selector sizeCode: encoder args: arguments size super: receiver == NodeSuper.
  	receiver == nil 
  		ifFalse: [total := total + (receiver sizeCodeForValue: encoder)].
  	sizes := arguments collect: 
  					[:arg | | argSize | 
  					argSize := arg sizeCodeForValue: encoder.
  					total := total + argSize.
  					argSize].
  	^total!

Item was changed:
  ----- Method: MessageNode>>emitCodeForValue:encoder: (in category 'code generation') -----
  emitCodeForValue: stack encoder: encoder
  	"For #ifTrue:ifFalse: and #whileTrue: / #whileFalse: style messages, the pc is set to the jump instruction, so that mustBeBoolean exceptions can be shown correctly."
  	special > 0
  		ifTrue: 
  			[pc := 0.
+ 			self perform: (MacroEmitters at: special) with: stack with: encoder with: true]
- 			self perform: (NewStyleMacroEmitters at: special) with: stack with: encoder with: true]
  		ifFalse: 
  			[receiver ~~ nil ifTrue: [receiver emitCodeForValue: stack encoder: encoder].
  			arguments do: [:argument | argument emitCodeForValue: stack encoder: encoder].
  			pc := encoder methodStreamPosition + 1. "debug pc is first byte of the send, i.e. the next byte".
  			selector
  				emitCode: stack
  				args: arguments size
  				encoder: encoder
  				super: receiver == NodeSuper]!




More information about the Squeak-dev mailing list