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

Esteban Lorenzano estebanlm at gmail.com
Sat Dec 3 10:46:58 UTC 2016


This change introduced a problem when generating sources… now I have an error: 

'Local variable 'bytecodePC' may mask global when inlining recordBcpc:’

cheers, 
Esteban

> On 2 Dec 2016, at 18:00, commits at source.squeak.org wrote:
> 
> 
> Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
> http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2020.mcz
> 
> ==================== Summary ====================
> 
> Name: VMMaker.oscog-eem.2020
> Author: eem
> Time: 2 December 2016, 8:59:35.572375 am
> UUID: f53bedb4-3a2d-42ed-bf04-56ed996e7aa0
> Ancestors: VMMaker.oscog-eem.2019
> 
> RegisterAllocatingCogit:
> Give sensible names to the three reconciliation methods in CogRegisterAllocatingSimStackEntry.  Be sure to use registerOrNone, not just liveRegister.
> Refactor mergeCurrentSimStackWith: for clarity.
> Have restoreSimStackAtMergePoint: maintain optStatus.
> 
> Execution gets as far as a stack imbalance in a send from Dictionary>noCheckNoGrowFillFrom: during EventSensor startUp:.
> 
> =============== Diff against VMMaker.oscog-eem.2019 ===============
> 
> Item was added:
> + ----- Method: CogRegisterAllocatingSimStackEntry>>reconcileBackwardsWith: (in category 'compile abstract instructions') -----
> + reconcileBackwardsWith: targetEntry
> + 	"Make the state of the receiver, a stack entry at a backward jump,
> + 	 the same as the corresponding simStackEntry at the target of the jump"
> + 	<var: #targetEntry type: #'targetEntry *'>
> + 	| targetReg |
> + 	(targetReg := targetEntry registerOrNone) = NoReg ifTrue:
> + 		[^self].
> + 	targetEntry type = SSConstant ifTrue:
> + 		[self assert: (type = SSConstant and: [constant = targetEntry constant]).
> + 		 ^self].
> + 	liveRegister ~= NoReg ifTrue:
> + 		[liveRegister ~= targetReg ifTrue:
> + 			[cogit MoveR: liveRegister R: targetReg].
> + 		 ^self].
> + 	type caseOf: {
> + 		[SSBaseOffset]	-> [cogit MoveMw: offset r: register R: targetReg].
> + 		[SSSpill]		-> [cogit MoveMw: offset r: register R: targetReg].
> + 		[SSConstant]	-> [cogit genMoveConstant: constant R: targetReg].
> + 		[SSRegister]	-> [register ~= targetReg ifTrue:
> + 								[cogit MoveR: register R: targetReg]] }!
> 
> Item was added:
> + ----- Method: CogRegisterAllocatingSimStackEntry>>reconcileForwardsWith: (in category 'compile abstract instructions') -----
> + reconcileForwardsWith: targetEntry
> + 	"Make the state of the receiver, a stack entry at the end of a basic block,
> + 	 the same as the corresponding simStackEntry at the target of a preceding
> + 	 jump to the beginning of the next basic block."
> + 	<var: #targetEntry type: #'targetEntry *'>
> + 	| targetReg |
> + 	(targetReg := targetEntry registerOrNone) = NoReg ifTrue:
> + 		[self assert: (self isSameEntryAs: targetEntry).
> + 		 ^self].
> + 	liveRegister ~= NoReg ifTrue:
> + 		[liveRegister ~= targetReg ifTrue:
> + 			[cogit MoveR: liveRegister R: targetReg].
> + 		 (spilled and: [targetEntry spilled not]) ifTrue:
> + 			[cogit AddCq: objectRepresentation wordSize R: SPReg].
> + 		 ^self].
> + 	spilled
> + 		ifTrue:
> + 			[targetEntry spilled ifTrue:
> + 				[cogit PopR: targetReg. "KISS; generate the least number of instructions..."
> + 				 ^self]]
> + 		ifFalse:
> + 			[self deny: targetEntry spilled].
> + 	type caseOf: {
> + 		[SSBaseOffset]	-> [cogit MoveMw: offset r: register R: targetReg].
> + 		[SSSpill]		-> [cogit MoveMw: offset r: register R: targetReg].
> + 		[SSConstant]	-> [cogit genMoveConstant: constant R: targetReg].
> + 		[SSRegister]	-> [register ~= targetReg ifTrue:
> + 								[cogit MoveR: register R: targetReg]] }!
> 
> Item was changed:
>  ----- Method: CogRegisterAllocatingSimStackEntry>>reconcilePoppingWith: (in category 'compile abstract instructions') -----
>  reconcilePoppingWith: targetEntry
>  	"Make the state of a targetEntry, a stack entry following a non-inlined special selector
>  	 send, the same as the corresponding entry (the receiver) along the inlined path."
>  	<var: #targetEntry type: #'targetEntry *'>
> + 	| targetReg |
>  	targetEntry spilled ifTrue:
>  		[self assert: (self isSameEntryAs: targetEntry).
> + 		 (targetReg := targetEntry registerOrNone) = NoReg ifTrue:
> - 		 targetEntry liveRegister = NoReg ifTrue:
>  			[^self].
>  		 type caseOf: {
> + 				[SSBaseOffset]	-> [cogit MoveMw: offset r: register R: targetReg].
> + 				[SSSpill]		-> [cogit MoveMw: offset r: register R: targetReg].
> + 				[SSConstant]	-> [cogit genMoveConstant: constant R: targetReg].
> + 				[SSRegister]	-> [targetReg ~= register ifTrue:
> + 										[cogit MoveR: register R: targetReg]] }.
> - 				[SSBaseOffset]	-> [cogit MoveMw: offset r: register R: targetEntry liveRegister].
> - 				[SSSpill]		-> [cogit MoveMw: offset r: register R: targetEntry liveRegister].
> - 				[SSConstant]	-> [cogit genMoveConstant: constant R: targetEntry liveRegister].
> - 				[SSRegister]	-> [targetEntry liveRegister ~= register ifTrue:
> - 										[cogit MoveR: register R: targetEntry liveRegister]] }.
>  		 ^self].
>  	targetEntry type = SSConstant ifTrue:
> + 		[self assert: (targetEntry registerOrNone) = NoReg.
> + 		 cogit AddCq: objectRepresentation wordSize R: SPReg.
> - 		[cogit AddCw: BytesPerWord R: SPReg.
>  		 ^self].
> + 	(targetReg := targetEntry registerOrNone) ~= NoReg ifTrue:
> + 		[cogit PopR: targetReg.
> - 	targetEntry registerOrNone ~= NoReg ifTrue:
> - 		[cogit PopR: targetEntry registerOrNone.
>  		 ^self].
>  	self halt!
> 
> Item was removed:
> - ----- Method: CogRegisterAllocatingSimStackEntry>>reconcileWith: (in category 'compile abstract instructions') -----
> - reconcileWith: targetEntry
> - 	"Make the state of the receiver, a stack entry at a backward jump,
> - 	 the same as the corresponding simStackEntry at the target of the jump"
> - 	<var: #targetEntry type: #'targetEntry *'>
> - 	targetEntry liveRegister = NoReg ifTrue:
> - 		[^self].
> - 	targetEntry type = SSConstant ifTrue:
> - 		[self assert: (type = SSConstant and: [constant = targetEntry constant]).
> - 		 ^self].
> - 	liveRegister ~= NoReg ifTrue:
> - 		[liveRegister ~= targetEntry liveRegister ifTrue:
> - 			[cogit MoveR: liveRegister R: targetEntry liveRegister].
> - 		 ^self].
> - 	type caseOf: {
> - 		[SSBaseOffset]	-> [cogit MoveMw: offset r: register R: targetEntry liveRegister].
> - 		[SSSpill]		-> [cogit MoveMw: offset r: register R: targetEntry liveRegister].
> - 		[SSConstant]	-> [cogit genMoveConstant: constant R: targetEntry liveRegister].
> - 		[SSRegister]	-> [register ~= targetEntry liveRegister ifTrue:
> - 								[cogit MoveR: register R: targetEntry liveRegister]] }!
> 
> Item was changed:
>  ----- Method: RegisterAllocatingCogit>>mergeCurrentSimStackWith: (in category 'bytecode generator support') -----
>  mergeCurrentSimStackWith: mergeSimStack
>  	<var: #mergeSimStack type: #'SimStackEntry *'>
>  	"At a merge point the cogit expects the stack to be in the same state as mergeSimStack.
>  	 mergeSimStack is the state as of some jump forward to this point.  So make simStack agree
>  	 with mergeSimStack (it is, um, problematic to plant code at the jump).
>  	 Values may have to be assigned to registers.  Registers may have to be swapped.
>  	 The state of optStatus must agree."
> + 	| currentEntry targetEntry |
> - 	| currentRegsMask mergeRegsMask potentialConflictRegMask conflictingRegsMask
> - 	   currentRegMask mergeRegMask currentEntry targetEntry |
>  	<var: #currentEntry type: #'SimStackEntry *'>
>  	<var: #targetEntry type: #'SimStackEntry *'>
>  	mergeSimStack ifNil: [^self].
> + 	"Assignments amongst the registers must be made in order to avoid overwriting.
> + 	 If necessary exchange registers amongst simStack's entries to resolve any conflicts."
> + 	self resolveRegisterOrderConflictsBetweenCurrentSimStackAnd: mergeSimStack.
> - 	currentRegsMask := mergeRegsMask := potentialConflictRegMask := 0.
> - 	0 to: simStackPtr do:
> - 		[:i|
> - 		 currentRegMask := (currentEntry := self simStack: simStack at: i) registerMaskOrNone.
> - 		 mergeRegMask := (targetEntry := self simStack: mergeSimStack at: i) registerMaskOrNone.
> - 		 currentRegMask = mergeRegMask
> - 			ifTrue:
> - 				[self assert: (currentEntry isSameEntryAs: targetEntry)]
> - 			ifFalse: "This checks for a potential conflict..."
> - 				[(currentRegMask ~= 0 or: [mergeRegMask ~= 0]) ifTrue:
> - 					[potentialConflictRegMask := potentialConflictRegMask bitOr: (currentRegMask bitOr: mergeRegMask)]].
> - 		 currentRegsMask := currentRegsMask bitOr: currentRegMask.
> - 		 mergeRegsMask := mergeRegsMask bitOr: mergeRegMask].
> - 	conflictingRegsMask := potentialConflictRegMask bitAnd: (currentRegsMask bitAnd: mergeRegsMask).
> - 	"One simple algorithm is to spill everything if there are any conflicts and then pop back.
> - 	 But this is terrible :-(  Can we do better? Yes... Consider the following two simStacks
> - 		target:		0: | rA | __ | rB | rC | rD | <- sp
> - 		current:	0: | __ | __ | rD | rA | rC | <- sp
> - 	 If we were to assign in a naive order, 0 through sp rA would be overwritten before its value in current[3] is written to rC,
> - 	 and rC would be overwritten before its value in current[4] is written to rD.  But if we swap the registers in current so that
> - 	 they respect the reverse ordering in target we can assign directly:
> - 		swap current[3] & current[4]
> - 					0: | __ | __ | rD | rC | rA | <- sp
> - 	now do the assignment in the order target[0] := current[0],  target[1] := current[1], ...  target[4] := current[4],
> - 	i.e. rA := current[0]; rB := rD; (rC := rC); (rD := rD)."
> - 	conflictingRegsMask ~= 0 ifTrue:
> - 		[(self isAPowerOfTwo: conflictingRegsMask) "Multiple conflicts mean we have to sort"
> - 			ifFalse: [self swapCurrentRegistersInMask: currentRegsMask accordingToRegisterOrderIn: mergeSimStack]
> - 			ifTrue: [self assignToTempRegConflictingRegisterIn: conflictingRegsMask]].
>  	self assert: (self conflcitsResolvedBetweenSimStackAnd: mergeSimStack).
>  	simStackPtr to: 0 by: -1 do:
>  		[:i|
> + 		 currentEntry := self simStack: simStack at: i.
> + 		 targetEntry := self simStack: mergeSimStack at: i.
> + 		 currentEntry reconcileForwardsWith: targetEntry.
> + 		 "Note, we could update the simStack and spillBase here but that is done in restoreSimStackAtMergePoint:
> + 		 spilled ifFalse:
> + 			[simSpillBase := i - 1].
> + 		 simStack
> + 			at: i
> + 			put: (self
> + 					cCode: [mergeSimStack at: i]
> + 					inSmalltalk: [(mergeSimStack at: i) copy])"]!
> - 		 currentRegMask := (currentEntry := self simStack: simStack at: i) registerMaskOrNone.
> - 		 mergeRegMask := (targetEntry := self simStack: mergeSimStack at: i) registerMaskOrNone.
> - 		 mergeRegMask ~= 0
> - 			ifTrue:
> - 				[currentRegMask ~= mergeRegMask
> - 					ifTrue:
> - 						[currentEntry reconcilePoppingWith: targetEntry.
> - 						 simStack
> - 							at: i
> - 							put: (self
> - 									cCode: [mergeSimStack at: i]
> - 									inSmalltalk: [(mergeSimStack at: i) copy])]
> - 					ifFalse:
> - 						[self assert: (currentEntry isSameEntryAs: targetEntry)]]
> - 			ifFalse:
> - 				[self assert: (currentRegMask = 0 or: [currentEntry spilled]).
> - 				 self assert: (currentEntry isSameEntryAs: targetEntry) "really? here to check"]]!
> 
> Item was changed:
>  ----- Method: RegisterAllocatingCogit>>reconcileRegisterStateForBackwardJoin: (in category 'bytecode generator support') -----
>  reconcileRegisterStateForBackwardJoin: fixup 
>  	<var: #fixup type: #'SSBytecodeFixup *'>
>  	| fixupSimStack |
>  	<var: #fixupSimStack type: #'SimStackEntry *'>
>  	self assert: (optStatus ssEntry isSameEntryAs: simSelf). 
>  	fixup isReceiverResultRegSelf ifTrue:
>  		[optStatus isReceiverResultRegLive ifFalse:
>  			[optStatus ssEntry storeToReg: ReceiverResultReg]].
>  	fixupSimStack := fixup mergeSimStack.
>  	simStackPtr to: 0 by: -1 do:
>  		[:i|
>  		 self assert: (self simStackAt: i) spilled.
> + 		 (self simStackAt: i) reconcileBackwardsWith: (fixupSimStack at: i)]!
> - 		 (self simStackAt: i) reconcileWith: (fixupSimStack at: i)]!
> 
> Item was added:
> + ----- Method: RegisterAllocatingCogit>>resolveRegisterOrderConflictsBetweenCurrentSimStackAnd: (in category 'bytecode generator support') -----
> + resolveRegisterOrderConflictsBetweenCurrentSimStackAnd: mergeSimStack
> + 	<var: #mergeSimStack type: #'SimStackEntry *'>
> + 	"One simple algorithm is to spill everything if there are any conflicts and then pop back.
> + 	 But this is terrible :-(  Can we do better? Yes... Consider the following two simStacks
> + 		target:		0: | rA | __ | rB | rC | rD | <- sp
> + 		current:	0: | __ | __ | rD | rA | rC | <- sp
> + 	 If we were to assign in a naive order, 0 through sp rA would be overwritten before its value in current[3] is written to rC,
> + 	 and rC would be overwritten before its value in current[4] is written to rD.  But if we swap the registers in current so that
> + 	 they respect the reverse ordering in target we can assign directly:
> + 		swap current[3] & current[4]
> + 					0: | __ | __ | rD | rC | rA | <- sp
> + 	 now do the assignment in the order target[0] := current[0],  target[1] := current[1], ...  target[4] := current[4],
> + 	 i.e. rA := current[0]; rB := rD; (rC := rC); (rD := rD).
> + 
> + 	 So find any conflicts, and if there are any, swap registers in the simStack to resolve them.
> + 	 The trivial case of a single conflict is resolved by assigning that conflict to TempReg.
> + 	"
> + 	| currentRegsMask mergeRegsMask potentialConflictRegMask conflictingRegsMask
> + 	   currentRegMask mergeRegMask currentEntry targetEntry |
> + 	<var: #currentEntry type: #'SimStackEntry *'>
> + 	<var: #targetEntry type: #'SimStackEntry *'>
> + 	currentRegsMask := mergeRegsMask := potentialConflictRegMask := 0.
> + 	0 to: simStackPtr do:
> + 		[:i|
> + 		 currentRegMask := (currentEntry := self simStack: simStack at: i) registerMaskOrNone.
> + 		 mergeRegMask := (targetEntry := self simStack: mergeSimStack at: i) registerMaskOrNone.
> + 		 (currentRegMask ~= mergeRegMask
> + 		  and: [currentRegMask ~= 0 or: [mergeRegMask ~= 0]]) ifTrue:
> + 			[potentialConflictRegMask := potentialConflictRegMask bitOr: (currentRegMask bitOr: mergeRegMask)].
> + 		 currentRegsMask := currentRegsMask bitOr: currentRegMask.
> + 		 mergeRegsMask := mergeRegsMask bitOr: mergeRegMask].
> + 	conflictingRegsMask := potentialConflictRegMask bitAnd: (currentRegsMask bitAnd: mergeRegsMask).
> + 	conflictingRegsMask ~= 0 ifTrue:
> + 		[(self isAPowerOfTwo: conflictingRegsMask) "Multiple conflicts mean we have to sort"
> + 			ifFalse: [self swapCurrentRegistersInMask: currentRegsMask accordingToRegisterOrderIn: mergeSimStack]
> + 			ifTrue: [self assignToTempRegConflictingRegisterIn: conflictingRegsMask]].!
> 
> Item was changed:
>  ----- Method: RegisterAllocatingCogit>>restoreSimStackAtMergePoint: (in category 'simulation stack') -----
>  restoreSimStackAtMergePoint: fixup
>  	<inline: true>
>  	"All the execution paths reaching a merge point expect everything to be spilled
>  	 on stack and the optStatus is unknown.  If the merge point follows a return, it
> + 	 isn't a merge, but a skip past a return.  If it is a real merge point then throw
> - 	 isn't a merge, but a sdkip past a return.  If it is a real merge point then throw
>  	 away all simStack and optStatus optimization state."
> + 	optStatus isReceiverResultRegLive: fixup isReceiverResultRegSelf.
>  	fixup mergeSimStack ifNotNil:
>  		[simSpillBase := methodOrBlockNumTemps.
> - 		 self flag: 'try and maintain this through the merge'.
> - 		 optStatus isReceiverResultRegLive: false.
>  		 0 to: simStackPtr do:
>  			[:i|
>  			self cCode: [simStack at: i put: (fixup mergeSimStack at: i)]
>  				inSmalltalk: [(simStack at: i) copyFrom: (fixup mergeSimStack at: i)]]].
>  	^0!
> 



More information about the Vm-dev mailing list