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

commits at source.squeak.org commits at source.squeak.org
Tue Mar 14 00:17:52 UTC 2017

Eliot Miranda uploaded a new version of VMMaker to project VM Maker:

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

Name: VMMaker.oscog-eem.2149
Author: eem
Time: 13 March 2017, 5:16:33.83321 pm
UUID: e49449d0-624a-4ad6-91a9-0ea0d0c0f195
Ancestors: VMMaker.oscog-eem.2148, VMMaker.oscog-cb.2148

Merge VMMaker.oscog-eem.2148 & VMMaker.oscog-cb.2148.

Reimplement the fix in for VMMaker.oscog-eem.2148
	context := ignoreContext
		ifTrue: [objectMemory nilObject ]
		ifFalse: [self ensureFrameIsMarried: localFP SP: localSP + (numCopiedArg * objectMemory bytesPerOop)]
and revert Clément's work-arounds for the bug.
Use TMethod>>replaceNodesIn: instead of the inlined version in some places.  It's much nicer simply to move the pass that transforms conditional assignments to its own method (ensureConditionalAssignmentsAreTransformedIn:) prior to any inlining attempts.

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

Item was added:
+ ----- Method: SocketPluginSimulator>>sqResolverLocalAddress (in category 'simulation') -----
+ sqResolverLocalAddress
+ 	"For now don't simulate the implicit semaphore."
+ 	| bytes |
+ 	bytes := NetNameResolver primLocalAddress.
+ 	self assert: bytes size = 4.
+ 	"Effectively netAddressToInt: bytes"
+ 	^	((bytes at: 4)) +
+ 		((bytes at: 3) <<8) +
+ 		((bytes at: 2) <<16) +
+ 		((bytes at: 1) <<24)!

Item was removed:
- ----- Method: StackInterpreterSimulator>>externalWriteBackHeadFramePointers (in category 'stack pages') -----
- externalWriteBackHeadFramePointers
- 	self assert: (localFP = framePointer
- 				or: [localFP = (self frameCallerFP: framePointer)]).
- 	super externalWriteBackHeadFramePointers!

Item was changed:
  ----- Method: StackInterpreterSimulator>>getErrorObjectFromPrimFailCode (in category 'debugging traps') -----
+ 	(primFailCode > 1 and: [(#(primitiveNew primitiveFetchNextMourner) includes: primitiveFunctionPointer) not]) ifTrue: [self halt].
- 	primFailCode > 1 ifTrue: [self halt].
  	^super getErrorObjectFromPrimFailCode!

Item was changed:
  ----- Method: StackInterpreterSimulator>>primitiveDirectoryEntry (in category 'file primitives') -----
  	| name pathName arrayNilOrSymbol result |
  	name := self stringOf: self stackTop.
  	pathName := self stringOf: (self stackValue: 1).
- 	"temporary work-around to make it work in Pharo..."
- 	self cppIf: PharoVM ifTrue: [ pathName := Smalltalk imagePath ].
  	self successful ifFalse:
  		[^self primitiveFail].
  	arrayNilOrSymbol := FileDirectory default primLookupEntryIn: pathName name: name.
  	arrayNilOrSymbol ifNil:
  		[self pop: 3 thenPush: objectMemory nilObject.
  	arrayNilOrSymbol isArray ifFalse:
  		["arrayNilOrSymbol ~~ #primFailed ifTrue:
  			[self halt]. "
  		self transcript show: name , ' NOT FOUND'.
  		 ^self primitiveFail].
  	result := PharoVM 
  			[self makeDirEntryName: (arrayNilOrSymbol at: 1) size: (arrayNilOrSymbol at: 1) size
  				createDate: (arrayNilOrSymbol at: 2) modDate: (arrayNilOrSymbol at: 3)
  				isDir: (arrayNilOrSymbol at: 4) fileSize: (arrayNilOrSymbol at: 5)
+ 				posixPermissions: (arrayNilOrSymbol at: 6 ifAbsent: [8r644]) isSymlink: (arrayNilOrSymbol at: 7 ifAbsent: [false]) ]
- 				posixPermissions: (arrayNilOrSymbol at: 6) isSymlink: (arrayNilOrSymbol at: 7) ]
  			[self makeDirEntryName: (arrayNilOrSymbol at: 1) size: (arrayNilOrSymbol at: 1) size
  				createDate: (arrayNilOrSymbol at: 2) modDate: (arrayNilOrSymbol at: 3)
  				isDir: (arrayNilOrSymbol at: 4) fileSize: (arrayNilOrSymbol at: 5) ].
  	self pop: 3 thenPush: result!

Item was added:
+ ----- Method: TMethod>>ensureConditionalAssignmentsAreTransformedIn: (in category 'inlining') -----
+ ensureConditionalAssignmentsAreTransformedIn: aCodeGen
+ 	"Make passes transforming
+ 		foo := expr ifTrue: [a] ifFalse: [b]
+ 	 into
+ 		expr ifTrue: [foo := a] ifFalse: [foo := b]
+ 	 until no such instances exist in the tree.  This is needed for correct inlining
+ 	 given the limitations of inlineCodeOrNilForStatement:returningNodes:in:"
+ 	| transformedAssignments |
+ 	[transformedAssignments := Dictionary new.
+ 	 parseTree
+ 		nodesDo:
+ 			[:node|
+ 			(self transformConditionalAssignment: node in: aCodeGen) ifNotNil:
+ 				[:replacement|
+ 				 transformedAssignments at: node put: replacement]]
+ 		unless: "Don't inline the arguments to asserts to keep the asserts readable"
+ 			[:node|
+ 			node isSend
+ 			and: [node selector == #cCode:inSmalltalk:
+ 				or: [aCodeGen isAssertSelector: node selector]]].
+ 	 transformedAssignments notEmpty
+ 	 and: [self replaceNodesIn: transformedAssignments.
+ 		  true]] whileTrue
+ 		!

Item was changed:
  ----- Method: TMethod>>transformToStructClassMethodFor: (in category 'transformations') -----
  transformToStructClassMethodFor: aCCodeGenerator
  	"Transform this method so that it can be used on an instance of a struct class (VMStructType subclass).
  	 Convert inst var refs into field dereferences of self.  Add selfSelector as the first argument with the
  	 right struct type. As a complete hack to avoid breaking the inlinert don't use 'self' as the name for self
  	 as this causes serious type redefinitions ``somewhere'' in the inliner."
  	| replacements selfNode typeForSelf |
  	self isStructAccessor ifTrue:
  		[^self returnType: (definingClass returnTypeForAccessor: selector)].
  	replacements := IdentityDictionary new.
  	selfNode := TVariableNode new setName: 'self_in_', (aCCodeGenerator cFunctionNameFor: selector).
  	args do:
  		(definingClass isAccessor: var) ifTrue:
  			[self error: 'In ', definingClass name, '>>', selector, ' ', var, ' arg shadows struct field and will break during translation!!']].
  	parseTree nodesDo:
  		node isVariable ifTrue:
  			[node name = 'self' ifTrue:
  				[replacements at: node put: selfNode copy].
  			 (definingClass isAccessor: node name) ifTrue:
  					at: node
  					put: (TSendNode new
  							setSelector: node name asSymbol
  							receiver: selfNode
  							arguments: #())]]].
  	replacements notEmpty ifTrue:
+ 		[self replaceNodesIn: replacements].
- 		[parseTree := parseTree replaceNodesIn: replacements].
  	typeForSelf := self typeForSelf.
  	self assert: (typeForSelf notNil and: [typeForSelf ~~ #implicit]).
  	self declarationAt: (args addFirst: selfNode name)
  		put: (declarations removeKey: 'self'), '_in_', (aCCodeGenerator cFunctionNameFor: selector)!

Item was changed:
  ----- Method: TMethod>>tryToInlineMethodExpressionsIn: (in category 'inlining') -----
  tryToInlineMethodExpressionsIn: aCodeGen
  	"Expand any (complete) inline methods sent by this method as receivers or parameters.
  	 Answer if anything was inlined."
  	| sendsToInline |
  	sendsToInline := Dictionary new: 100.
- 			(self transformConditionalAssignment: node in: aCodeGen) ifNotNil:
- 				[:replacement|
- 				 sendsToInline at: node put: replacement].
  			(self inlineableFunctionCall: node in: aCodeGen) ifTrue:
  				[(self inlineFunctionCall: node in: aCodeGen) ifNotNil:
  					 sendsToInline at: node put: replacement]]]
  		unless: "Don't inline the arguments to asserts to keep the asserts readable"
  			node isSend
  			and: [node selector == #cCode:inSmalltalk:
  				or: [aCodeGen isAssertSelector: node selector]]].
  	sendsToInline isEmpty ifTrue:
+ 	self replaceNodesIn: sendsToInline.
- 	parseTree := parseTree replaceNodesIn: sendsToInline.

Item was changed:
  ----- Method: TMethod>>tryToInlineMethodStatementsIn:statementListsInto: (in category 'inlining') -----
  tryToInlineMethodStatementsIn: aCodeGen statementListsInto: aBlock
  	"Expand any (complete) inline methods sent by this method as top-level statements.
  	 Answer if anything was inlined."
  	| stmtLists didSomething newStatements returningNodes |
  	didSomething := false.
  	returningNodes := Set new.
- 	stmtLists := self statementsListsForInliningIn: aCodeGen.
- 	"stmtLists may include expressions that are used for value but the exitVar is distant because its in an ifTrue:ifTrue:,
- 	 e.g. in
- 			context := ignoreContext
- 							ifTrue: [objectMemory nilObject ]
- 							ifFalse: [self ensureFrameIsMarried: localFP SP: localSP + (numCopiedArg * objectMemory bytesPerOop)].
- 	ensureFrameIsMarried:SP: *does* have an exitVar, context, but it is the exitVar for the ifTrue:ifFalse:.  So
- 	inlineCodeOrNilForStatement:returningNodes:in: should not consider inlining these in its last phrase where exitVar is nil."
  	parseTree nodesDo:
  		node isReturn ifTrue:
  			[returningNodes add: node expression.
  			 node expression isConditionalSend ifTrue:
+ 				[returningNodes addAll: (node expression args collect: [:stmtList| stmtList statements last])]]].
+ 	stmtLists := self statementsListsForInliningIn: aCodeGen.
- 				[returningNodes addAll: (node expression args collect: [:stmtList| stmtList statements last])]].
- 		node isAssignment ifTrue:
- 			[node expression nodesDo:
- 				[:assignmentSubNode|
- 				(stmtLists includes: assignmentSubNode) ifTrue:
- 					[stmtLists remove: assignmentSubNode]]]].
  	stmtLists do:
  		newStatements := OrderedCollection new: stmtList statements size.
  		stmtList statements do:
  			(self inlineCodeOrNilForStatement: stmt returningNodes: returningNodes in: aCodeGen)
  				ifNil: [newStatements addLast: stmt]
  				ifNotNil: [:inlinedStmts|
  					didSomething := true.
  					newStatements addAllLast: inlinedStmts]].
  		stmtList setStatements: newStatements asArray].
  	"This is a hack; forgive me. The inlining above tends to keep return statements in statement lists.
  	 In the case of returning ifs we don't want the returns in case the returning if is generated as an expression."
  	returningNodes do:
  		 (returningNode isConditionalSend
  		  and: [returningNode args anySatisfy: [:alternativeNode| alternativeNode endsWithReturn]]) ifTrue:
  			[returningNode args withIndexDo:
  				[:alternativeNode :index|
  				 alternativeNode endsWithReturn ifTrue:
  					[returningNode args at: index put: alternativeNode copyWithoutReturn]]]].
  	aBlock value: stmtLists.

Item was changed:
  ----- Method: TMethod>>tryToInlineMethodsIn: (in category 'inlining') -----
  tryToInlineMethodsIn: aCodeGen
  	"Expand any (complete) inline methods sent by this method.
  	 Set the complete flag when all inlining has been done.
  	 Answer if something was inlined."
  	| didSomething statementLists |
  	"complete ifTrue:
  	self definedAsMacro ifTrue:
  		[complete ifTrue:
  		 ^complete := true].
+ 	self ensureConditionalAssignmentsAreTransformedIn: aCodeGen.
  	didSomething := self tryToInlineMethodStatementsIn: aCodeGen statementListsInto: [:stmtLists| statementLists := stmtLists].
  	didSomething := (self tryToInlineMethodExpressionsIn: aCodeGen) or: [didSomething].
  	didSomething ifTrue:
  		[writtenToGlobalVarsCache := nil].
  	complete ifFalse:
  		[self checkForCompletenessIn: aCodeGen.
  		 complete ifTrue: [didSomething := true]].  "marking a method complete is progress"

More information about the Vm-dev mailing list