[Vm-dev] VM Maker: VMMaker.oscog-eem.931.mcz

commits at source.squeak.org commits at source.squeak.org
Fri Nov 14 19:36:43 UTC 2014


Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.931.mcz

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

Name: VMMaker.oscog-eem.931
Author: eem
Time: 14 November 2014, 11:34:08.053 am
UUID: 13d1914a-98dc-4d3a-8e80-ec9ce100239b
Ancestors: VMMaker.oscog-eem.930

Yet more tweaking to get the same inlining behaviour
as before the constant to send putch for ShiftForWord.
Refactor mostBasicConstantSelectors etc into the
class side of VMBasicConstants.

=============== Diff against VMMaker.oscog-eem.930 ===============

Item was changed:
  ----- Method: CCodeGenerator>>isConstantNode:valueInto: (in category 'utilities') -----
  isConstantNode: aNode valueInto: aBlock
  	"Answer if aNode evaluates to a constant, and if so, evaluate aBlock with the value of that constant."
  
  	aNode isConstant ifTrue:
  		[aBlock value: aNode value.
  		 ^true].
  	aNode isSend ifFalse:
  		[^false].
+ 	(self anyMethodNamed: aNode selector)
+ 		ifNil:
+ 			[(VMBasicConstants valueOfBasicSelector: aNode selector) ifNotNil:
+ 				[:value|
+ 				 aBlock value: value.
+ 				 ^true]]
+ 		ifNotNil:
+ 			[:m|
+ 			(m statements size = 1
+ 			 and: [m statements last isReturn]) ifTrue:
+ 				[^self isConstantNode: m statements last expression valueInto: aBlock]].
- 	(self anyMethodNamed: aNode selector) ifNotNil:
- 		[:m|
- 		(m statements size = 1
- 		 and: [m statements last isReturn]) ifTrue:
- 			[^self isConstantNode: m statements last expression valueInto: aBlock]].
  	^false!

Item was removed:
- ----- Method: CCodeGenerator>>mostBasicConstantSelectors (in category 'accessing') -----
- mostBasicConstantSelectors
- 	"c.f. VMBasicConstants class>>#mostBasicConstantNames"
- 	^#(baseHeaderSize bytesPerOop bytesPerWord shiftForWord wordSize)!

Item was changed:
  ----- Method: CCodeGenerator>>shouldGenerateAsInterpreterProxySend: (in category 'utilities') -----
  shouldGenerateAsInterpreterProxySend: aSendNode
  	^(self messageReceiverIsInterpreterProxy: aSendNode)
+ 	  and: [(VMBasicConstants mostBasicConstantSelectors includes: aSendNode selector) not]!
- 	  and: [(self mostBasicConstantSelectors includes: aSendNode selector) not]!

Item was changed:
  ----- Method: TMethod>>isNode:substitutableFor:inMethod:in: (in category 'inlining') -----
  isNode: aNode substitutableFor: argName inMethod: targetMeth in: aCodeGen
  	"Answer if the given parameter node may be substituted directly into the body of
  	 the method during inlining, instead of being bound to the actual parameter variable.
  	 We allow a constant, a local variable, or a formal parameter, or simple expressions
  	 involving only these to to be directly substituted. Note that global variables cannot
  	 be subsituted into methods with possible side effects (i.e., methods that may assign
  	 to global variables) because the inlined method might depend on having the value of
  	 the global variable captured when it is passed in as an argument."
  
  	| madeNonTrivialCall count constantExpression usageCount |
  	aNode isConstant ifTrue: [^true].
  
  	aNode isVariable ifTrue:
  		[((locals includes: aNode name)
  		 or: [(args includes: aNode name)
  		 or: [#('self' 'true' 'false' 'nil') includes: aNode name]]) ifTrue: [^true].
  		"We can substitute any variable provided it is only read in the method being inlined,
  		 and if it is not read after any non-trivial call (which may update the variable)."
  		madeNonTrivialCall := false.
  		(targetMeth isComplete
  		 and: [targetMeth parseTree
  				noneSatisfy:
  					[:node|
  					 (node isSend
  					  and: [(aCodeGen isBuiltinSelector: node selector) not]) ifTrue:
  						[madeNonTrivialCall := true].
  					 (madeNonTrivialCall and: [node isVariable and: [node name = argName]])
  					 or: [node isAssignment
  						  and: [node variable name = argName]]]
  				unless:
  					[:node|
  					node isSend and: [aCodeGen isAssertSelector: node selector]]]) ifTrue:
  			[^true].
  		^targetMeth maySubstituteGlobal: aNode name in: aCodeGen].
  
  	"For now allow literal blocks to be substituted.  They better be accessed only
  	 with value[:value:*] messages though!!"
  	aNode isStmtList ifTrue: [^true].
  
  	count := 0.
  	constantExpression := true.
  	"scan expression tree; must contain only constants, builtin ops, and inlineable vars"
  	aNode nodesDo:
  		[:node|
  		node isConstant
  			ifTrue: [] ifFalse:
  		[node isSend
  			ifTrue:
+ 				[((VMBasicConstants mostBasicConstantSelectors includes: node selector)
- 				[((aCodeGen mostBasicConstantSelectors includes: node selector)
  				  or: [node isBuiltinOperator]) ifFalse: [^false].
  				 count := count + 1] ifFalse:
  		[node isVariable ifTrue:
  			[(aCodeGen isNonArgumentImplicitReceiverVariableName: node name) ifFalse:
  				[constantExpression := false.
  				((locals includes: node name)
  				 or: [(args includes: node name)
  				 or: [(#('self' 'true' 'false' 'nil') includes: node name)
  				 or: [targetMeth maySubstituteGlobal: node name in: aCodeGen]]]) ifFalse: [^false]]] ifFalse:
  		[^false]]]].
  	"inline constant expressions"
  	constantExpression ifNil: [^true].
  
  	"scan target to find usage count"
  	usageCount := 0.
  	targetMeth parseTree nodesDo:
  		[:node|
  		(node isVariable and: [node name = argName]) ifTrue:
  			[usageCount := usageCount + 1]].
  	"Now only inline expressions if they are used only once or are simple
  	 w.r.t. the usage count; a heuristic that seems to work well enough."
  	^usageCount = 1 or: [count <= usageCount]!

Item was changed:
  ----- Method: TSendNode>>bindVariableUsesIn:andConstantFoldIf:in: (in category 'transformations') -----
  bindVariableUsesIn: aDictionary andConstantFoldIf: constantFold in: codeGen
  	"Answer either the receiver, if it contains no references to the given variables, or a new node with the given variables rebound.
  	 Attempt to constant-fold and answer a constant node commented with the original expression.
  	 Commenting with the original expression is important because it allows us to detect shared cases.
  	 e.g. currentBytecode bitAnd: 15 is the same in case 1 and case 17, but '1 /* 1 bitAnd: 15 */' differs
  	 from '1 /* 17 bitAnd: 15 */', whereas '1 /* currentBytecode bitAnd: 15 */' doesn't change."
  	| newReceiver newArguments |
  	"Constant-fold shiftForWord, but not BytesPerWord"
+ 	((VMBasicConstants mostBasicConstantSelectors includes: selector)
- 	((codeGen mostBasicConstantSelectors includes: selector)
  	 and: [(codeGen isBuiltinSelector: selector) not]) ifTrue:
  		[codeGen isConstantNode: self valueInto:
  			[:val|
  			 ^TConstantNode new
  				setValue: val;
  				yourself]].
  	newReceiver := receiver bindVariableUsesIn: aDictionary andConstantFoldIf: constantFold in: codeGen.
  	newArguments := arguments collect: [:a| a bindVariableUsesIn: aDictionary andConstantFoldIf: constantFold in: codeGen].
  	(newReceiver = receiver
  	 and: [newArguments = arguments]) ifTrue:
  		[^self].
  	(constantFold
  	 and: [newReceiver isConstant and: [newReceiver value isInteger]
  	 and: [(newArguments allSatisfy: [:ea| ea isConstant and: [ea value isInteger]])
  	 and: [codeGen isBuiltinSelector: selector]]]) ifTrue:
  		[| value |
  		value := [newReceiver value perform: selector withArguments: (newArguments collect: [:ea| ea value])]
  					on: Error
  					do: [:ea| nil].
  		 (value isInteger
  		 or: [value == true
  		 or: [value == false]]) ifTrue:
  			[^TConstantNode new
  				setValue: value;
  				"We assume Message prints its keywords and arguments interleaved.
  				 e.g. that (Message selector: #between:and: arguments: #(0 1)) printString = 'between: 0 and: 1'"
  				comment: (receiver isLeaf
  								ifTrue: [receiver printString]
  								ifFalse: ['(', receiver printString, ')']),
  							' ',
  							(Message selector: selector arguments: (arguments collect: [:ea| ea value])) printString;
  				yourself]].
  	^self shallowCopy
  		receiver: newReceiver;
  		arguments: newArguments;
  		yourself
  		!

Item was changed:
+ ----- Method: VMBasicConstants class>>mostBasicConstantNames (in category 'C translation') -----
- ----- Method: VMBasicConstants class>>mostBasicConstantNames (in category 'accessing') -----
  mostBasicConstantNames
+ 	"c.f. mostBasicConstantSelectors"
+ 	^#(BaseHeaderSize BytesPerWord BytesPerOop ShiftForWord BytesPerWord)!
- 	"c.f. CCodeGenerator class>>#mostBasicConstantSelectors"
- 	^#(BaseHeaderSize BytesPerWord BytesPerOop)!

Item was added:
+ ----- Method: VMBasicConstants class>>mostBasicConstantSelectors (in category 'C translation') -----
+ mostBasicConstantSelectors
+ 	"c.f. mostBasicConstantNames"
+ 	^#(baseHeaderSize wordSize bytesPerOop shiftForWord bytesPerWord "bytesPerWord isn't used, but kept for history")!

Item was added:
+ ----- Method: VMBasicConstants class>>valueOfBasicSelector: (in category 'C translation') -----
+ valueOfBasicSelector: selector
+ 	"Answer the numberic value of a basic constant accessed via the selector.
+ 	 Answer nil if selector is not a basic constant accessor."
+ 	"self mostBasicConstantSelectors collect: [:s| {s. self valueOfBasicSelector: s}]"
+ 	| index key |
+ 	^((index := self mostBasicConstantSelectors indexOf: selector) > 0
+ 	  and: [(key := self mostBasicConstantNames at: index ifAbsent: []) notNil
+ 	  and: [self includesKey: key]]) ifTrue:
+ 		[classPool at: key]!



More information about the Vm-dev mailing list