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

commits at source.squeak.org commits at source.squeak.org
Sat Apr 18 00:09:54 UTC 2015


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

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

Name: VMMaker.oscog-eem.1210
Author: eem
Time: 17 April 2015, 5:08:05.523 pm
UUID: c2e233d4-648a-4ffa-95d6-f002c1ae4574
Ancestors: VMMaker.oscog-eem.1207, VMMaker.oscog-cb.1209

Fix register allocation in frameless #== with
forwarders.  Now spur images start up with the new
#== code that only checks for forwarders on false..

Have genEnsureOopInRegNotForwarded:scratchReg:ifForwarder:ifNotForwarder:
answer 0, in accordance with tradition.

Fix some facade issues.

Allow turning on compilationTrace throguh init opts.

Fix slip in generateAllConfigurationsUnderVersionControl

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

Item was added:
+ ----- Method: CoInterpreter>>ceSistaTrap (in category 'trampolines') -----
+ ceSistaTrap
+ 	<api>
+ 	<option: #SistaVM>
+ 	| context obj |
+ 	instructionPointer := self popStack.
+ 	context := self ensureFrameIsMarried: framePointer SP: stackPointer.
+ 	"If there is a trap, the object is supposed to remain on
+ 	 the stack, but the cogit always removes it.  So restore it here."
+ 	obj := self stackTop.
+ 	self push: context.
+ 	self push: obj.
+ 	self push: instructionPointer.
+ 	^self
+ 		ceSendAbort: (objectMemory splObj: SelectorSistaTrap)
+ 		to: context
+ 		numArgs: 1!

Item was removed:
- ----- Method: CoInterpreter>>ceSistaTrap: (in category 'trampolines') -----
- ceSistaTrap: anObject
- 	<api>
- 	<option: #SistaVM>
- 	| context |
- 	instructionPointer := self popStack.
- 	context := self ensureFrameIsMarried: framePointer SP: stackPointer.
- 	"If there is a trap, the object is supposed to remain on
- 	 the stack, but the cogit always removes it.  So restore it here."
- 	self push: anObject.
- 	self push: context.
- 	self push: anObject.
- 	self push: instructionPointer.
- 	^self
- 		ceSendAbort: (objectMemory splObj: SelectorSistaTrap)
- 		to: anObject
- 		numArgs: 1!

Item was changed:
  CogClass subclass: #CogObjectRepresentation
  	instanceVariableNames: 'cogit methodZone objectMemory coInterpreter ceStoreCheckTrampoline'
  	classVariableNames: ''
+ 	poolDictionaries: 'CogCompilationConstants CogMethodConstants CogRTLOpcodes VMBasicConstants VMObjectIndices VMSqueakClassIndices VMStackFrameOffsets'
- 	poolDictionaries: 'CogMethodConstants CogRTLOpcodes VMBasicConstants VMObjectIndices VMSqueakClassIndices VMStackFrameOffsets'
  	category: 'VMMaker-JIT'!
  
  !CogObjectRepresentation commentStamp: '<historical>' prior: 0!
  I am an abstract superclass for object representations whose job it is to generate abstract instructions for accessing objects.  It is hoped that this level of indirection between the Cogit code generator and object access makes it easier to adapt the code generator to different garbage collectors, object representations and languages.!

Item was added:
+ ----- Method: CogObjectRepresentation>>isUnannotatableConstant: (in category 'compile abstract instructions') -----
+ isUnannotatableConstant: simStackEntry
+ 	<inline: true>
+ 	^ simStackEntry type = SSConstant 
+ 		and: [(self shouldAnnotateObjectReference: simStackEntry constant) not ]!

Item was changed:
  ----- Method: CogObjectRepresentationFor32BitSpur>>genFetchIndexRegister:from:into: (in category 'compile abstract instructions') -----
  genFetchIndexRegister: indexReg from: tableObj into: destReg
  	"indexReg contains the 1-relative index of an element in tableObj.
  	 Since BaseHeaderSize > BytesPerOop we must adjust it to use
  	 it as a zero-relative index from the beginning of the object."
  	self assert: indexReg ~= destReg.
  	cogit AddCq: objectMemory baseHeaderSize / objectMemory wordSize - 1 R: indexReg.
+ 	cogit genMoveConstant: tableObj R: destReg.
- 	cogit annotate: (cogit MoveCw: tableObj R: destReg) objRef: tableObj.
  	cogit MoveXwr: indexReg R: destReg R: destReg.
  	^0!

Item was changed:
  ----- Method: CogObjectRepresentationFor64BitSpur>>genFetchIndexRegister:from:into: (in category 'compile abstract instructions') -----
  genFetchIndexRegister: indexReg from: tableObj into: destReg
  	"indexReg contains the 1-relative index of an element in tableObj.
  	 Since BaseHeaderSize = BytesPerOop we can use it as a
  	 zero-relative index from the beginning of the object."
  	self assert: indexReg ~= destReg.
+ 	cogit genMoveConstant: tableObj R: destReg.
- 	cogit annotate: (cogit MoveCw: tableObj R: destReg) objRef: tableObj.
  	cogit MoveXwr: indexReg R: destReg R: destReg.
  	^0!

Item was changed:
  CogObjectRepresentation subclass: #CogObjectRepresentationForSpur
  	instanceVariableNames: 'ceScheduleScavengeTrampoline ceSmallActiveContextInMethodTrampoline ceSmallActiveContextInBlockTrampoline ceLargeActiveContextInMethodTrampoline ceLargeActiveContextInBlockTrampoline'
  	classVariableNames: ''
+ 	poolDictionaries: 'VMBytecodeConstants VMSqueakClassIndices'
- 	poolDictionaries: 'CogCompilationConstants VMBytecodeConstants VMSqueakClassIndices'
  	category: 'VMMaker-JIT'!

Item was changed:
  ----- Method: CogObjectRepresentationForSpur>>genEnsureOopInRegNotForwarded:scratchReg: (in category 'compile abstract instructions') -----
  genEnsureOopInRegNotForwarded: reg scratchReg: scratch
+ 	^ self 
+ 		genEnsureOopInRegNotForwarded: reg 
+ 		scratchReg: scratch 
+ 		jumpBackTo: cogit Label "label is just before the forwarder check"!
- 	"Make sure that the oop in reg is not forwarded.  This routine assumes the object will
- 	 never be forwarded to an immediate, as it is used to unforward  literal variables (associations). 
- 	 Use the fact that isForwardedObjectClassIndexPun is a power of two to save an instruction."
- 	| skip loop ok |
- 	<var: #ok type: #'AbstractInstruction *'>
- 	<var: #skip type: #'AbstractInstruction *'>
- 	<var: #loop type: #'AbstractInstruction *'>
- 	self assert: reg ~= scratch.
- 	cogit MoveR: reg R: scratch.
- 	skip := self genJumpImmediateInScratchReg: scratch.
- 	loop := cogit Label.
- 	"notionally
- 		self genGetClassIndexOfNonImm: reg into: scratch.
- 		cogit CmpCq: objectMemory isForwardedObjectClassIndexPun R: TempReg.
- 	 but the following is an instruction shorter:"
- 	cogit MoveMw: 0 r: reg R: scratch.
- 	cogit
- 		AndCq: objectMemory classIndexMask - objectMemory isForwardedObjectClassIndexPun
- 		R: scratch.
- 	ok := cogit JumpNonZero:  0.
- 	self genLoadSlot: 0 sourceReg: reg destReg: reg.
- 	cogit Jump: loop.
- 	skip jmpTarget: (ok jmpTarget: cogit Label).
- 	^0!

Item was added:
+ ----- Method: CogObjectRepresentationForSpur>>genEnsureOopInRegNotForwarded:scratchReg:ifForwarder:ifNotForwarder: (in category 'compile abstract instructions') -----
+ genEnsureOopInRegNotForwarded: reg scratchReg: scratch ifForwarder: fwdJumpTarget ifNotForwarder: nonFwdJumpTargetOrZero
+ 	"Make sure that the oop in reg is not forwarded.  
+ 	 Use the fact that isForwardedObjectClassIndexPun is a power of two to save an instruction."
+ 	| skip ok finished |
+ 	<inline: true>
+ 	<var: #ok type: #'AbstractInstruction *'>
+ 	<var: #skip type: #'AbstractInstruction *'>
+ 	<var: #finished type: #'AbstractInstruction *'>
+ 	self assert: reg ~= scratch.
+ 	cogit MoveR: reg R: scratch.
+ 	skip := self genJumpImmediateInScratchReg: scratch.
+ 	"notionally
+ 		self genGetClassIndexOfNonImm: reg into: scratch.
+ 		cogit CmpCq: objectMemory isForwardedObjectClassIndexPun R: TempReg.
+ 	 but the following is an instruction shorter:"
+ 	cogit MoveMw: 0 r: reg R: scratch.
+ 	cogit
+ 		AndCq: objectMemory classIndexMask - objectMemory isForwardedObjectClassIndexPun
+ 		R: scratch.
+ 	ok := cogit JumpNonZero: 0.
+ 	self genLoadSlot: 0 sourceReg: reg destReg: reg.
+ 	cogit Jump: fwdJumpTarget.
+ 	finished := nonFwdJumpTargetOrZero = 0
+ 		ifTrue: [ cogit Label ]
+ 		ifFalse: [ nonFwdJumpTargetOrZero ].
+ 	skip jmpTarget: (ok jmpTarget: finished).
+ 	^0!

Item was added:
+ ----- Method: CogObjectRepresentationForSpur>>genEnsureOopInRegNotForwarded:scratchReg:jumpBackTo: (in category 'compile abstract instructions') -----
+ genEnsureOopInRegNotForwarded: reg scratchReg: scratch jumpBackTo: instruction
+ 	^ self 
+ 		genEnsureOopInRegNotForwarded: reg 
+ 		scratchReg: scratch 
+ 		ifForwarder: instruction
+ 		ifNotForwarder: 0!

Item was changed:
  ----- Method: CogObjectRepresentationForSpur>>genInnerPrimitiveIdentical:orNotIf: (in category 'primitive generators') -----
  genInnerPrimitiveIdentical: retNoffset orNotIf: orNot
  	| jumpImmediate jumpCmp |
  	<var: #jumpCmp type: #'AbstractInstruction *'>
  	<var: #jumpImmediate type: #'AbstractInstruction *'>
  	cogit MoveR: Arg0Reg R: TempReg.
  	jumpImmediate := self genJumpImmediateInScratchReg: TempReg.
  	self genEnsureObjInRegNotForwarded: Arg0Reg scratchReg: TempReg.
  	jumpImmediate jmpTarget:
  		(cogit CmpR: Arg0Reg R: ReceiverResultReg).
  	jumpCmp := orNot
  					ifTrue: [cogit JumpZero: 0]
  					ifFalse: [cogit JumpNonZero: 0].
+ 	cogit genMoveTrueR: ReceiverResultReg.
- 	cogit annotate: (cogit MoveCw: objectMemory trueObject R: ReceiverResultReg)
- 		objRef: objectMemory trueObject.
  	cogit RetN: retNoffset.
+ 	jumpCmp jmpTarget: (cogit genMoveFalseR: ReceiverResultReg).
- 	jumpCmp jmpTarget: (cogit annotate: (cogit MoveCw: objectMemory falseObject R: ReceiverResultReg)
- 								objRef: objectMemory falseObject).
  	cogit RetN: retNoffset.
  	^0!

Item was added:
+ ----- Method: CogObjectRepresentationForSpur>>genSpecialSelectorEqualsEqualsGuts (in category 'compile abstract instructions') -----
+ genSpecialSelectorEqualsEqualsGuts
+ 	< inline: true >
+ 	^ cogit genSpecialSelectorEqualsEqualsWithForwarders!

Item was removed:
- ----- Method: CogObjectRepresentationForSqueakV3>>branchIfInstanceOfBehavior:branches: (in category 'sista support') -----
- branchIfInstanceOfBehavior: classObj branches: branches
- 	"Generate a branch if ReceiverResultReg is an instance of classObj, otherwise fall-
- 	 through. Store the branch in branches and answer the number of branches generated."
- 	<var: #branches type: #'AbstractInstruction **'>
- 	| jmpImmediate compactClassIndex |
- 	<var: #jmpImmediate type: #'AbstractInstruction *'>
- 	cogit MoveR: ReceiverResultReg R: TempReg.
- 	jmpImmediate := self genJumpSmallIntegerInScratchReg: TempReg.
- 	classObj = (objectMemory splObj: ClassSmallInteger) ifTrue:
- 		[branches at: 0 put: jmpImmediate.
- 		 ^1].
- 	(compactClassIndex := objectMemory compactClassIndexOfClass: classObj) ~= 0
- 		ifTrue:
- 			[self genGetCompactClassIndexNonImmOf: ReceiverResultReg into: TempReg.
- 			 cogit CmpCq: compactClassIndex R: TempReg]
- 		ifFalse:
- 			[self genGetClassObjectOfNonCompact: ReceiverResultReg into: TempReg.
- 			 cogit
- 				annotate: (cogit CmpCw: classObj R: TempReg)
- 				objRef: classObj].
- 	branches at: 0 put: (cogit JumpZero: 0).
- 	^1!

Item was removed:
- ----- Method: CogObjectRepresentationForSqueakV3>>branchIfInstanceOfBehaviors:branches: (in category 'sista support') -----
- branchIfInstanceOfBehaviors: arrayObj branches: branches
- 	"Generate a branch if ReceiverResultReg is an instance of any of the classes in arrayObj,
- 	 otherwise fall-through. Store the branch in branches and answer the number of branches
- 	 generated."
- 	<var: #branches type: #'AbstractInstruction **'>
- 	| anImmediate allCompact noneCompact classObj jmpImmediate jmpCompact branchIndex |
- 	<var: #jmpCompact type: #'AbstractInstruction *'>
- 	<var: #jmpImmediate type: #'AbstractInstruction *'>
- 	"let me tell you all about it, let me falsify"
- 	anImmediate := false. allCompact := true. noneCompact := true.
- 	0 to: (objectMemory numSlotsOf: arrayObj) - 1 do:
- 		[:i|
- 		 classObj := objectMemory fetchPointer: i ofObject: arrayObj.
- 		 classObj = (objectMemory splObj: ClassSmallInteger)
- 			ifTrue:
- 				[anImmediate := true]
- 			ifFalse:
- 				[(objectMemory compactClassIndexOfClass: classObj) = 0
- 					ifTrue: [allCompact := false]
- 					ifFalse: [noneCompact := false]]].
- 	cogit MoveR: ReceiverResultReg R: TempReg.
- 	branchIndex := 0.
- 	jmpImmediate := self genJumpSmallIntegerInScratchReg: TempReg.
- 	self genGetCompactClassIndexNonImmOf: ReceiverResultReg into: TempReg.
- 	noneCompact
- 		ifTrue:
- 			[cogit CmpCq: 0 R: TempReg.
- 			 jmpCompact := cogit JumpNonZero: 0]
- 		ifFalse:
- 			[0 to: (objectMemory numSlotsOf: arrayObj) - 1 do:
- 				[:i| | compactClassIndex |
- 				 classObj := objectMemory fetchPointer: i ofObject: arrayObj.
- 				 (classObj ~= (objectMemory splObj: ClassSmallInteger)
- 				  and: [(compactClassIndex := objectMemory compactClassIndexOfClass: classObj) ~= 0]) ifTrue:
- 					[cogit CmpCq: compactClassIndex R: TempReg.
- 					 branches at: branchIndex put: (cogit JumpZero: 0).
- 					 branchIndex := branchIndex + 1]]].
- 	allCompact ifFalse:
- 		[self genGetClassObjectOfNonCompact: ReceiverResultReg into: TempReg.
- 		 0 to: (objectMemory numSlotsOf: arrayObj) - 1 do:
- 			[:i|
- 			 classObj := objectMemory fetchPointer: i ofObject: arrayObj.
- 			 (classObj ~= (objectMemory splObj: ClassSmallInteger)
- 			  and: [(objectMemory compactClassIndexOfClass: classObj) = 0]) ifTrue:
- 				[cogit
- 					annotate: (cogit CmpCw: classObj R: TempReg)
- 					objRef: classObj.
- 				 branches at: branchIndex put: (cogit JumpZero: 0).
- 				 branchIndex := branchIndex + 1]]].
- 	"Either succeed or fail on the immediate test."
- 	anImmediate
- 		ifTrue: [branches at: branchIndex put: jmpImmediate.
- 				branchIndex := branchIndex + 1]
- 		ifFalse: [jmpImmediate jmpTarget: cogit Label].
- 	noneCompact ifTrue:
- 		[jmpCompact jmpTarget: cogit Label].
- 	self assert: branchIndex = (objectMemory numSlotsOf: arrayObj).
- 	^branchIndex!

Item was changed:
  ----- Method: CogObjectRepresentationForSqueakV3>>genFetchIndexRegister:from:into: (in category 'compile abstract instructions') -----
  genFetchIndexRegister: indexReg from: tableObj into: destReg
  	"indexReg contains the 1-relative index of an element in tableObj.
  	 Since BaseHeaderSize = BytesPerOop we can use it as a
  	 zero-relative index from the beginning of the object."
  	self assert: indexReg ~= destReg.
+ 	cogit genMoveConstant: tableObj R: destReg.
- 	cogit annotate: (cogit MoveCw: tableObj R: destReg) objRef: tableObj.
  	cogit MoveXwr: indexReg R: destReg R: destReg.
  	^0!

Item was changed:
  ----- Method: CogObjectRepresentationForSqueakV3>>genGetClassObjectOf:into:scratchReg:instRegIsReceiver: (in category 'compile abstract instructions') -----
  genGetClassObjectOf: instReg into: destReg scratchReg: scratchReg instRegIsReceiver: instRegIsReceiver
  	"Fetch the instance's class into destReg.  This is almost identical
  	 to genGetClassFormatOfNonInt:into:scratchReg: but because we
  	 put the fetch of SmallInteger between the then and the else for 
  	 compact class/non-compact class we cannot easily share code.
  	 instRegIsReceiver is ignored.  It is for Spur compatibility where
  	 objects may be forwarded."
  	| jumpIsInt jumpCompact jumpGotClass jumpGotClass2 |
  	<var: #jumpIsInt type: #'AbstractInstruction *'>
  	<var: #jumpCompact type: #'AbstractInstruction *'>
  	<var: #jumpGotClass type: #'AbstractInstruction *'>
  	<var: #jumpGotClass2 type: #'AbstractInstruction *'>
  	cogit MoveR: instReg R: scratchReg.
  	cogit AndCq: 1 R: scratchReg.
  	jumpIsInt := cogit JumpNonZero: 0.
  	"Get header word in scratchReg"
  	cogit MoveMw: 0 r: instReg R: scratchReg.
  	"Form the byte index of the compact class field"
  	cogit LogicalShiftRightCq: (objectMemory compactClassFieldLSB - objectMemory shiftForWord) R: scratchReg.
  	cogit AndCq: self compactClassFieldMask << objectMemory shiftForWord R: scratchReg.
  	jumpCompact := cogit JumpNonZero: 0.
  	cogit MoveMw: objectMemory classFieldOffset r: instReg R: destReg.
  	cogit AndCq: AllButTypeMask signedIntFromLong R: destReg.
  	jumpGotClass := cogit Jump: 0.
+ 	jumpIsInt jmpTarget: (cogit genMoveConstant: objectMemory classSmallInteger R: destReg).
- 	jumpIsInt jmpTarget:
- 		(cogit annotate: (cogit MoveCw: objectMemory classSmallInteger R: destReg)
- 				objRef: objectMemory classSmallInteger).
  	jumpGotClass2 := cogit Jump: 0.
  	"Don't have to subtract one from the destReg compactClassArray index because of the header word."
  	self assert: objectMemory baseHeaderSize = objectMemory wordSize.
  	jumpCompact jmpTarget:
  		(cogit annotate: (cogit MoveMw: (objectMemory splObj: CompactClasses) r: scratchReg R: destReg)
  			objRef: (objectMemory splObj: CompactClasses)).
  	jumpGotClass jmpTarget:
  	(jumpGotClass2 jmpTarget: cogit Label).
  	^0!

Item was changed:
  ----- Method: CogObjectRepresentationForSqueakV3>>genInnerPrimitiveIdentical:orNotIf: (in category 'primitive generators') -----
  genInnerPrimitiveIdentical: retNoffset orNotIf: orNot
  	| jumpCmp |
  	<var: #jumpCmp type: #'AbstractInstruction *'>
  	cogit CmpR: Arg0Reg R: ReceiverResultReg.
  	jumpCmp := orNot
  					ifTrue: [cogit JumpZero: 0]
  					ifFalse: [cogit JumpNonZero: 0].
+ 	cogit genMoveTrueR: ReceiverResultReg.
- 	cogit annotate: (cogit MoveCw: objectMemory trueObject R: ReceiverResultReg)
- 		objRef: objectMemory trueObject.
  	cogit RetN: retNoffset.
+ 	jumpCmp jmpTarget: (cogit genMoveFalseR: ReceiverResultReg).
- 	jumpCmp jmpTarget: (cogit annotate: (cogit MoveCw: objectMemory falseObject R: ReceiverResultReg)
- 								objRef: objectMemory falseObject).
  	cogit RetN: retNoffset.
  	^0!

Item was changed:
  ----- Method: CogObjectRepresentationForSqueakV3>>genInnerPrimitiveStringAt: (in category 'primitive generators') -----
  genInnerPrimitiveStringAt: retNOffset
  	| jumpSI jumpNotSI jumpNotByteIndexable jumpBounds jumpShortHeader jumpSkip |
  	"c.f. StackInterpreter>>stSizeOf: lengthOf:baseHeader:format: fixedFieldsOf:format:length:"
  	<var: #jumpSI type: #'AbstractInstruction *'>
  	<var: #jumpNotSI type: #'AbstractInstruction *'>
  	<var: #jumpNotByteIndexable type: #'AbstractInstruction *'>
  	<var: #jumpBounds type: #'AbstractInstruction *'>
  	<var: #jumpShortHeader type: #'AbstractInstruction *'>
  	<var: #jumpSkip type: #'AbstractInstruction *'>
  	cogit MoveR: ReceiverResultReg R: TempReg.
  	jumpSI := self genJumpSmallIntegerInScratchReg: TempReg.
  	cogit MoveR: Arg0Reg R: TempReg.
  	cogit MoveR: Arg0Reg R: Arg1Reg.
  	jumpNotSI := self genJumpNotSmallIntegerInScratchReg: TempReg.
  	cogit
  		MoveMw: 0 r: ReceiverResultReg R: TempReg;	"self baseHeader: receiver"
  		MoveR: TempReg R: ClassReg;					"copy header word; we'll need it later"
  		LogicalShiftRightCq: objectMemory instFormatFieldLSB R: TempReg;
  		AndCq: self instFormatFieldMask R: TempReg;	"self formatOfHeader: destReg"
  		MoveR: TempReg R: SendNumArgsReg;
  		AndCq: 3 R: SendNumArgsReg;					"get odd bytes from format (if it turns out to be bytes)"
  		SubR: SendNumArgsReg R: TempReg;
  		CmpCq: 8 R: TempReg.							"check format is 8"
  	jumpNotByteIndexable := cogit JumpNonZero: 0.
  	cogit
  		MoveR: ClassReg R: TempReg;
  		AndCq: TypeMask R: TempReg;
  		CmpCq: HeaderTypeSizeAndClass R: TempReg.	"(hdr bitAnd: TypeMask) = HeaderTypeSizeAndClass"
  	jumpShortHeader := cogit JumpNonZero: 0.
  	self assert: Size4Bit = 0.
  	cogit
  		MoveMw: 0 - (2 * objectMemory wordSize) r: ReceiverResultReg R: ClassReg; "(self sizeHeader: oop) bitAnd: LongSizeMask"
  		AndCq: LongSizeMask signedIntFromLong R: ClassReg.
  	jumpSkip :=  cogit Jump: 0.
  	jumpShortHeader jmpTarget: (cogit AndCq: SizeMask R: ClassReg).	"hdr bitAnd: SizeMask"
  	jumpSkip jmpTarget: (cogit SubCq: objectMemory baseHeaderSize R: ClassReg). "sz - BaseHeaderSize"
  	cogit SubR: SendNumArgsReg R: ClassReg. "sz - (fmt bitAnd: 3)"
  	self genConvertSmallIntegerToIntegerInReg: Arg1Reg.
  	cogit SubCq: 1 R: Arg1Reg.
  	cogit CmpR: ClassReg R: Arg1Reg.
  	jumpBounds := cogit JumpAboveOrEqual: 0.
  	cogit AddCq: objectMemory baseHeaderSize R: Arg1Reg.
+ 	cogit genMoveConstant: objectMemory characterTable R: Arg0Reg.
- 	cogit annotate: (cogit MoveCw: objectMemory characterTable R: Arg0Reg)
- 		objRef: objectMemory characterTable.
  	cogit MoveXbr: Arg1Reg R: ReceiverResultReg R: ReceiverResultReg;
  		AddCq: objectMemory baseHeaderSize / objectMemory wordSize R: ReceiverResultReg.
  	cogit MoveXwr: ReceiverResultReg R: Arg0Reg R: ReceiverResultReg.
  	cogit RetN: retNOffset.
  	jumpSI jmpTarget:
  	(jumpNotSI jmpTarget:
  	(jumpNotByteIndexable jmpTarget:
  	(jumpBounds jmpTarget:
  		cogit Label))).
  	^0!

Item was added:
+ ----- Method: CogObjectRepresentationForSqueakV3>>genSpecialSelectorEqualsEqualsGuts (in category 'compile abstract instructions') -----
+ genSpecialSelectorEqualsEqualsGuts
+ 	< inline: true >
+ 	^ cogit genVanillaSpecialSelectorEqualsEquals!

Item was changed:
  ----- Method: CogSimStackEntry>>popToReg: (in category 'compile abstract instructions') -----
  popToReg: reg
  	| inst |
  	<var: #inst type: #'AbstractInstruction *'>
  	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].
- 				[SSConstant]	-> [inst := (objectRepresentation shouldAnnotateObjectReference: constant)
- 												ifTrue: [cogit annotate: (cogit MoveCw: constant R: reg) objRef: constant]
- 												ifFalse: [cogit MoveCq: constant R: reg]].
  				[SSRegister]	-> [inst := reg ~= register
  												ifTrue: [cogit MoveR: register R: reg]
  												ifFalse: [cogit Label]] }].
  	annotateUse ifTrue:
  		[cogit annotateBytecode: inst.
  		 annotateUse := false]!

Item was changed:
  ----- Method: CogSimStackEntry>>storeToReg: (in category 'compile abstract instructions') -----
  storeToReg: reg
  	| inst |
  	<var: #inst type: #'AbstractInstruction *'>
  	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].
- 		[SSConstant]	-> [inst := (objectRepresentation shouldAnnotateObjectReference: constant)
- 										ifTrue: [cogit annotate: (cogit MoveCw: constant R: reg) objRef: constant]
- 										ifFalse: [cogit MoveCq: constant R: reg]].
  		[SSRegister]	-> [inst := reg ~= register
  										ifTrue: [cogit MoveR: register R: reg]
  										ifFalse: [cogit Label]] }.
  	annotateUse ifTrue:
  		[cogit annotateBytecode: inst.
  		 annotateUse := false]!

Item was changed:
  ----- Method: Cogit>>setInterpreter: (in category 'initialization') -----
  setInterpreter: aCoInterpreter
  	"Initialization of the code generator in the simulator.
  	 These objects already exist in the generated C VM
  	 or are used only in the simulation."
  	<doNotGenerate>
  	coInterpreter := aCoInterpreter.
  	objectMemory := aCoInterpreter objectMemory.
  	threadManager := aCoInterpreter threadManager. "N.B. may be nil"
  	methodZone := CogMethodZone new.
  	objectRepresentation := objectMemory objectRepresentationClass
  								forCogit: self methodZone: methodZone.
  	methodZone setInterpreter: aCoInterpreter
  				objectRepresentation: objectRepresentation
  				cogit: self.
  	generatorTable := self class generatorTable.
  	primitiveGeneratorTable := self class primitiveTable.
  	processor := ProcessorClass new.
  	simulatedAddresses := Dictionary new.
  	simulatedTrampolines := Dictionary new.
  	simulatedVariableGetters := Dictionary new.
  	simulatedVariableSetters := Dictionary new.
  	traceStores := 0.
  	traceFlags := 8. "record prim trace on by default (see Cogit class>>decareCVarsIn:)"
  	debugPrimCallStackOffset := 0.
  	singleStep := printRegisters := printInstructions := clickConfirm := false.
  	breakBlock ifNil: [self breakPC: breakPC].
  	(backEnd := processor abstractInstructionCompilerClass new) cogit: self.
  	(methodLabel := processor abstractInstructionCompilerClass new) cogit: self.
  	ordinarySendTrampolines := CArrayAccessor on: (Array new: NumSendTrampolines).
  	superSendTrampolines := CArrayAccessor on: (Array new: NumSendTrampolines).
  	BytecodeSetHasDirectedSuperSend ifTrue:
  		[directedSuperSendTrampolines := CArrayAccessor on: (Array new: NumSendTrampolines)].
  	NewspeakVM ifTrue:
  		[selfSendTrampolines := CArrayAccessor on: (Array new: NumSendTrampolines).
  		dynamicSuperSendTrampolines := CArrayAccessor on: (Array new: NumSendTrampolines).
  		implicitReceiverSendTrampolines := CArrayAccessor on: (Array new: NumSendTrampolines).
  		outerSendTrampolines := CArrayAccessor on: (Array new: NumSendTrampolines)].
  	"debug metadata"
  	objectReferencesInRuntime := CArrayAccessor on: (Array new: NumObjRefsInRuntime).
  	runtimeObjectRefIndex := 0.
  	"debug metadata"
  	trampolineAddresses := CArrayAccessor on: (Array new: NumTrampolines * 2).
  	trampolineTableIndex := 0.
  
+ 	compilationTrace ifNil: [compilationTrace := self class initializationOptions at: #compilationTrace ifAbsent: [0]].
- 	compilationTrace ifNil: [compilationTrace := 0].
  	extA := extB := 0!

Item was changed:
  ----- Method: CurrentImageCoInterpreterFacade>>methodHeaderOf: (in category 'accessing') -----
+ methodHeaderOf: methodOop
+ 	^self rawHeaderOf: methodOop!
- methodHeaderOf: oop
- 	^(self objectForOop: oop) header!

Item was changed:
  ----- Method: FilePluginSimulator>>fileValueOf: (in category 'simulation') -----
  fileValueOf: objectPointer
  	| index file |
  	index := (interpreterProxy isIntegerObject: objectPointer)
  				ifTrue: [interpreterProxy integerValueOf: objectPointer]
  				ifFalse:
  					[((interpreterProxy isBytes: objectPointer)
  					  and: [(interpreterProxy byteSizeOf: objectPointer) = (self sizeof: #SQFile)]) ifFalse:
  						[interpreterProxy primitiveFail.
  						 ^nil].
  					interpreterProxy longAt: objectPointer + interpreterProxy baseHeaderSize].
+ 	file := openFiles at: index ifAbsent: [ interpreterProxy primitiveFail. ^ nil ].
- 	file := openFiles at: index.
  	"this attempts to preserve file positions across snapshots when debugging the VM
  	 requires saving an image in full flight and pushing it over the cliff time after time..."
  	(file closed and: [states includesKey: file]) ifTrue:
  		[[:pos :isBinary|
  		  file reopen; position: pos.
  		  isBinary ifTrue:
  			[file binary]] valueWithArguments: (states at: file)].
  	^file!

Item was changed:
  ----- Method: ObjectMemory>>storeLong64:ofObject:withValue: (in category 'object access') -----
  storeLong64: longIndex ofObject: oop withValue: value
  	<var: #value type: #sqLong>
+ 	self flag: #endianness.
+ 	self long32At: oop + self baseHeaderSize + (longIndex << 3) put: (self cCode: [value] inSmalltalk: [value bitAnd: 16rFFFFFFFF]);
+ 		long32At: oop + self baseHeaderSize + (longIndex << 3) + 4 put: (value >> 32).
+ 	^value!
- 	^self long64At: oop + self baseHeaderSize + (longIndex << 3) put: value!

Item was changed:
  ----- Method: SistaStackToRegisterMappingCogit>>genSpecialSelectorEqualsEquals (in category 'bytecode generators') -----
  genSpecialSelectorEqualsEquals
  	"Override to count inlined branches if followed by a conditional branch.
  	 We borrow the following conditional branch's counter and when about to
  	 inline the comparison we decrement the counter (without writing it back)
  	 and if it trips simply abort the inlining, falling back to the normal send which
  	 will then continue to the conditional branch which will trip and enter the abort."
  	| nextPC postBranchPC targetBytecodePC primDescriptor branchDescriptor nExts
  	  counterAddress countTripped unforwardArg unforwardRcvr |
  	<var: #countTripped type: #'AbstractInstruction *'>
  	<var: #primDescriptor type: #'BytecodeDescriptor *'>
  	<var: #branchDescriptor type: #'BytecodeDescriptor *'>
  
+ 	((coInterpreter isOptimizedMethod: methodObj) or: [needsFrame not]) ifTrue: [ ^ super genSpecialSelectorEqualsEquals ].
- 	(coInterpreter isOptimizedMethod: methodObj) ifTrue: [ ^ super genSpecialSelectorEqualsEquals ].
  
  	self ssFlushTo: simStackPtr - 2.
  	primDescriptor := self generatorAt: byte0.
  
  	nextPC := bytecodePC + primDescriptor numBytes.
  	nExts := 0.
  	[branchDescriptor := self generatorAt: (objectMemory fetchByte: nextPC ofObject: methodObj) + (byte0 bitAnd: 256).
  	 branchDescriptor isExtension] whileTrue:
  		[nExts := nExts + 1.
  		 nextPC := nextPC + branchDescriptor numBytes].
  	"Only interested in inlining if followed by a conditional branch."
  	(branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse]) ifFalse:
  		[^self genSpecialSelectorSend].
  
  	targetBytecodePC := nextPC
  							+ branchDescriptor numBytes
  							+ (self spanFor: branchDescriptor at: nextPC exts: nExts in: methodObj).
  	postBranchPC := nextPC + branchDescriptor numBytes.
  	unforwardRcvr := (self ssValue: 1) type ~= SSConstant
  						or: [objectRepresentation shouldAnnotateObjectReference: (self ssValue: 1) constant].
  	unforwardArg := self ssTop type ~= SSConstant
  						or: [objectRepresentation shouldAnnotateObjectReference: self ssTop constant].
  	self marshallSendArguments: 1.
  
  	self ssAllocateRequiredReg: SendNumArgsReg. "Use this as the count reg."
  	counterAddress := counters + ((self sizeof: #sqInt) * counterIndex).
  	self flag: 'will need to use MoveAw32:R: if 64 bits'.
  	self assert: objectMemory wordSize = CounterBytes.
  	self MoveAw: counterAddress R: SendNumArgsReg.
  	self SubCq: 16r10000 R: SendNumArgsReg. "Count executed"
  	"If counter trips simply abort the inlined comparison and send continuing to the following
  	 branch *without* writing back.  A double decrement will not trip the second time."
  	countTripped := self JumpCarry: 0.
  	self MoveR: SendNumArgsReg Aw: counterAddress. "write back"
  	unforwardRcvr ifTrue:
  		[objectRepresentation genEnsureOopInRegNotForwarded: ReceiverResultReg scratchReg: TempReg].
  	unforwardArg ifTrue:
  		[objectRepresentation genEnsureOopInRegNotForwarded: Arg0Reg scratchReg: TempReg].
  	self CmpR: Arg0Reg R: ReceiverResultReg.
  	"Cmp is weird/backwards so invert the comparison.  Further since there is a following conditional
  	 jump bytecode define non-merge fixups and leave the cond bytecode to set the mergeness."
  	self gen: (branchDescriptor isBranchTrue ifTrue: [JumpZero] ifFalse: [JumpNonZero])
  		operand: (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger.
  	self SubCq: 1 R: SendNumArgsReg. "Count untaken"
  	self MoveR: SendNumArgsReg Aw: counterAddress. "write back"
  	self Jump: (self ensureNonMergeFixupAt: postBranchPC - initialPC).
  	countTripped jmpTarget: self Label.
  	^self genMarshalledSend: (coInterpreter specialSelector: byte0 - self firstSpecialSelectorBytecodeOffset)
  		numArgs: 1
  		sendTable: ordinarySendTrampolines!

Item was changed:
  ----- Method: SistaStackToRegisterMappingCogit>>generateSistaRuntime (in category 'initialization') -----
  generateSistaRuntime
  	"Trap sends Sista trap message to context with top of stack, so we don't need any arguments..."
+ 	ceTrapTrampoline := self genTrampolineFor: #ceSistaTrap called: 'ceSistaTrapTrampoline'!
- 	ceTrapTrampoline := self genTrampolineFor: #ceSistaTrap:
- 									called: 'ceSistaTrapTrampoline'
- 									arg: ReceiverResultReg!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>compileAbstractInstructionsFrom:through: (in category 'compile abstract instructions') -----
  compileAbstractInstructionsFrom: start through: end
  	"Loop over bytecodes, dispatching to the generator for each bytecode, handling fixups in due course."
  	| nextOpcodeIndex descriptor nExts fixup result |
  	<var: #descriptor type: #'BytecodeDescriptor *'>
  	<var: #fixup type: #'BytecodeFixup *'>
  	self traceSimStack.
  	bytecodePC := start.
  	nExts := 0.
  	descriptor := nil.
  	deadCode := false.
  	[self cCode: '' inSmalltalk:
  		[(debugBytecodePointers includes: bytecodePC) ifTrue: [self halt]].
  	fixup := self fixupAt: bytecodePC - initialPC.
+ 	"If there's no fixup following a return there's no jump to that code and it is dead."
+ 	(descriptor notNil and: [descriptor isReturn]) ifTrue: [deadCode := true].
+ 	fixup targetInstruction asUnsignedInteger > 0 ifTrue:
+ 		[fixup targetInstruction asUnsignedInteger >= 2 ifTrue:
+ 			[self merge: fixup afterContinuation: deadCode not].
+ 		deadCode := false].
- 	fixup targetInstruction asUnsignedInteger > 0
- 		ifTrue:
- 			[deadCode := false.
- 	 		 fixup targetInstruction asUnsignedInteger >= 2 ifTrue:
- 				[self merge: fixup
- 					afterContinuation: (descriptor notNil
- 										and: [descriptor isUnconditionalBranch
- 											or: [descriptor isReturn]]) not]]
- 		ifFalse: "If there's no fixup following a return there's no jump to that code and it is dead."
- 			[(descriptor notNil and: [descriptor isReturn]) ifTrue:
- 				[deadCode := true]].
  	 self cCode: '' inSmalltalk:
  		[deadCode ifFalse:
  			[self assert: simStackPtr + (needsFrame ifTrue: [0] ifFalse: [1])
  						= (self debugStackPointerFor: bytecodePC)]].
  	 byte0 := (objectMemory fetchByte: bytecodePC ofObject: methodObj) + bytecodeSetOffset.
  	 descriptor := self generatorAt: byte0.
  	 self loadSubsequentBytesForDescriptor: descriptor at: bytecodePC.
  	 nextOpcodeIndex := opcodeIndex.
  	 result := deadCode
  				ifTrue: "insert nops for dead code that is mapped so that bc to mc mapping is not many to one"
  					[(descriptor isMapped
  					  or: [inBlock and: [descriptor isMappedInBlock]]) ifTrue:
  						[self annotateBytecode: self Nop].
  						0]
  				ifFalse:
  					[self perform: descriptor generator].
  	 descriptor isExtension ifFalse: "extended bytecodes must consume their extensions"
  		[self assert: (extA = 0 and: [extB = 0])].
  	 self traceDescriptor: descriptor; traceSimStack.
  	 (fixup targetInstruction asUnsignedInteger between: 1 and: 2) ifTrue:
  		["There is a fixup for this bytecode.  It must point to the first generated
  		   instruction for this bytecode.  If there isn't one we need to add a label."
  		 opcodeIndex = nextOpcodeIndex ifTrue:
  			[self Label].
  		 fixup targetInstruction: (self abstractInstructionAt: nextOpcodeIndex)].
  	 bytecodePC := self nextBytecodePCFor: descriptor at: bytecodePC exts: nExts in: methodObj.
  	 result = 0 and: [bytecodePC <= end]] whileTrue:
  		[nExts := descriptor isExtension ifTrue: [nExts + 1] ifFalse: [0]].
  	self checkEnoughOpcodes.
  	^result!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>compileBlockFrameBuild: (in category 'compile abstract instructions') -----
  compileBlockFrameBuild: blockStart
  	"Build a frame for a block activation.  See CoInterpreter class>>initializeFrameIndices.
  	 Override to push the register receiver and register arguments, if any, and to correctly
  	 initialize the explicitly nilled/pushed temp entries (they are /not/ of type constant nil)."
  	super compileBlockFrameBuild: blockStart.
  	methodOrBlockNumTemps := blockStart numArgs + blockStart numCopied + blockStart numInitialNils.
  	self initSimStackForFramefulMethod: blockStart startpc.
  	blockStart numInitialNils > 0 ifTrue:
  		[blockStart numInitialNils > 1
  			ifTrue:
+ 				[self genMoveConstant: objectMemory nilObject R: TempReg.
- 				[self
- 					annotate: (self MoveCw: objectMemory nilObject R: TempReg)
- 					objRef: objectMemory nilObject.
  				 1 to: blockStart numInitialNils do:
  					[:ign| self PushR: TempReg]]
  			ifFalse:
  				[self
  					annotate: (self PushCw: objectMemory nilObject)
  					objRef: objectMemory nilObject].
  		 methodOrBlockNumTemps := blockStart numArgs + blockStart numCopied]!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genBinaryConstOpVarInlinePrimitive: (in category 'inline primitive generators') -----
  genBinaryConstOpVarInlinePrimitive: prim
  	"Const op var version of binary inline primitives."
  	"SistaV1: 248		11111000 	iiiiiiii		mjjjjjjj		Call Primitive #iiiiiiii + (jjjjjjj * 256) m=1 means inlined primitive, no hard return after execution.
  	 See EncoderForSistaV1's class comment and StackInterpreter>>#binaryInlinePrimitive:"
  	| ra val untaggedVal adjust |
  	ra := self allocateOneRegister.
  	self ssTop popToReg: ra.
  	self ssPop: 1.
  	val := self ssTop constant.
  	self ssPop: 1.
  	untaggedVal := val - objectMemory smallIntegerTag.
  	prim caseOf: {
  		"0 through 6, +, -, *, /, //, \\, quo:, SmallInteger op SmallInteger => SmallInteger, no overflow"
  		[0]	->	[self AddCq: untaggedVal R: ra].
  		[1]	->	[self MoveCq: val R: TempReg.
  				 self SubR: ra R: TempReg.
  				 objectRepresentation genAddSmallIntegerTagsTo: TempReg.
  				 self MoveR: TempReg R: ra].
  		[2]	->	[objectRepresentation genRemoveSmallIntegerTagsInScratchReg: ra.
  				 self MoveCq: (objectMemory integerValueOf: val) R: TempReg.
  				 self MulR: TempReg R: ra.
  				 objectRepresentation genAddSmallIntegerTagsTo: ra].
  
  		"2016 through 2019, bitAnd:, bitOr:, bitXor, bitShift:, SmallInteger op SmallInteger => SmallInteger, no overflow"
  
  		"2032	through 2037, >, <, >=, <=. =, ~=, SmallInteger op SmallInteger => Boolean (flags?? then in jump bytecodes if ssTop is a flags value, just generate the instruction!!!!)"
  		"CmpCqR is SubRCq so everything is reversed, but because no CmpRCq things are reversed again and we invert the sense of the jumps."
  		[32] -> [ self CmpCq: val R: ra.
  				self genBinaryInlineComparison: JumpLess opFalse: JumpGreaterOrEqual destReg: ra ].
  		[33] -> [ self CmpCq: val R: ra.
  				self genBinaryInlineComparison: JumpGreater opFalse: JumpLessOrEqual destReg: ra ].
  		[34] -> [ self CmpCq: val R: ra.
  				self genBinaryInlineComparison: JumpLessOrEqual opFalse: JumpGreater destReg: ra ].
  		[35] -> [ self CmpCq: val R: ra.
  				self genBinaryInlineComparison: JumpGreaterOrEqual opFalse: JumpLess destReg: ra ].
  		[36] -> [ self CmpCq: val R: ra.
  				self genBinaryInlineComparison: JumpZero opFalse: JumpNonZero destReg: ra ].
  		[37] -> [ self CmpCq: val R: ra.
  				self genBinaryInlineComparison: JumpNonZero opFalse: JumpZero destReg: ra ].
  
  		"2064	through 2068, Pointer Object>>at:, Byte Object>>at:, Short16 Word Object>>at: LongWord32 Object>>at: Quad64Word Object>>at:. obj op 0-rel SmallInteger => oop"
  		[64] ->	[objectRepresentation genConvertSmallIntegerToIntegerInReg: ra.
  				adjust := (objectMemory baseHeaderSize >> objectMemory shiftForWord) - 1. "shift by baseHeaderSize and then move from 1 relative to zero relative"
  				adjust ~= 0 ifTrue: [ self AddCq: adjust R: ra. ]. 
+ 				self genMoveConstant: val R: TempReg.
- 				self annotate: (self MoveCw: val R: TempReg) objRef: val.
  				self MoveXwr: ra R: TempReg R: ra].
  		[65] ->	[objectRepresentation genConvertSmallIntegerToIntegerInReg: ra.
  				adjust := objectMemory baseHeaderSize - 1. "shift by baseHeaderSize and then move from 1 relative to zero relative"
  				self AddCq: adjust R: ra.
+ 				self genMoveConstant: val R: TempReg.
- 				self annotate: (self MoveCw: val R: TempReg) objRef: val.
  				self MoveXbr: ra R: TempReg R: ra.
  				objectRepresentation genConvertIntegerToSmallIntegerInReg: ra]
  	}
  	otherwise: [^EncounteredUnknownBytecode].
  	self ssPushRegister: ra.
  	^0!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genBinaryInlineComparison:opFalse:destReg: (in category 'inline primitive generators') -----
  genBinaryInlineComparison: opTrue opFalse: opFalse destReg: destReg
  	"Inlined comparison. opTrue = jump for true and opFalse = jump for false"
  	| nextPC branchDescriptor nExts |	
  	nextPC := bytecodePC + 3.
  	nExts := 0.	
  	[branchDescriptor := self generatorAt: (objectMemory fetchByte: nextPC ofObject: methodObj) + (byte0 bitAnd: 256).
  	 branchDescriptor isExtension] whileTrue:
  		[nExts := nExts + 1.
  	 	 nextPC := nextPC + branchDescriptor numBytes].
  	(branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse])
  		ifTrue: "This is the path where the inlined comparison is followed immediately by a branch"
  			[| targetBytecodePC postBranchPC |
  			targetBytecodePC := nextPC
  					+ branchDescriptor numBytes
  					+ (self spanFor: branchDescriptor at: nextPC exts: nExts in: methodObj).
  			postBranchPC := nextPC + branchDescriptor numBytes.
  			(self fixupAt: nextPC - initialPC) targetInstruction = 0
  				ifTrue: "The next instruction is dead.  we can skip it."
  					[deadCode := true.
  				 	 self ensureFixupAt: targetBytecodePC - initialPC.
+ 					 self ensureFixupAt: postBranchPC - initialPC ]
- 					 self ensureFixupAt: postBranchPC - initialPC]
  				ifFalse:
  					[self ssPushConstant: objectMemory trueObject]. "dummy value"
  			self gen: (branchDescriptor isBranchTrue ifTrue: [opTrue] ifFalse: [opFalse])
+ 				operand: (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger. 
+ 			deadCode ifFalse: [ self Jump: (self ensureNonMergeFixupAt: postBranchPC - initialPC) ] ]
- 				operand: (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger.
- 			self Jump: (self ensureNonMergeFixupAt: postBranchPC - initialPC)]
  		ifFalse: "This is the path where the inlined comparison is *not* followed immediately by a branch"
  			[| condJump jump |
  			condJump := self gen: opTrue operand: 0.
+ 			self genMoveFalseR: destReg.
- 	 		self 
- 				annotate: (self MoveCw: objectMemory falseObject R: destReg) 
- 				objRef: objectMemory falseObject.
  	 		jump := self Jump: 0.
+ 			condJump jmpTarget: (self genMoveTrueR: destReg).
- 			condJump jmpTarget: (self 
- 				annotate: (self MoveCw: objectMemory trueObject R: destReg) 
- 				objRef: objectMemory trueObject).
  			jump jmpTarget: self Label].
  	^ 0!

Item was added:
+ ----- Method: StackToRegisterMappingCogit>>genCompConstant:R: (in category 'bytecode generator support') -----
+ genCompConstant: constant R: register
+ 	<inline: true>
+ 	^ (objectRepresentation shouldAnnotateObjectReference: constant)
+ 		ifTrue: [ self annotate: (self CmpCw: constant R: register) objRef: constant ]
+ 		ifFalse: [ self CmpCq: constant R: register ]
+ 	!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genDoubleComparison:invert: (in category 'primitive generators') -----
  genDoubleComparison: jumpOpcodeGenerator invert: invertComparison
  	"Receiver and arg in registers.
  	 Stack looks like
  		return address"
  	<var: #jumpOpcodeGenerator declareC: 'AbstractInstruction *(*jumpOpcodeGenerator)(void *)'>
  	| jumpFail jumpImmediate jumpNonInt jumpCond compare |
  	<var: #jumpImmediate type: #'AbstractInstruction *'>
  	<var: #jumpNonInt type: #'AbstractInstruction *'>
  	<var: #jumpCond type: #'AbstractInstruction *'>
  	<var: #compare type: #'AbstractInstruction *'>
  	<var: #jumpFail type: #'AbstractInstruction *'>
  	self MoveR: Arg0Reg R: TempReg.
  	objectRepresentation genGetDoubleValueOf: ReceiverResultReg into: DPFPReg0.
  	jumpImmediate := objectRepresentation genJumpImmediateInScratchReg: TempReg.
  	objectRepresentation genGetCompactClassIndexNonImmOf: Arg0Reg into: SendNumArgsReg.
  	objectRepresentation genCmpClassFloatCompactIndexR: SendNumArgsReg.
  	jumpFail := self JumpNonZero: 0.
  	objectRepresentation genGetDoubleValueOf: Arg0Reg into: DPFPReg1.
  	invertComparison "May need to invert for NaNs"
  		ifTrue: [compare := self CmpRd: DPFPReg0 Rd: DPFPReg1]
  		ifFalse: [compare := self CmpRd: DPFPReg1 Rd: DPFPReg0].
  	jumpCond := self perform: jumpOpcodeGenerator with: 0. "FP jumps are a little weird"
+ 	self genMoveFalseR: ReceiverResultReg.
- 	self annotate: (self MoveCw: objectMemory falseObject R: ReceiverResultReg)
- 		objRef: objectMemory falseObject.
  	self RetN: 0.
+ 	jumpCond jmpTarget: (self genMoveTrueR: ReceiverResultReg).
- 	jumpCond jmpTarget: (self annotate: (self MoveCw: objectMemory trueObject R: ReceiverResultReg)
- 								objRef: objectMemory trueObject).
  	self RetN: 0.
  	jumpImmediate jmpTarget: self Label.
  	objectRepresentation smallIntegerIsOnlyImmediateType ifFalse:
  		[jumpNonInt := objectRepresentation genJumpNotSmallIntegerInScratchReg: TempReg].
  	objectRepresentation genConvertSmallIntegerToIntegerInReg: Arg0Reg.
  	self ConvertR: Arg0Reg Rd: DPFPReg1.
  	self Jump: compare.
  	jumpFail jmpTarget: self Label.
  	objectRepresentation smallIntegerIsOnlyImmediateType ifFalse:
  		[jumpNonInt jmpTarget: jumpFail getJmpTarget].
  	^0!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genMarshalledSend:numArgs:sendTable: (in category 'bytecode generator support') -----
  genMarshalledSend: selector numArgs: numArgs sendTable: sendTable
  	<inline: false>
  	<var: #sendTable type: #'sqInt *'>
  	| annotation |
  	(objectMemory isYoung: selector) ifTrue:
  		[hasYoungReferent := true].
  	self assert: needsFrame.
  	annotation := self annotationForSendTable: sendTable.
  	"Deal with stale super sends; see SpurMemoryManager's class comment."
  	(self annotationIsForUncheckedEntryPoint: annotation) ifTrue:
  		[objectRepresentation genEnsureOopInRegNotForwarded: ReceiverResultReg scratchReg: TempReg].
  	numArgs > 2 ifTrue:
  		[self MoveCq: numArgs R: SendNumArgsReg].
  	(BytecodeSetHasDirectedSuperSend
  	 and: [annotation = IsDirectedSuperSend]) ifTrue:
+ 		[self genMoveConstant: tempOop R: TempReg].
- 		[self annotate: (self MoveCw: tempOop R: TempReg) objRef: tempOop].
  	self MoveCw: selector R: ClassReg.
  	self annotate: (self Call: (sendTable at: (numArgs min: NumSendTrampolines - 1)))
  		with: annotation.
  	optStatus isReceiverResultRegLive: false.
  	^self ssPushRegister: ReceiverResultReg!

Item was added:
+ ----- Method: StackToRegisterMappingCogit>>genMoveConstant:R: (in category 'bytecode generator support') -----
+ genMoveConstant: constant R: register
+ 	<inline: true>
+ 	^ (objectRepresentation shouldAnnotateObjectReference: constant)
+ 		ifTrue: [ (self annotate: (self MoveCw: constant R: register) objRef: constant) ]
+ 		ifFalse: [ self MoveCq: constant R: register ]
+ 	
+ 	!

Item was added:
+ ----- Method: StackToRegisterMappingCogit>>genMoveFalseR: (in category 'bytecode generator support') -----
+ genMoveFalseR: register
+ 	<inline: true>
+ 	^ self genMoveConstant: objectMemory falseObject R: register
+ 	!

Item was added:
+ ----- Method: StackToRegisterMappingCogit>>genMoveTrueR: (in category 'bytecode generator support') -----
+ genMoveTrueR: register
+ 	<inline: true>
+ 	^ self genMoveConstant: objectMemory trueObject R: register
+ 	!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genPushLiteralVariable: (in category 'bytecode generator support') -----
  genPushLiteralVariable: literalIndex
  	<inline: false>
  	| association freeReg |
  	freeReg := self ssAllocatePreferredReg: ClassReg.
  	association := self getLiteral: literalIndex.
  	"N.B. Do _not_ use ReceiverResultReg to avoid overwriting receiver in assignment in frameless methods."
  	"So far descriptors are not rich enough to describe the entire dereference so generate the register
  	 load but don't push the result.  There is an order-of-evaluation issue if we defer the dereference."
+ 	self genMoveConstant: association R: TempReg.
- 	self annotate: (self MoveCw: association R: TempReg) objRef: association.
  	objectRepresentation
  		genEnsureObjInRegNotForwarded: TempReg
  		scratchReg: freeReg.
  	objectRepresentation
  		genLoadSlot: ValueIndex
  		sourceReg: TempReg
  		destReg: freeReg.
  	self ssPushRegister: freeReg.
  	^0!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genSmallIntegerComparison: (in category 'primitive generators') -----
  genSmallIntegerComparison: jumpOpcode
  	| jumpFail jumpTrue |
  	<var: #jumpFail type: #'AbstractInstruction *'>
  	<var: #jumpTrue type: #'AbstractInstruction *'>
  	self MoveR: Arg0Reg R: TempReg.
  	jumpFail := objectRepresentation genJumpNotSmallIntegerInScratchReg: TempReg.
  	self CmpR: Arg0Reg R: ReceiverResultReg. "N.B. FLAGS := RRReg - Arg0Reg"
  	jumpTrue := self gen: jumpOpcode.
+ 	self genMoveFalseR: ReceiverResultReg.
- 	self annotate: (self MoveCw: objectMemory falseObject R: ReceiverResultReg)
- 		objRef: objectMemory falseObject.
  	self RetN: 0.
+ 	jumpTrue jmpTarget: (self genMoveTrueR: ReceiverResultReg).
- 	jumpTrue jmpTarget: (self annotate: (self MoveCw: objectMemory trueObject R: ReceiverResultReg)
- 								objRef: objectMemory trueObject).
  	self RetN: 0.
  	jumpFail jmpTarget: self Label.
  	^0!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genSmallIntegerComparison:orDoubleComparison: (in category 'primitive generators') -----
  genSmallIntegerComparison: jumpOpcode orDoubleComparison: jumpFPOpcodeGenerator
  	"Stack looks like
  		return address"
  	| jumpDouble jumpNonInt jumpFail jumpTrue jumpCond |
  	<var: #jumpFPOpcodeGenerator declareC: 'AbstractInstruction *(*jumpFPOpcodeGenerator)(void *)'>
  	<var: #jumpDouble type: #'AbstractInstruction *'>
  	<var: #jumpNonInt type: #'AbstractInstruction *'>
  	<var: #jumpCond type: #'AbstractInstruction *'>
  	<var: #jumpTrue type: #'AbstractInstruction *'>
  	<var: #jumpFail type: #'AbstractInstruction *'>
  	backEnd hasDoublePrecisionFloatingPointSupport ifFalse:
  		[^self genSmallIntegerComparison: jumpOpcode].
  	self MoveR: Arg0Reg R: TempReg.
  	jumpDouble := objectRepresentation genJumpNotSmallIntegerInScratchReg: TempReg.
  	self CmpR: Arg0Reg R: ReceiverResultReg. "N.B. FLAGS := RRReg - Arg0Reg"
  	jumpTrue := self gen: jumpOpcode.
+ 	self genMoveFalseR: ReceiverResultReg.
- 	self annotate: (self MoveCw: objectMemory falseObject R: ReceiverResultReg)
- 		objRef: objectMemory falseObject.
  	self RetN: 0.
+ 	jumpTrue jmpTarget: (self genMoveTrueR: ReceiverResultReg).
- 	jumpTrue jmpTarget: (self annotate: (self MoveCw: objectMemory trueObject R: ReceiverResultReg)
- 								objRef: objectMemory trueObject).
  	self RetN: 0.
  	
  	"Argument may be a Float : let us check or fail"
  	jumpDouble jmpTarget: self Label.
  	objectRepresentation smallIntegerIsOnlyImmediateType ifFalse:
  		[self MoveR: ClassReg R: TempReg.
  		 jumpNonInt := objectRepresentation genJumpImmediateInScratchReg: TempReg].
  	objectRepresentation genGetCompactClassIndexNonImmOf: Arg0Reg into: SendNumArgsReg.
  	objectRepresentation genCmpClassFloatCompactIndexR: SendNumArgsReg.
  	jumpFail := self JumpNonZero: 0.
  
  	"It was a Float, so convert the receiver to double and perform the operation"
  	objectRepresentation genConvertSmallIntegerToIntegerInReg: ReceiverResultReg.
  	self ConvertR: ReceiverResultReg Rd: DPFPReg0.
  	objectRepresentation genGetDoubleValueOf: Arg0Reg into: DPFPReg1.
  	self CmpRd: DPFPReg1 Rd: DPFPReg0.
  	jumpCond := self perform: jumpFPOpcodeGenerator with: 0. "FP jumps are a little weird"
  	self annotate: (self MoveCw: objectMemory falseObject R: ReceiverResultReg)
  		objRef: objectMemory falseObject.
  	self RetN: 0.
  	jumpCond jmpTarget: (self annotate: (self MoveCw: objectMemory trueObject R: ReceiverResultReg)
  							objRef: objectMemory trueObject).
  	self RetN: 0.
  
  	objectRepresentation smallIntegerIsOnlyImmediateType
  		ifTrue: [jumpFail jmpTarget: self Label]
  		ifFalse: [jumpNonInt jmpTarget: (jumpFail jmpTarget: self Label)].
  	^0!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genSpecialSelectorEqualsEquals (in category 'bytecode generators') -----
  genSpecialSelectorEqualsEquals
+ 	| primDescriptor
+ 	  result |
- 	| nextPC postBranchPC targetBytecodePC primDescriptor branchDescriptor nExts
- 	  unforwardArg unforwardRcvr jumpEqual jumpNotEqual rcvrReg argReg result |
  	<var: #jumpEqual type: #'AbstractInstruction *'>
  	<var: #jumpNotEqual type: #'AbstractInstruction *'>
  	<var: #primDescriptor type: #'BytecodeDescriptor *'>
  	<var: #branchDescriptor type: #'BytecodeDescriptor *'>
  	primDescriptor := self generatorAt: byte0.
+ 	
+ 	((objectRepresentation isUnannotatableConstant: self ssTop)
+ 		and: [ objectRepresentation isUnannotatableConstant: (self ssValue: 1) ]) ifTrue:
- 	"forwarders have been followed in cog:selector:"
- 	(self ssTop type = SSConstant
- 	 and: [(self ssValue: 1) type = SSConstant]) ifTrue:
  		[self assert: primDescriptor isMapped not.
  		 result := self ssTop constant = (self ssValue: 1) constant
  									ifTrue: [objectMemory trueObject]
  									ifFalse: [objectMemory falseObject].
  		 self ssPop: 2.
  		 ^self ssPushConstant: result].
  
+ 	^ objectRepresentation genSpecialSelectorEqualsEqualsGuts!
- 	nextPC := bytecodePC + primDescriptor numBytes.
- 	nExts := 0.
- 	[branchDescriptor := self generatorAt: (objectMemory fetchByte: nextPC ofObject: methodObj) + (byte0 bitAnd: 256).
- 	 branchDescriptor isExtension] whileTrue:
- 		[nExts := nExts + 1.
- 		 nextPC := nextPC + branchDescriptor numBytes].
- 	"If branching the stack must be flushed for the merge"
- 	(branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse]) ifTrue:
- 		[self ssFlushTo: simStackPtr - 2].
- 
- 	unforwardRcvr := (self ssValue: 1) type ~= SSConstant
- 						or: [objectRepresentation shouldAnnotateObjectReference: (self ssValue: 1) constant].
- 	unforwardArg := self ssTop type ~= SSConstant
- 						or: [objectRepresentation shouldAnnotateObjectReference: self ssTop constant].
- 
- 	"Don't use ReceiverResultReg for receiver to keep ReceiverResultReg live.
- 	 Optimize e.g. rcvr == nil, the common case for ifNil: et al."
- 	needsFrame
- 		ifTrue: 
- 			[unforwardArg ifTrue:
- 				[self ssAllocateRequiredReg: (argReg := Arg0Reg) upThrough: simStackPtr - 1].
- 			 self ssAllocateRequiredReg: (rcvrReg := Arg1Reg) upThrough: simStackPtr - 2]
- 		ifFalse:
- 			[unforwardArg ifTrue:
- 				[argReg := self ssAllocatePreferredReg: ClassReg].
- 			 rcvrReg := self ssAllocatePreferredReg: SendNumArgsReg].
- 	unforwardArg
- 		ifTrue:
- 			[self ssTop popToReg: argReg.
- 			 objectRepresentation genEnsureOopInRegNotForwarded: argReg scratchReg: TempReg.
- 			 (self ssValue: 1) popToReg: rcvrReg.
- 			 unforwardRcvr ifTrue:
- 				[objectRepresentation genEnsureOopInRegNotForwarded: rcvrReg scratchReg: TempReg].
- 			 self CmpR: argReg R: rcvrReg]
- 		ifFalse:
- 			[(self ssValue: 1) popToReg: rcvrReg.
- 			 unforwardRcvr ifTrue:
- 				[objectRepresentation genEnsureOopInRegNotForwarded: rcvrReg scratchReg: TempReg].
- 			 self CmpCq: self ssTop constant R: rcvrReg].
- 	self ssPop: 2.
- 
- 	"If not followed by a branch, resolve to true or false."
- 	(branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse]) ifFalse:
- 		[jumpNotEqual := self JumpNonZero: 0.
- 		 self annotate: (self MoveCw: objectMemory trueObject R: rcvrReg)
- 			objRef: objectMemory trueObject.
- 		 jumpEqual := self Jump: 0.
- 		 jumpNotEqual jmpTarget: (self annotate: (self MoveCw: objectMemory falseObject R: rcvrReg)
- 										objRef: objectMemory falseObject).
- 		 jumpEqual jmpTarget: self Label.
- 		 self ssPushRegister: rcvrReg.
- 		 ^0].
- 
- 	"Further since there is a following conditional jump bytecode, define
- 	 non-merge fixups and leave the cond bytecode to set the mergeness."
- 	targetBytecodePC := nextPC
- 							+ branchDescriptor numBytes
- 							+ (self spanFor: branchDescriptor at: nextPC exts: nExts in: methodObj).
- 	postBranchPC := nextPC + branchDescriptor numBytes.
- 	(self fixupAt: nextPC - initialPC) targetInstruction = 0
- 		ifTrue: "The next instruction is dead.  we can skip it."
- 			[deadCode := true.
- 		 	 self ensureFixupAt: targetBytecodePC - initialPC.
- 			 self ensureFixupAt: postBranchPC - initialPC]
- 		ifFalse:
- 			[self ssPushConstant: objectMemory trueObject]. "dummy value"
- 	self gen: (branchDescriptor isBranchTrue ifTrue: [JumpZero] ifFalse: [JumpNonZero])
- 		operand: (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger.
- 	self Jump: (self ensureNonMergeFixupAt: postBranchPC - initialPC).
- 	^0!

Item was added:
+ ----- Method: StackToRegisterMappingCogit>>genSpecialSelectorEqualsEqualsWithForwarders (in category 'bytecode generators') -----
+ genSpecialSelectorEqualsEqualsWithForwarders
+ 	| primDescriptor nextPC nExts branchDescriptor unforwardRcvr argReg targetBytecodePC
+ 	unforwardArg  rcvrReg jumpNotEqual jumpEqual postBranchPC label fixup |
+ 	<var: #jumpEqual type: #'AbstractInstruction *'>
+ 	<var: #jumpNotEqual type: #'AbstractInstruction *'>
+ 	<var: #primDescriptor type: #'BytecodeDescriptor *'>
+ 	<var: #branchDescriptor type: #'BytecodeDescriptor *'>
+ 	
+ 	primDescriptor := self generatorAt: byte0.
+ 
+ 	nextPC := bytecodePC + primDescriptor numBytes.
+ 	nExts := 0.
+ 	[branchDescriptor := self generatorAt: (objectMemory fetchByte: nextPC ofObject: methodObj) + (byte0 bitAnd: 256).
+ 	 branchDescriptor isExtension] whileTrue:
+ 		[nExts := nExts + 1.
+ 		 nextPC := nextPC + branchDescriptor numBytes].
+ 	"If branching the stack must be flushed for the merge"
+ 	(branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse]) ifTrue:
+ 		[self ssFlushTo: simStackPtr - 2].
+ 
+ 	unforwardRcvr := (objectRepresentation isUnannotatableConstant: (self ssValue: 1)) not.
+ 	unforwardArg := (objectRepresentation isUnannotatableConstant: self ssTop) not.
+ 
+ 	"if the rcvr or the arg is an annotable constant, we need to push it to a register 
+ 	else the forwarder check can't jump back to the comparison after unforwarding the constant"
+ 	unforwardArg
+ 		ifTrue: 
+ 			[unforwardRcvr
+ 				ifTrue:
+ 					[self allocateTwoRegistersInto: [:rTop :rNext| argReg := rTop. rcvrReg := rNext].
+ 					 self ssTop popToReg: argReg.
+ 					 (self ssValue:1) popToReg: rcvrReg]
+ 				ifFalse:
+ 					[argReg := self allocateOneRegister.
+ 					 self ssTop popToReg: argReg]]
+ 		ifFalse:
+ 			[self assert: unforwardRcvr.
+ 			 rcvrReg := self allocateOneRegister.
+ 			 (self ssValue:1) popToReg: rcvrReg].
+ 
+ 	label := self Label.
+ 	
+ 	"Here we can use Cq because the constant does not need to be annotated"
+ 	self assert: (unforwardArg not or: [argReg notNil]).
+ 	self assert: (unforwardRcvr not or: [rcvrReg notNil]).
+ 	unforwardArg 
+ 		ifFalse: [ self CmpCq: self ssTop constant R: rcvrReg ]
+ 		ifTrue: [ unforwardRcvr
+ 			ifFalse: [ self CmpCq: (self ssValue: 1) constant R: argReg ]
+ 			ifTrue: [ self CmpR: argReg R: rcvrReg ] ].
+ 			 
+ 	self ssPop: 2.
+ 
+ 	"If not followed by a branch, resolve to true or false."
+ 	(branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse]) ifFalse:
+ 		[jumpEqual := self JumpZero: 0.
+ 		 unforwardArg ifTrue: [ objectRepresentation genEnsureOopInRegNotForwarded: argReg scratchReg: TempReg jumpBackTo: label ].
+ 		 unforwardRcvr ifTrue: [ objectRepresentation genEnsureOopInRegNotForwarded: rcvrReg scratchReg: TempReg jumpBackTo: label ].
+ 		 self genMoveFalseR: rcvrReg.
+ 		 jumpNotEqual := self Jump: 0.
+ 		 jumpEqual jmpTarget: (self genMoveTrueR: rcvrReg).
+ 		 jumpNotEqual jmpTarget: self Label.
+ 		 self ssPushRegister: rcvrReg.
+ 		 ^0].
+ 
+ 	"Further since there is a following conditional jump bytecode, define
+ 	 non-merge fixups and leave the cond bytecode to set the mergeness."
+ 	targetBytecodePC := nextPC
+ 							+ branchDescriptor numBytes
+ 							+ (self spanFor: branchDescriptor at: nextPC exts: nExts in: methodObj).
+ 	postBranchPC := nextPC + branchDescriptor numBytes.
+ 	(self fixupAt: nextPC - initialPC) targetInstruction = 0
+ 		ifTrue: "The next instruction is dead.  we can skip it."
+ 			[deadCode := true.
+ 		 	 self ensureFixupAt: targetBytecodePC - initialPC.
+ 			 self ensureFixupAt: postBranchPC - initialPC]
+ 		ifFalse:
+ 			[self ssPushConstant: objectMemory trueObject]. "dummy value"
+ 
+ 	self assert: (unforwardArg or: [ unforwardRcvr ]).
+ 	branchDescriptor isBranchTrue ifTrue: 
+ 		[ deadCode ifFalse: [ fixup := self ensureNonMergeFixupAt: postBranchPC - initialPC ].
+ 		self JumpZero:  (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger.
+ 		unforwardArg ifTrue: [ (deadCode or: [ unforwardRcvr ]) 
+ 			ifTrue: [ objectRepresentation genEnsureOopInRegNotForwarded: argReg scratchReg: TempReg jumpBackTo: label ]
+ 			ifFalse: [ objectRepresentation 
+ 				genEnsureOopInRegNotForwarded: argReg 
+ 				scratchReg: TempReg 
+ 				ifForwarder: label
+ 				ifNotForwarder: fixup ] ].
+ 		unforwardRcvr ifTrue: [ deadCode 
+ 			ifTrue: [objectRepresentation genEnsureOopInRegNotForwarded: rcvrReg scratchReg: TempReg jumpBackTo: label ]
+ 			ifFalse: [objectRepresentation 
+ 				genEnsureOopInRegNotForwarded: rcvrReg 
+ 				scratchReg: TempReg 
+ 				ifForwarder: label
+ 				ifNotForwarder: fixup ] ] ].
+ 	branchDescriptor isBranchFalse ifTrue: 
+ 		[ fixup := (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger.
+ 		self JumpZero: (self ensureNonMergeFixupAt: postBranchPC - initialPC).
+ 		unforwardArg ifTrue: [ unforwardRcvr 
+ 			ifFalse: [objectRepresentation 
+ 				genEnsureOopInRegNotForwarded: argReg 
+ 				scratchReg: TempReg 
+ 				ifForwarder: label
+ 				ifNotForwarder: fixup ]
+ 			ifTrue: [ objectRepresentation genEnsureOopInRegNotForwarded: rcvrReg scratchReg: TempReg jumpBackTo: label ] ].
+ 		unforwardRcvr ifTrue: 
+ 			[ objectRepresentation 
+ 				genEnsureOopInRegNotForwarded: rcvrReg 
+ 				scratchReg: TempReg 
+ 				ifForwarder: label
+ 				ifNotForwarder: fixup ].
+ 		"Not reached"].
+ 	^0!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genStorePop:LiteralVariable: (in category 'bytecode generator support') -----
  genStorePop: popBoolean LiteralVariable: litVarIndex
  	<inline: false>
  	| topReg valueReg association constVal |
  	self flag: 'with better register allocation this wouldn''t need a frame.  e.g. use SendNumArgs instead of ReceiverResultReg'.
  	self assert: needsFrame.
  	optStatus isReceiverResultRegLive: false.
  	"N.B.  No need to check the stack for references because we generate code for
  	 literal variable loads that stores the result in a register, deferring only the register push."
  	association := self getLiteral: litVarIndex.
  	constVal := self ssTop maybeConstant.
  	"Avoid store check for immediate values"
  	(self ssTop type = SSConstant
  	 and: [(objectRepresentation shouldAnnotateObjectReference: constVal) not]) ifTrue:
  		[self ssAllocateRequiredReg: ReceiverResultReg.
+ 		self genMoveConstant: association R: ReceiverResultReg.
- 		 self annotate: (self MoveCw: association R: ReceiverResultReg) objRef: association.
  		 objectRepresentation
  			genEnsureObjInRegNotForwarded: ReceiverResultReg
  			scratchReg: TempReg.
  		 self ssStorePop: popBoolean toPreferredReg: TempReg.
  		 traceStores > 0 ifTrue:
  			[self CallRT: ceTraceStoreTrampoline].
  		 ^objectRepresentation
  			genStoreImmediateInSourceReg: TempReg
  			slotIndex: ValueIndex
  			destReg: ReceiverResultReg].
  	((topReg := self ssTop registerOrNil) isNil
  	 or: [topReg = ReceiverResultReg]) ifTrue:
  		[topReg := ClassReg].
  	self ssPop: 1.
  	self ssAllocateCallReg: topReg. "for the ceStoreCheck call in genStoreSourceReg:... below"
  	self ssPush: 1.
  	valueReg := self ssStorePop: popBoolean toPreferredReg: topReg.
  	valueReg = ReceiverResultReg ifTrue:
  		[self MoveR: valueReg R: topReg].
  	self ssAllocateCallReg: ReceiverResultReg.
  	self annotate: (self MoveCw: association R: ReceiverResultReg) objRef: association.
  	objectRepresentation genEnsureObjInRegNotForwarded: ReceiverResultReg scratchReg: TempReg.
  	traceStores > 0 ifTrue:
  		[self MoveR: topReg R: TempReg.
  		 self CallRT: ceTraceStoreTrampoline].
  	^objectRepresentation
  		genStoreSourceReg: topReg
  		slotIndex: ValueIndex
  		destReg: ReceiverResultReg
  		scratchReg: TempReg
  		inFrame: needsFrame!

Item was added:
+ ----- Method: StackToRegisterMappingCogit>>genVanillaSpecialSelectorEqualsEquals (in category 'bytecode generators') -----
+ genVanillaSpecialSelectorEqualsEquals
+ 	| nextPC postBranchPC targetBytecodePC primDescriptor branchDescriptor nExts
+ 	  jumpEqual jumpNotEqual rcvrReg argReg argIsConstant rcvrIsConstant  |
+ 	<var: #jumpEqual type: #'AbstractInstruction *'>
+ 	<var: #jumpNotEqual type: #'AbstractInstruction *'>
+ 	<var: #primDescriptor type: #'BytecodeDescriptor *'>
+ 	<var: #branchDescriptor type: #'BytecodeDescriptor *'>
+ 	primDescriptor := self generatorAt: byte0.
+ 
+ 	nextPC := bytecodePC + primDescriptor numBytes.
+ 	nExts := 0.
+ 	[branchDescriptor := self generatorAt: (objectMemory fetchByte: nextPC ofObject: methodObj) + bytecodeSetOffset.
+ 	 branchDescriptor isExtension] whileTrue:
+ 		[nExts := nExts + 1.
+ 		 nextPC := nextPC + branchDescriptor numBytes].
+ 	"If branching the stack must be flushed for the merge"
+ 	(branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse]) ifTrue:
+ 		[self ssFlushTo: simStackPtr - 2].
+ 
+ 	"Don't use ReceiverResultReg for receiver to keep ReceiverResultReg live.
+ 	 Optimize e.g. rcvr == nil, the common case for ifNil: et al."
+ 	
+ 	argIsConstant := self ssTop type = SSConstant.
+ 	rcvrIsConstant := argIsConstant and: [ (self ssValue:1) type = SSConstant ].
+ 	
+ 	needsFrame "If frameless, arg0 and arg1 may be live"
+ 		ifTrue: [argReg := Arg0Reg. rcvrReg := Arg1Reg]
+ 		ifFalse: [argReg := ClassReg. rcvrReg := SendNumArgsReg].
+ 	argIsConstant ifFalse: 
+ 		[self ssAllocateRequiredReg: argReg upThrough: simStackPtr - 1.
+ 		self ssTop popToReg: argReg].
+ 	rcvrIsConstant ifFalse: 
+ 		[ self ssAllocateRequiredReg: rcvrReg upThrough: simStackPtr - 2.
+ 		(self ssValue:1) popToReg: rcvrReg.].
+ 	
+ 	argIsConstant 
+ 		ifTrue: [ self genCompConstant: self ssTop constant R: rcvrReg ]
+ 		ifFalse: [ rcvrIsConstant
+ 			ifTrue: [ self genCompConstant: (self ssValue: 1) constant R: argReg ]
+ 			ifFalse: [ self CmpR: argReg R: rcvrReg ] ].
+ 		
+ 	self ssPop: 2.
+ 
+ 	"If not followed by a branch, resolve to true or false."
+ 	(branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse]) ifFalse:
+ 		[jumpNotEqual := self JumpNonZero: 0.
+ 		 self genMoveTrueR: rcvrReg.
+ 		 jumpEqual := self Jump: 0.
+ 		 jumpNotEqual jmpTarget: (self genMoveFalseR: rcvrReg).
+ 		 jumpEqual jmpTarget: self Label.
+ 		 self ssPushRegister: rcvrReg.
+ 		 ^0].
+ 
+ 	"Further since there is a following conditional jump bytecode, define
+ 	 non-merge fixups and leave the cond bytecode to set the mergeness."
+ 	targetBytecodePC := nextPC
+ 							+ branchDescriptor numBytes
+ 							+ (self spanFor: branchDescriptor at: nextPC exts: nExts in: methodObj).
+ 	postBranchPC := nextPC + branchDescriptor numBytes.
+ 	(self fixupAt: nextPC - initialPC) targetInstruction = 0
+ 		ifTrue: "The next instruction is dead.  we can skip it."
+ 			[deadCode := true.
+ 		 	 self ensureFixupAt: targetBytecodePC - initialPC.
+ 			 self ensureFixupAt: postBranchPC - initialPC]
+ 		ifFalse:
+ 			[self ssPushConstant: objectMemory trueObject]. "dummy value"
+ 	self gen: (branchDescriptor isBranchTrue ifTrue: [JumpZero] ifFalse: [JumpNonZero])
+ 		operand: (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger.
+ 		deadCode ifFalse: [self Jump: (self ensureNonMergeFixupAt: postBranchPC - initialPC)].
+ 	^0!

Item was changed:
  ----- Method: VMMaker class>>generateAllSqueakConfigurationsUnderVersionControl (in category 'configurations') -----
  generateAllSqueakConfigurationsUnderVersionControl
  	self generateSqueakCogVM;
  		generateSqueakCogMTVM;
  		generateSqueakSpurCogVM;
- 		generateSqueakCogSistaVM;
  		generateSqueakSpurCogSistaVM
  !



More information about the Vm-dev mailing list