[Vm-dev] VM Maker: VMMaker.oscog-cb.1813.mcz

commits at source.squeak.org commits at source.squeak.org
Sun Apr 17 23:22:25 UTC 2016


ClementBera uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-cb.1813.mcz

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

Name: VMMaker.oscog-cb.1813
Author: cb
Time: 17 April 2016, 4:20:47.744692 pm
UUID: 6ad4e1ff-610a-48a9-a89e-3bc27bab1e21
Ancestors: VMMaker.oscog-cb.1812

Improvement on RegisterAllocatingCogit. Still not fully functional.

=============== Diff against VMMaker.oscog-cb.1812 ===============

Item was changed:
  CogSSBytecodeFixup subclass: #CogRASSBytecodeFixup
+ 	instanceVariableNames: 'mergeSimStack'
- 	instanceVariableNames: 'mergeFixup'
  	classVariableNames: ''
  	poolDictionaries: ''
  	category: 'VMMaker-JIT'!

Item was changed:
  ----- Method: CogRASSBytecodeFixup class>>instVarNamesAndTypesForTranslationDo: (in category 'translation') -----
  instVarNamesAndTypesForTranslationDo: aBinaryBlock
  	"enumerate aBinaryBlock with the names and C type strings for the inst vars to include in a CogRASSBytecodeFixup struct."
  
  	self allInstVarNames do:
  		[:ivn|
  		aBinaryBlock
  			value: ivn
  			value: (ivn caseOf: {
  					['targetInstruction']	-> [#'AbstractInstruction *'].
+ 					['mergeSimStack']	-> [#'CogSimStackEntry *'] }
- 					['mergeFixup']		-> [#'CogSimStackEntry *'] }
  					otherwise: [#sqInt])]!

Item was removed:
- ----- Method: CogRASSBytecodeFixup>>mergeFixup (in category 'accessing') -----
- mergeFixup
- 
- 	^ mergeFixup!

Item was removed:
- ----- Method: CogRASSBytecodeFixup>>mergeFixup: (in category 'accessing') -----
- mergeFixup: anObject
- 
- 	^mergeFixup := anObject!

Item was added:
+ ----- Method: CogRASSBytecodeFixup>>mergeSimStack (in category 'accessing') -----
+ mergeSimStack
+ 
+ 	^ mergeSimStack!

Item was added:
+ ----- Method: CogRASSBytecodeFixup>>mergeSimStack: (in category 'accessing') -----
+ mergeSimStack: anObject
+ 
+ 	^mergeSimStack := anObject!

Item was added:
+ CogSimStackEntry subclass: #CogRegisterAllocatingSimStackEntry
+ 	instanceVariableNames: 'liveRegister'
+ 	classVariableNames: ''
+ 	poolDictionaries: ''
+ 	category: 'VMMaker-JIT'!

Item was added:
+ ----- Method: CogRegisterAllocatingSimStackEntry>>ensureSpilledAt:from: (in category 'compile abstract instructions') -----
+ ensureSpilledAt: baseOffset from: baseRegister
+ 	| inst |
+ 	<var: #inst type: #'AbstractInstruction *'>
+ 	spilled ifTrue:
+ 		[type = SSSpill ifTrue:
+ 			[self assert: (offset = baseOffset and: [register = baseRegister]).
+ 			 ^self]].
+ 	self assert: type ~= SSSpill.
+ 	cogit traceSpill: self.
+ 	type = SSConstant
+ 		ifTrue:
+ 			[inst := cogit genPushConstant: constant]
+ 		ifFalse:
+ 			[type = SSBaseOffset
+ 				ifTrue:
+ 					[ liveRegister = NoReg
+ 						ifTrue: 
+ 							[cogit MoveMw: offset r: register R: TempReg.
+ 					 		 inst := cogit PushR: TempReg ]
+ 						ifFalse: [ inst := cogit PushR: liveRegister]]
+ 				ifFalse:
+ 					[self assert: type = SSRegister.
+ 					 inst := cogit PushR: register].
+ 			 type := SSSpill.
+ 			 offset := baseOffset.
+ 			 register := baseRegister].
+ 	spilled := true.
+ 	self maybeAnnotateUse: inst!

Item was added:
+ ----- Method: CogRegisterAllocatingSimStackEntry>>liveRegister (in category 'accessing') -----
+ liveRegister
+ 
+ 	^ liveRegister!

Item was added:
+ ----- Method: CogRegisterAllocatingSimStackEntry>>liveRegister: (in category 'accessing') -----
+ liveRegister: anObject
+ 
+ 	^liveRegister := anObject!

Item was added:
+ ----- Method: CogRegisterAllocatingSimStackEntry>>popToReg: (in category 'compile abstract instructions') -----
+ popToReg: reg
+ 	| inst |
+ 	<var: #inst type: #'AbstractInstruction *'>
+ 	liveRegister ~= NoReg
+ 		ifTrue: 
+ 			[inst := reg ~= liveRegister
+ 				ifTrue: [cogit MoveR: liveRegister R: reg]
+ 				ifFalse: [cogit Label] ]
+ 		ifFalse: 
+ 			[spilled
+ 				ifTrue:
+ 					[inst := cogit PopR: reg]
+ 				ifFalse:
+ 					[type caseOf: {
+ 						[SSBaseOffset]	-> [inst := cogit MoveMw: offset r: register R: reg].
+ 						[SSConstant]	-> [inst := cogit genMoveConstant: constant R: reg].
+ 						[SSRegister]	-> [inst := reg ~= register
+ 														ifTrue: [cogit MoveR: register R: reg]
+ 														ifFalse: [cogit Label]] }]].
+ 	self maybeAnnotateUse: inst.
+ 	reg ~= TempReg ifTrue: [ liveRegister := reg ]!

Item was added:
+ ----- Method: CogRegisterAllocatingSimStackEntry>>printStateOn: (in category 'printing') -----
+ printStateOn: aStream
+ 	<doNotGenerate> "Smalltalk-side only"
+ 	type isInteger ifFalse: [^self].
+ 	aStream nextPut: $(.
+ 	type caseOf: {
+ 		[SSBaseOffset]	-> [aStream
+ 								nextPutAll: 'bo ';
+ 								nextPutAll: (cogit backEnd nameForRegister: register).
+ 							offset negative ifFalse: [aStream nextPut: $+].
+ 							aStream print: offset].
+ 		[SSConstant]	-> [aStream
+ 								nextPutAll: 'const ';
+ 								print: constant].
+ 		[SSRegister]	-> [aStream
+ 								nextPutAll: 'reg ';
+ 								nextPutAll: (cogit backEnd nameForRegister: register)].
+ 		[SSSpill]		-> [aStream
+ 								nextPutAll: 'spill @ ';
+ 								nextPutAll: (cogit backEnd nameForRegister: register).
+ 							offset negative ifFalse: [aStream nextPut: $+].
+ 							aStream print: offset] }.
+ 	(spilled and: [type ~= SSSpill]) ifTrue:
+ 		[aStream nextPutAll: ' (spilled)'].
+ 	liveRegister ~= NoReg ifTrue:
+ 		[aStream nextPutAll: ' (live: '; nextPutAll: (cogit backEnd nameForRegister: liveRegister); nextPut: $)].
+ 	annotateUse ifTrue:
+ 		[aStream nextPutAll: ' (ANNOTATED)'].
+ 	bcptr ifNotNil:
+ 		[aStream space; nextPut: ${; print: bcptr; nextPut: $}].
+ 	aStream nextPut: $)!

Item was added:
+ ----- Method: CogRegisterAllocatingSimStackEntry>>storeToReg: (in category 'compile abstract instructions') -----
+ storeToReg: reg
+ 	| inst |
+ 	<var: #inst type: #'AbstractInstruction *'>
+ 	liveRegister ~= NoReg
+ 		ifTrue:
+ 			[inst := reg ~= liveRegister
+ 							ifTrue: [cogit MoveR: liveRegister R: reg]
+ 							ifFalse: [cogit Label]]
+ 		ifFalse:
+ 			[type caseOf: {
+ 				[SSBaseOffset]	-> [inst := cogit MoveMw: offset r: register R: reg].
+ 				[SSSpill]		-> [inst := cogit MoveMw: offset r: register R: reg].
+ 				[SSConstant]	-> [inst := cogit genMoveConstant: constant R: reg].
+ 				[SSRegister]	-> [inst := reg ~= register
+ 												ifTrue: [cogit MoveR: register R: reg]
+ 												ifFalse: [cogit Label]] }].
+ 	self maybeAnnotateUse: inst.
+ 	reg ~= TempReg ifTrue: [ liveRegister := reg ]!

Item was changed:
  StackToRegisterMappingCogit subclass: #RegisterAllocatingCogit
+ 	instanceVariableNames: 'numFixups mergeSimStacksBase nextFixup'
- 	instanceVariableNames: 'numFixups mergeSimStacksBase'
  	classVariableNames: ''
  	poolDictionaries: ''
  	category: 'VMMaker-JIT'!
  
  !RegisterAllocatingCogit commentStamp: 'cb 4/15/2016 14:58' prior: 0!
  RegisterAllocatingCogit is an optimizing code generator that is specialized in register allocation..
  
  On the contrary to StackToRegisterMappingCogit, RegisterAllocatingCogit keeps at each control flow merge point the state of the simulated stack to merge into and not only an integer fixup. Each branch and jump record the current state of the simulated stack, and each fixup is responsible for merging this state into the saved simulated stack.
  !

Item was changed:
  ----- Method: RegisterAllocatingCogit>>allocateMergeFixups (in category 'compile abstract instructions') -----
  allocateMergeFixups
  	"Allocate the various arrays needed to allocate the merge fixups, failing if the size
  	 needed is considered too high.
  
  	 This *must* be inlined since the arrays are alloca'ed (stack allocated)
  	 so that they are freed when compilation is done.
  
  	 N.B. We do one single alloca to save embarrassing C optimizers that
  	 generate incorrect code as both gcc and the intel compiler do on x86."
  	<inline: true>
  	| mergeSimStackBytes |
+ 	mergeSimStackBytes := numFixups * self simStackSlots * (self sizeof: CogSimStackEntry).
+ 	nextFixup := 0.
- 	mergeSimStackBytes := numFixups * self  simStackSlots.
  	self cCode:
  		[mergeSimStacksBase := self alloca: mergeSimStackBytes.
  		 self b: mergeSimStacksBase zero: mergeSimStackBytes]!

Item was added:
+ ----- Method: RegisterAllocatingCogit>>copySimStack (in category 'simulation only') -----
+ copySimStack
+ 	<doNotGenerate>
+ 	^CArrayAccessor on: (simStack object collect: [:stackEntry| stackEntry copy])!

Item was added:
+ ----- Method: RegisterAllocatingCogit>>ensureFixupAt: (in category 'bytecode generator support') -----
+ ensureFixupAt: targetIndex
+ 	| fixup |	
+ 	<var: #fixup type: #'BytecodeFixup *'>
+ 	fixup := self fixupAt: targetIndex.
+ 	fixup needsFixup 
+ 		ifTrue: [self mergeCurrentSimStackWith: fixup mergeSimStack ]
+ 		ifFalse: 
+ 			[self assert: fixup mergeSimStack isNil.
+ 			self moveSimStackConstantsToRegisters.
+ 			self setMergeSimStackOf: fixup ].
+ 	^super ensureFixupAt: targetIndex.
+ !

Item was added:
+ ----- Method: RegisterAllocatingCogit>>flushLiveRegistersForCRunTimeCall (in category 'bytecode generator support') -----
+ flushLiveRegistersForCRunTimeCall
+ 	<inline: true>
+ 	0 to: simStackPtr do:
+ 		[:i| | reg |
+ 		 self assert: (self simStackAt: i) type = (i <= methodOrBlockNumTemps
+ 													ifTrue: [SSBaseOffset]
+ 													ifFalse: [SSSpill]).
+ 		 reg := (self simStackAt: i) liveRegister.
+ 		 (reg ~= NoReg and: [(self isCallerSavedReg: reg)]) ifTrue:
+ 			[(self simStackAt: i) liveRegister: NoReg]]!

Item was added:
+ ----- Method: RegisterAllocatingCogit>>flushLiveRegistersForSend (in category 'bytecode generator support') -----
+ flushLiveRegistersForSend
+ 	<inline: true>
+ 	0 to: simStackPtr do:
+ 		[:i|
+ 		 self assert: (self simStackAt: i) type = (i <= methodOrBlockNumTemps
+ 													ifTrue: [SSBaseOffset]
+ 													ifFalse: [SSSpill]).
+ 		 (self simStackAt: i) liveRegister: NoReg]!

Item was added:
+ ----- Method: RegisterAllocatingCogit>>genJumpIf:to: (in category 'bytecode generator support') -----
+ genJumpIf: boolean to: targetBytecodePC
+ 	<inline: false>
+ 	| desc fixup ok |
+ 	<var: #desc type: #'CogSimStackEntry *'>
+ 	<var: #fixup type: #'BytecodeFixup *'>
+ 	<var: #ok type: #'AbstractInstruction *'>
+ 	1halt.
+ 	self ssFlushTo: simStackPtr - 1.
+ 	desc := self ssTop.
+ 	self ssPop: 1.
+ 	(desc type == SSConstant
+ 	 and: [desc constant = objectMemory trueObject or: [desc constant = objectMemory falseObject]]) ifTrue:
+ 		["Must arrange there's a fixup at the target whether it is jumped to or
+ 		  not so that the simStackPtr can be kept correct."
+ 		 fixup := self ensureFixupAt: targetBytecodePC - initialPC.
+ 		 "Must enter any annotatedConstants into the map"
+ 		 desc annotateUse ifTrue:
+ 			[self annotateBytecode: (self prevInstIsPCAnnotated
+ 											ifTrue: [self Nop]
+ 											ifFalse: [self Label])].
+ 		 "Must annotate the bytecode for correct pc mapping."
+ 		 self annotateBytecode: (desc constant = boolean
+ 									ifTrue: [self Jump: fixup]
+ 									ifFalse: [self prevInstIsPCAnnotated
+ 												ifTrue: [self Nop]
+ 												ifFalse: [self Label]]).
+ 		 ^0].
+ 	desc popToReg: TempReg.
+ 	"Cunning trick by LPD.  If true and false are contiguous subtract the smaller.
+ 	 Correct result is either 0 or the distance between them.  If result is not 0 or
+ 	 their distance send mustBeBoolean."
+ 	self assert: (objectMemory objectAfter: objectMemory falseObject) = objectMemory trueObject.
+ 	self genSubConstant: boolean R: TempReg.
+ 	self JumpZero: (self ensureFixupAt: targetBytecodePC - initialPC).
+ 
+ 	self extASpecifiesNoMustBeBoolean ifTrue: 
+ 		[ extA := 0. 
+ 		self annotateBytecode: self lastOpcode.
+ 		^ 0].
+ 	extA := 0.
+ 	
+ .	self CmpCq: (boolean == objectMemory falseObject
+ 					ifTrue: [objectMemory trueObject - objectMemory falseObject]
+ 					ifFalse: [objectMemory falseObject - objectMemory trueObject])
+ 		R: TempReg.
+ 	ok := self JumpZero: 0.
+ 	self CallRT: (boolean == objectMemory falseObject
+ 					ifTrue: [ceSendMustBeBooleanAddFalseTrampoline]
+ 					ifFalse: [ceSendMustBeBooleanAddTrueTrampoline]).
+ 	ok jmpTarget: (self annotateBytecode: self Label).
+ 	^0!

Item was changed:
  ----- Method: RegisterAllocatingCogit>>genJumpTo: (in category 'bytecode generator support') -----
  genJumpTo: targetBytecodePC
- 	self assert: simStackPtr <= (simSpillBase + 1). "Only 1 spilledValue max".
- 	"Self ssFlushTo: simStackPtr"
  	self Jump: (self ensureFixupAt: targetBytecodePC - initialPC).
  	^ 0!

Item was added:
+ ----- Method: RegisterAllocatingCogit>>genMarshalledSend:numArgs:sendTable: (in category 'bytecode generator support') -----
+ genMarshalledSend: selectorIndex numArgs: numArgs sendTable: sendTable
+ 	self flushLiveRegistersForSend.
+ 	^super genMarshalledSend: selectorIndex numArgs: numArgs sendTable: sendTable!

Item was added:
+ ----- Method: RegisterAllocatingCogit>>genStorePop:TemporaryVariable: (in category 'bytecode generator support') -----
+ genStorePop: popBoolean TemporaryVariable: tempIndex
+ 	"Override so that if a register other than TempReg is allocated, the temp is marked as being live in that register."
+ 	| reg |
+ 	self ssFlushUpThroughTemporaryVariable: tempIndex.
+ 	reg := self ssStorePop: popBoolean toPreferredReg: TempReg.
+ 	self MoveR: reg
+ 		Mw: (self frameOffsetOfTemporary: tempIndex)
+ 		r: FPReg.
+ 	reg ~= TempReg ifTrue:
+ 		[(self simStackAt: tempIndex) liveRegister: reg].
+ 	^0!

Item was added:
+ ----- Method: RegisterAllocatingCogit>>initSimStackForFramefulMethod: (in category 'simulation stack') -----
+ initSimStackForFramefulMethod: startpc
+ 	super initSimStackForFramefulMethod: startpc.
+ 	simSelf liveRegister: NoReg.
+ 	0 to: simStackPtr do:
+ 		[:i| (self simStackAt: i) liveRegister: NoReg]!

Item was added:
+ ----- Method: RegisterAllocatingCogit>>initSimStackForFramelessBlock: (in category 'simulation stack') -----
+ initSimStackForFramelessBlock: startpc
+ 	super initSimStackForFramelessBlock: startpc.
+ 	simSelf liveRegister: simSelf register.
+ 	0 to: simStackPtr do:
+ 		[:i| (self simStackAt: i) liveRegister: NoReg]!

Item was added:
+ ----- Method: RegisterAllocatingCogit>>initSimStackForFramelessMethod: (in category 'simulation stack') -----
+ initSimStackForFramelessMethod: startpc
+ 	super initSimStackForFramelessMethod: startpc.
+ 	simSelf liveRegister: NoReg.
+ 	0 to: simStackPtr do:
+ 		[:i| | desc |
+ 		desc := self simStackAt: 1.
+ 		desc liveRegister: (desc type = SSRegister ifTrue: [desc register] ifFalse: [NoReg])]!

Item was added:
+ ----- Method: RegisterAllocatingCogit>>mergeCurrentSimStackWith: (in category 'bytecode generator support') -----
+ mergeCurrentSimStackWith: mergeSimStack
+ 	<var: #mergeSimStack type: #'SimStackEntry *'>
+ 	<var: #currentSSEntry type: #'SimStackEntry *'>
+ 	<var: #expectedSSEntry type: #'SimStackEntry *'>
+ 	"At merge point the cogit expects the stack to be in the same state as mergeSimStack.
+ 	The logic is very naive, we align the existing state from the current stack to the merge stack
+ 	from simStackPtr to methodOrBlockNumTemps, and if a conflict happen, we flush what remains
+ 	to be merged."
+ 	self flag: #TODO. "we could have a better algorithm with the current set of live registers to avoid flushing"
+ 	simStackPtr to: methodOrBlockNumTemps by: -1 do:
+ 		[:i|
+ 			| currentSSEntry expectedSSEntry |
+ 			currentSSEntry := self simStackAt: i.
+ 			expectedSSEntry := self simStack: mergeSimStack at: i.
+ 			expectedSSEntry
+ 				caseOf: {
+ 					[SSBaseOffset]	-> [ self assert: (expectedSSEntry register = ReceiverResultReg or: [ expectedSSEntry register = FPReg ]).
+ 										(expectedSSEntry register = ReceiverResultReg and: [needsFrame]) ifTrue: 
+ 											[optStatus isReceiverResultRegLive ifFalse: 
+ 												[self ssFlushFrom: i - 1 upThroughRegister: ReceiverResultReg.
+ 											 	 self putSelfInReceiverResultReg ].
+ 											 optStatus isReceiverResultRegLive: true].  ].
+ 					[SSSpill]		-> [currentSSEntry ensureSpilledAt: (self frameOffsetOfTemporary: i) from: FPReg].
+ 					[SSConstant]	-> [self assert: expectedSSEntry liveRegister notNil. 
+ 										currentSSEntry storeToReg: expectedSSEntry liveRegister ].
+ 					[SSRegister]	-> [(currentSSEntry type = SSRegister and: [currentSSEntry register = expectedSSEntry register])
+ 											ifFalse: 
+ 												[ self ssFlushFrom: i - 1 upThroughRegister: expectedSSEntry register.
+ 												currentSSEntry storeToReg: expectedSSEntry register ] ]}.
+ 			 ]!

Item was added:
+ ----- Method: RegisterAllocatingCogit>>moveSimStackConstantsToRegisters (in category 'bytecode generator support') -----
+ moveSimStackConstantsToRegisters
+ 	<inline: true>
+ 	(simSpillBase max: 0) to: simStackPtr do: 
+ 		[:i|
+ 			| desc |
+ 			desc := self simStackAt: i.
+ 			(desc type = SSConstant and: [desc liveRegister = NoReg])
+ 				ifTrue: [ desc storeToReg: (self allocateRegNotConflictingWith: 0) ] ]!

Item was added:
+ ----- Method: RegisterAllocatingCogit>>setMergeSimStackOf: (in category 'bytecode generator support') -----
+ setMergeSimStackOf: fixup
+ 	<var: #fixup type: #'BytecodeFixup *'>
+ 	self assert: nextFixup < numFixups.
+ 	self moveSimStackConstantsToRegisters.
+ 	self cCode: [fixup mergeSimStack: mergeSimStacksBase + (nextFixup * self simStackSlots * (self sizeof: CogSimStackEntry))].
+ 	nextFixup := nextFixup + 1.
+ 	self cCode: [self mem: fixup mergeSimStack cp: self simStackSlots * (self sizeof: CogSimStackEntry) y: simStack]
+ 		inSmalltalk: [fixup mergeSimStack: self copySimStack]!

Item was added:
+ ----- Method: RegisterAllocatingCogit>>simStack:at: (in category 'simulation stack') -----
+ simStack: stack at: index
+ 	<cmacro: '(index) (stack + (index))'>
+ 	<returnTypeC: #'CogSimStackEntry *'>
+ 	^self addressOf: (stack at: index)!

Item was added:
+ ----- Method: RegisterAllocatingCogit>>simStackEntryClass (in category 'initialization') -----
+ simStackEntryClass
+ 	<doNotGenerate>
+ 	^CogRegisterAllocatingSimStackEntry!

Item was added:
+ ----- Method: RegisterAllocatingCogit>>ssFlushFrom:upThrough: (in category 'simulation stack') -----
+ ssFlushFrom: start upThrough: unaryBlock
+ 	"Any occurrences on the stack of the value being stored (which is the top of stack)
+ 	 must be flushed, and hence any values colder than them stack."
+ 	<inline: true>
+ 	start to: (simSpillBase max: 0) by: -1 do:
+ 		[ :index |
+ 		(unaryBlock value: (self simStackAt: index)) ifTrue: [ ^ self ssFlushTo: index ] ]!

Item was added:
+ ----- Method: RegisterAllocatingCogit>>ssFlushFrom:upThroughRegister: (in category 'simulation stack') -----
+ ssFlushFrom: start upThroughRegister: reg
+ 	"Any occurrences on the stack of the register must be
+ 	 flushed, and hence any values colder than them stack."
+ 	<var: #desc type: #'CogSimStackEntry *'>
+ 	self ssFlushFrom: start upThrough: [ :desc | desc type = SSRegister and: [ desc register = reg ] ]!

Item was added:
+ ----- Method: RegisterAllocatingCogit>>ssStorePop:toPreferredReg: (in category 'simulation stack') -----
+ ssStorePop: popBoolean toPreferredReg: preferredReg
+ 	"Store or pop the top simulated stack entry to a register.
+ 	 Use preferredReg if the entry is not itself a register.
+ 	 Answer the actual register the result ends up in."
+ 	| actualReg |
+ 	actualReg := preferredReg.
+ 	self ssTop type = SSRegister ifTrue: 
+ 		[self assert: self ssTop liveRegister = self ssTop register.
+ 		self assert: self ssTop annotateUse not.
+ 		self assert: self ssTop spilled not].
+ 	self ssTop liveRegister ~= NoReg ifTrue:
+ 		[actualReg := self ssTop liveRegister].
+ 	self ssStorePop: popBoolean toReg: actualReg. "generates nothing if ssTop is already in actualReg"
+ 	^ actualReg!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>mergeWithFixupIfRequired: (in category 'simulation stack') -----
  mergeWithFixupIfRequired: fixup
  	"If this bytecode has a fixup, some kind of merge needs to be done. There are 4 cases:
  		1) the bytecode has no fixup (fixup isNotAFixup)
  			do nothing
  		2) the bytecode has a non merge fixup
  			the fixup has needsNonMergeFixup.
  			The code generating non merge fixup (currently only special selector code) is responsible
  				for the merge so no need to do it.
  			We set deadCode to false as the instruction can be reached from jumps.
  		3) the bytecode has a merge fixup, but execution flow *cannot* fall through to the merge point.
  			the fixup has needsMergeFixup and deadCode = true.
  			ignores the current simStack as it does not mean anything 
  			restores the simStack to the state the jumps to the merge point expects it to be.
  		4) the bytecode has a merge fixup and execution flow *can* fall through to the merge point.
  			the fixup has needsMergeFixup and deadCode = false.
  			flushes the stack to the stack pointer so the fall through execution path simStack is 
  				in the state the merge point expects it to be. 
  			restores the simStack to the state the jumps to the merge point expects it to be.
  			
  	In addition, if this is a backjump merge point, we patch the fixup to hold the current simStackPtr 
  	for later assertions."
  	
  	<var: #fixup type: #'BytecodeFixup *'>
  	"case 1"
  	fixup notAFixup ifTrue: [^ 0].
  
  	"case 2"
  	fixup isNonMergeFixup ifTrue: [deadCode := false. ^ 0 ].
  
  	"cases 3 and 4"
  	self assert: fixup isMergeFixup.
  	self traceMerge: fixup.
  	deadCode 
  		ifTrue: [simStackPtr := fixup simStackPtr] "case 3"
  		ifFalse: [self ssFlushTo: simStackPtr]. "case 4"
+ 	"cases 3 and 4"
  	deadCode := false.
  	fixup isBackwardBranchFixup ifTrue: [fixup simStackPtr: simStackPtr].
  	fixup targetInstruction: self Label.
  	self assert: simStackPtr = fixup simStackPtr.
  	self cCode: '' inSmalltalk:
  		[self assert: fixup simStackPtr = (self debugStackPointerFor: bytecodePC)].
  	self restoreSimStackAtMergePoint: fixup.
  	
  	^0!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>restoreSimStackAtMergePoint: (in category 'simulation stack') -----
  restoreSimStackAtMergePoint: fixup
  	<inline: true>
+ 	"All the execution paths reaching a merge point expect everything to be
- 	"All the execution paths reaching a merge point expected everything to be
  	spilled on stack and the optStatus is unknown. Throw away all simStack and 
  	optStatus optimization state."
  	simSpillBase := methodOrBlockNumTemps.
  	optStatus isReceiverResultRegLive: false.
  	methodOrBlockNumTemps to: simStackPtr do:
  		[:i|
  			(self simStackAt: i)
  				type: SSSpill;
  				offset: FoxMFReceiver - (i - methodOrBlockNumArgs + 1 * objectMemory bytesPerOop);
  				register: FPReg;
  				spilled: true].
  	^ 0!



More information about the Vm-dev mailing list