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

commits at source.squeak.org commits at source.squeak.org
Thu Apr 16 17:53:54 UTC 2015


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

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

Name: VMMaker.oscog-eem.1200
Author: eem
Time: 16 April 2015, 10:52:10.154 am
UUID: ceecee7e-aaa2-408c-a876-f346805fbdb2
Ancestors: VMMaker.oscog-eem.1199

Refactor the slot store and store check machinery
to take an inFrame: argument and hence deal with
the store check in genInnerPrimitiveAtPut: on ARM.

Implement jumpLong[Conditional]ByteSize for ARM
noting that this is unsatisfactory.  We need to
generate "short" branches on ARM for PICs.

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

Item was added:
+ ----- Method: CogARMCompiler>>jumpLongByteSize (in category 'accessing') -----
+ jumpLongByteSize
+ 	self flag: 'for the moment the Cogit understands only a Jump vs JumpLong distinction where JumpLong spans the 32-bit address space.  But this leads to 20-byte branches.  What we need to distingush between is variable sized jumps ("short" jumps, which is what Jump means now), fixed size jumops within the code zone and fixed size jumps within the 32-bit address space.'.
+ 	^20!

Item was added:
+ ----- Method: CogARMCompiler>>jumpLongConditionalByteSize (in category 'accessing') -----
+ jumpLongConditionalByteSize
+ 	^self jumpLongByteSize!

Item was changed:
  ----- Method: CogObjectRepresentationFor32BitSpur>>genGetActiveContextLarge:inBlock: (in category 'initialization') -----
  genGetActiveContextLarge: isLarge inBlock: isInBlock
  	"Create a trampoline to answer the active context that will
  	 answer it if a frame is already married, and create it otherwise.
  	 Assume numArgs is in SendNumArgsReg and ClassReg is free."
  	| header slotSize jumpSingle loopHead jumpNeedScavenge continuation exit |
  	<var: #jumpNeedScavenge type: #'AbstractInstruction *'>
  	<var: #continuation type: #'AbstractInstruction *'>
  	<var: #jumpSingle type: #'AbstractInstruction *'>
  	<var: #loopHead type: #'AbstractInstruction *'>
  	<var: #exit type: #'AbstractInstruction *'>
  	cogit "load the flag; stash it in both TempReg & ClassReg; do the compare (a prime candidated for use of AndCq:R:R:)"
  		MoveMw: FoxMethod r: FPReg R: ClassReg;
  		AndCq: MFMethodFlagHasContextFlag R: ClassReg R: TempReg.
  	jumpSingle := cogit JumpZero: 0. "jump if flag bit not set"
  	cogit "since the flag bit was set, get the context in the receiver reg and return"
  		MoveMw: FoxThisContext r: FPReg R: ReceiverResultReg;
  		RetN: 0.
  	jumpSingle jmpTarget: cogit Label.
  
  	"OK, it doesn't exist; instantiate and initialize it"
  	"set the hasContext flag; See CoInterpreter class>>initializeFrameIndices"
  	cogit
  		OrCq: MFMethodFlagHasContextFlag R: ClassReg;
  		MoveR: ClassReg Mw: FoxMethod r: FPReg.
  	"now get the home CogMethod into ClassReg and save for post-instantiation."
  	isInBlock
  		ifTrue:
  			[cogit
  				SubCq: 3 R: ClassReg; "-3 is -(hasContext+isBlock) flags"
  				MoveM16: 0 r: ClassReg R: TempReg;
  				SubR: TempReg R: ClassReg]
  		ifFalse:
  			[cogit SubCq: 1 R: ClassReg]. "-1 is hasContext flag"
  
  	"instantiate the context..."
  	slotSize := isLarge ifTrue: [LargeContextSlots] ifFalse: [SmallContextSlots].
  	header := objectMemory
  					headerForSlots: slotSize
  					format: objectMemory indexablePointersFormat
  					classIndex: ClassMethodContextCompactIndex.
  	self flag: #endianness.
  	cogit
  		MoveAw: objectMemory freeStartAddress R: ReceiverResultReg;
  		MoveCq: (self low32BitsOf: header) R: TempReg;
  		MoveR: TempReg Mw: 0 r: ReceiverResultReg;
  		MoveCq: header >> 32 R: TempReg;
  		MoveR: TempReg Mw: 4 r: ReceiverResultReg;
  		MoveR: ReceiverResultReg R: TempReg;
  		AddCq: (objectMemory smallObjectBytesForSlots: slotSize) R: TempReg;
  		MoveR: TempReg Aw: objectMemory freeStartAddress;
  		CmpCq: objectMemory getScavengeThreshold R: TempReg.
  	jumpNeedScavenge := cogit JumpAboveOrEqual: 0.
  
  	"Now initialize the fields of the context.  See CoInterpreter>>marryFrame:SP:copyTemps:"
  	"sender gets frame pointer as a SmallInteger"
  	continuation :=
  	cogit MoveR: FPReg R: TempReg.
  	self genSetSmallIntegerTagsIn: TempReg.
  	cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (SenderIndex * objectMemory bytesPerOop) r: ReceiverResultReg.
  
  	"pc gets frame caller as a SmallInteger"
  	cogit MoveMw: FoxSavedFP r: FPReg R: TempReg.
  	self genSetSmallIntegerTagsIn: TempReg.
  	cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (InstructionPointerIndex * objectMemory bytesPerOop) r: ReceiverResultReg.
  
  	"Set the method field, freeing up ClassReg again, and frame's context field,"
  	cogit
  		MoveMw: (cogit offset: CogMethod of: #methodObject) r: ClassReg R: TempReg;
  		MoveR: TempReg Mw: objectMemory baseHeaderSize + (MethodIndex * objectMemory wordSize) r: ReceiverResultReg;
  		MoveR: ReceiverResultReg Mw: FoxThisContext r: FPReg.
  
  	"Now compute stack pointer; this is stackPointer (- 1 for return pc if a CISC) - framePointer - 4 (1 each for saved pc, method, context, receiver) + 1 (1-relative) + numArgs"
  	"TPR note - the code here is actually doing
  	context stackPointer := ((((fp - sp) / 4) - [3|4]) + num args) asSmallInteger"
  	cogit
  		MoveR: FPReg R: TempReg;
  		SubR: SPReg R: TempReg;
  		LogicalShiftRightCq: self log2BytesPerWord R: TempReg;
  		SubCq: (cogit backEnd hasLinkRegister ifTrue: [3] ifFalse: [4]) R: TempReg;
  		AddR: SendNumArgsReg R: TempReg.
  	self genConvertIntegerToSmallIntegerInReg: TempReg.
  	cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (StackPointerIndex * objectMemory bytesPerOop) r: ReceiverResultReg.
  
  	"Set closureOrNil to either the stacked receiver or nil"
  	isInBlock
  		ifTrue:
  			[cogit
  				MoveR: SendNumArgsReg R: TempReg;
  				AddCq: 2 R: TempReg; "+2 for saved fp and saved pc"
  				MoveXwr: TempReg R: FPReg R: TempReg]
  		ifFalse:
  			[cogit MoveCw: objectMemory nilObject R: TempReg].
  	cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (ClosureIndex * objectMemory bytesPerOop) r: ReceiverResultReg.
  
  	"Set the receiver"
  	cogit
  		MoveMw: FoxMFReceiver r: FPReg R: TempReg;
  		MoveR: TempReg Mw: objectMemory baseHeaderSize + (ReceiverIndex * objectMemory bytesPerOop) r: ReceiverResultReg.
  
  	"Now copy the arguments.  This is tricky because of the shortage of registers,.  ClassReg ranges
  	 from 1 to numArgs (SendNumArgsReg), and from ReceiverIndex + 1 to ReceiverIndex + numArgs.
  	 1 to: numArgs do:
  		[:i|
  		temp := longAt(FPReg + ((SendNumArgs - i + 2) * BytesPerWord)). +2 for saved pc and savedfp
  		longAtput(FPReg + FoxMFReceiver + (i * BytesPerWord), temp)]"
  	"TPR note: this is a prime candidate for passing off to the backend to do at least faintly optimal code"
  	cogit MoveCq: 1 R: ClassReg.
  	loopHead := cogit CmpR: SendNumArgsReg R: ClassReg.
  	exit := cogit JumpGreater: 0.
  	cogit
  		MoveR: SendNumArgsReg R: TempReg;
  		SubR: ClassReg R: TempReg;
  		AddCq: 2 R: TempReg; "+2 for saved fp and saved pc"
  		MoveXwr: TempReg R: FPReg R: TempReg;
  		AddCq: ReceiverIndex + (objectMemory baseHeaderSize / objectMemory wordSize) R: ClassReg; "Now convert ClassReg from frame index to context index"
  		MoveR: TempReg Xwr: ClassReg R: ReceiverResultReg;
  		SubCq: ReceiverIndex + (objectMemory baseHeaderSize / objectMemory wordSize) - 1 R: ClassReg; "convert back adding 1 ;-)"
  		Jump: loopHead.
  	exit jmpTarget: cogit Label.
  
  	"Finally nil or copy the non-argument temps.
  	 ClassReg := FPReg + FoxMFReceiver.
  	 SendNumArgsReg := SendNumArgsReg+ReceiverIndex.
  	 [ClassReg := ClassReg - 4.
  	  backEnd hasLinkRegister
  			ifTrue: [ClassReg > SPReg]
  			ifFalse: [ClassReg >= SPReg]] whileTrue:
  		[receiver[SendNumArgsReg] := *ClassReg.
  		 SendNumArgsReg := SendNumArgsReg + 1]]"
  	coInterpreter marryFrameCopiesTemps ifFalse:
  		[cogit MoveCq: objectMemory nilObject R: TempReg].
+ 	"Could usefully use AddCq:R:R:"
  	cogit
  		MoveR: FPReg R: ClassReg;
  		AddCq: FoxMFReceiver R: ClassReg;
  		AddCq: ReceiverIndex + 1 + (objectMemory baseHeaderSize / objectMemory wordSize) R: SendNumArgsReg.
  	loopHead :=
  	cogit SubCq: objectMemory wordSize R: ClassReg.
  	cogit CmpR: SPReg R: ClassReg.
  	"If on a CISC there's a retpc for the trampoline call on top of stack; if on a RISC there isn't."
  	exit := cogit backEnd hasLinkRegister
+ 				ifTrue: [cogit JumpBelow: 0]
+ 				ifFalse: [cogit JumpBelowOrEqual: 0].
- 				ifTrue: [cogit JumpBelowOrEqual: 0]
- 				ifFalse: [cogit JumpBelow: 0].
  	coInterpreter marryFrameCopiesTemps ifTrue:
  		[cogit MoveMw: 0 r: ClassReg R: TempReg].
  	cogit
  		MoveR: TempReg Xwr: SendNumArgsReg R: ReceiverResultReg;
  		AddCq: 1 R: SendNumArgsReg;
  		Jump: loopHead.
  	exit jmpTarget: cogit Label.
  
  	cogit RetN: 0.
  	
  	jumpNeedScavenge jmpTarget:
  		(cogit backEnd saveAndRestoreLinkRegAround: [cogit CallRT: ceScheduleScavengeTrampoline]). "We need to push the LR here for ARM, and pop it back after the callRT:"
  	cogit Jump: continuation.
  	^0!

Item was changed:
  ----- Method: CogObjectRepresentationFor32BitSpur>>genInnerPrimitiveAtPut: (in category 'primitive generators') -----
  genInnerPrimitiveAtPut: retNoffset
  	"Implement the guts of primitiveAtPut"
  	| formatReg jumpImmediate jumpBadIndex
  	  jumpNotIndexablePointers jumpNotIndexableBits
  	  jumpIsContext jumpIsCompiledMethod jumpIsBytes jumpHasFixedFields
  	  jumpArrayOutOfBounds jumpFixedFieldsOutOfBounds
  	  jumpWordsOutOfBounds jumpBytesOutOfBounds jumpBytesOutOfRange
  	  jumpNonSmallIntegerValue jumpShortsUnsupported jumpNotPointers
  	  |
  	<inline: true>
  	"c.f. StackInterpreter>>stSizeOf: SpurMemoryManager>>lengthOf:format: fixedFieldsOf:format:length:"
  	<var: #jumpIsBytes type: #'AbstractInstruction *'>
  	<var: #jumpBadIndex type: #'AbstractInstruction *'>
  	<var: #jumpIsContext type: #'AbstractInstruction *'>
  	<var: #jumpImmediate type: #'AbstractInstruction *'>
  	<var: #jumpHasFixedFields type: #'AbstractInstruction *'>
  	<var: #jumpNotIndexableBits type: #'AbstractInstruction *'>
  	<var: #jumpArrayOutOfBounds type: #'AbstractInstruction *'>
  	<var: #jumpBytesOutOfBounds type: #'AbstractInstruction *'>
  	<var: #jumpShortsUnsupported type: #'AbstractInstruction *'>
  	<var: #jumpWordsOutOfBounds type: #'AbstractInstruction *'>
  	<var: #jumpNotIndexablePointers type: #'AbstractInstruction *'>
  
  	cogit MoveR: ReceiverResultReg R: TempReg.
  	jumpImmediate := self genJumpImmediateInScratchReg: TempReg.
  	cogit MoveR: Arg0Reg R: TempReg.
  	jumpBadIndex := self genJumpNotSmallIntegerInScratchReg: TempReg.
  	self genConvertSmallIntegerToIntegerInReg: Arg0Reg.
  	cogit SubCq: 1 R: Arg0Reg. "1-rel => 0-rel"
  
  	"formatReg := self formatOf: ReceiverResultReg"
  	self genGetFormatOf: ReceiverResultReg
  		into: (formatReg := SendNumArgsReg)
  		leastSignificantHalfOfBaseHeaderIntoScratch: nil.
  
  	self genGetNumSlotsOf: ReceiverResultReg into: ClassReg.
  
  	"dispatch on format in a combination of highest dynamic frequency order first and convenience.
  		  0 = 0 sized objects (UndefinedObject True False et al)
  		  1 = non-indexable objects with inst vars (Point et al)
  		  2 = indexable objects with no inst vars (Array et al)
  		  3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al)
  		  4 = weak indexable objects with inst vars (WeakArray et al)
  		  5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron)
  		  6 unused, reserved for exotic pointer objects?
  		  7 Forwarded Object, 1st field is pointer, rest of fields are ignored
  		  8 unused, reserved for exotic non-pointer objects?
  		  9 (?) 64-bit indexable
  		10 - 11 32-bit indexable
  		12 - 15 16-bit indexable
  		16 - 23 byte indexable
  		24 - 31 compiled method"
  	cogit CmpCq: objectMemory weakArrayFormat R: formatReg.
  	jumpNotPointers := cogit JumpAbove: 0.
  	"optimistic store check; assume index in range (almost always is)."
+ 	self genStoreCheckReceiverReg: ReceiverResultReg
+ 		valueReg: Arg1Reg
+ 		scratchReg: TempReg
+ 		inFrame: false.
- 	self genStoreCheckReceiverReg: ReceiverResultReg valueReg: Arg1Reg scratchReg: TempReg.
  
  	cogit CmpCq: objectMemory arrayFormat R: formatReg.
  	jumpNotIndexablePointers := cogit JumpBelow: 0.
  	jumpHasFixedFields := cogit JumpNonZero: 0.
  	cogit CmpR: Arg0Reg R: ClassReg.
  	jumpArrayOutOfBounds := cogit JumpBelowOrEqual: 0.
  	cogit AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: Arg0Reg.
  	cogit MoveR: Arg1Reg Xwr: Arg0Reg R: ReceiverResultReg.
  	cogit MoveR: Arg1Reg R: ReceiverResultReg.
  	cogit RetN: retNoffset.
  
  	jumpHasFixedFields jmpTarget: cogit Label.
  	self genGetClassIndexOfNonImm: ReceiverResultReg into: formatReg.
  	cogit CmpCq: ClassMethodContextCompactIndex R: formatReg.
  	jumpIsContext := cogit JumpZero: 0.
  	"get # fixed fields in formatReg"
  	cogit PushR: ClassReg.
  	self genGetClassObjectOfClassIndex: formatReg into: ClassReg scratchReg: TempReg.
  	self genLoadSlot: InstanceSpecificationIndex sourceReg: ClassReg destReg: formatReg.
  	cogit PopR: ClassReg.
  	self genConvertSmallIntegerToIntegerInReg: formatReg.
  	cogit AndCq: objectMemory fixedFieldsOfClassFormatMask R: formatReg.
  	cogit SubR: formatReg R: ClassReg.
  	cogit AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: formatReg.
  	cogit CmpR: Arg0Reg R: ClassReg.
  	jumpFixedFieldsOutOfBounds := cogit JumpBelowOrEqual: 0.
  	cogit AddR: formatReg R: Arg0Reg.
  	cogit MoveR: Arg1Reg Xwr: Arg0Reg R: ReceiverResultReg.
  	cogit MoveR: Arg1Reg R: ReceiverResultReg.
  	cogit RetN: retNoffset.
  
  	jumpNotPointers jmpTarget:
  		(cogit CmpCq: objectMemory firstCompiledMethodFormat R: formatReg).
  	jumpIsCompiledMethod := cogit JumpAboveOrEqual: 0.
  	cogit MoveR: Arg1Reg R: TempReg.
  	jumpNonSmallIntegerValue := self genJumpNotSmallIntegerInScratchReg: TempReg.
  					cogit CmpCq: objectMemory firstByteFormat R: formatReg.
  	jumpIsBytes := cogit JumpAboveOrEqual: 0.
  					cogit CmpCq: objectMemory firstShortFormat R: formatReg.
  	jumpShortsUnsupported := cogit JumpAboveOrEqual: 0.
  					cogit CmpCq: objectMemory firstLongFormat R: formatReg.
  	"For now ignore 64-bit indexability."
  	jumpNotIndexableBits := cogit JumpBelow: 0.
  
  	cogit CmpR: Arg0Reg R: ClassReg.
  	jumpWordsOutOfBounds := cogit JumpBelowOrEqual: 0.
  	cogit MoveR: Arg1Reg R: TempReg.
  	self genConvertSmallIntegerToIntegerInReg: TempReg.
  	cogit AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: Arg0Reg.
  	cogit MoveR: TempReg Xwr: Arg0Reg R: ReceiverResultReg.
  	cogit MoveR: Arg1Reg R: ReceiverResultReg.
  	cogit RetN: retNoffset.
  
  	jumpIsBytes jmpTarget:
  		(cogit CmpCq: (objectMemory integerObjectOf: 255) R: Arg1Reg).
  	jumpBytesOutOfRange := cogit JumpAbove: 0.
  	cogit LogicalShiftLeftCq: objectMemory shiftForWord R: ClassReg.
  	cogit AndCq: objectMemory wordSize - 1 R: formatReg.
  	cogit SubR: formatReg R: ClassReg;
  	CmpR: Arg0Reg R: ClassReg.
  	jumpBytesOutOfBounds := cogit JumpBelowOrEqual: 0.
  	cogit MoveR: Arg1Reg R: TempReg.
  	self genConvertSmallIntegerToIntegerInReg: TempReg.
  	cogit AddCq: objectMemory baseHeaderSize R: Arg0Reg.
  	cogit MoveR: TempReg Xbr: Arg0Reg R: ReceiverResultReg.
  	cogit MoveR: Arg1Reg R: ReceiverResultReg.
  	cogit RetN: retNoffset.
  
  	"there are no shorts as yet.  so this is dead code:
  	jumpIsShorts jmpTarget:
  		(cogit CmpCq: (objectMemory integerObjectOf: 65535) R: Arg1Reg).
  	jumpShortsOutOfRange := cogit JumpAbove: 0.
  	cogit LogicalShiftLeftCq: objectMemory shiftForWord - 1 R: ClassReg.
  	cogit AndCq: 1 R: formatReg.
  	cogit SubR: formatReg R: ClassReg;
  	CmpR: Arg0Reg R: ClassReg.
  	jumpShortsOutOfBounds := cogit JumpBelowOrEqual: 0.
  	cogit MoveR: Arg1Reg R: TempReg.
  	cogit genConvertSmallIntegerToIntegerInReg: TempReg.
  	cogit AddR: Arg0Reg R: ReceiverResultReg.
  	cogit MoveR: TempReg M16: objectMemory baseHeaderSize r: ReceiverResultReg.
  	cogit MoveR: Arg1Reg R: ReceiverResultReg.
  	jumpShortsDone := cogit Jump: 0."
  
  	jumpIsContext jmpTarget: 
  	(jumpNotIndexableBits jmpTarget:
  	(jumpBytesOutOfRange jmpTarget:
  	(jumpIsCompiledMethod jmpTarget:
  	(jumpArrayOutOfBounds jmpTarget:
  	(jumpBytesOutOfBounds jmpTarget:
  	(jumpShortsUnsupported jmpTarget:
  	(jumpWordsOutOfBounds jmpTarget:
  	(jumpNotIndexablePointers jmpTarget:
  	(jumpNonSmallIntegerValue jmpTarget:
  	(jumpFixedFieldsOutOfBounds jmpTarget: cogit Label)))))))))).
  
  	cogit AddCq: 1 R: Arg0Reg. "0-rel => 1-rel"
  	self genConvertIntegerToSmallIntegerInReg: Arg0Reg.
  
  	jumpBadIndex jmpTarget: (jumpImmediate jmpTarget: cogit Label).
  
  	^0!

Item was removed:
- ----- Method: CogObjectRepresentationForSpur>>genStoreCheckReceiverReg:valueReg:scratchReg: (in category 'compile abstract instructions') -----
- genStoreCheckReceiverReg: destReg valueReg: valueReg scratchReg: scratchReg
- 	"Generate the code for a store check of valueReg into destReg."
- 	| jmpImmediate jmpDestYoung jmpSourceOld jmpAlreadyRemembered mask rememberedBitByteOffset |
- 	<var: #jmpImmediate type: #'AbstractInstruction *'>
- 	<var: #jmpDestYoung type: #'AbstractInstruction *'>
- 	<var: #jmpSourceOld type: #'AbstractInstruction *'>
- 	<var: #jmpAlreadyRemembered type: #'AbstractInstruction *'>
- 	"Is value stored an integer?  If so we're done"
- 	cogit MoveR: valueReg R: scratchReg.
- 	cogit AndCq: objectMemory tagMask R: scratchReg.
- 	jmpImmediate := cogit JumpNonZero: 0.
- 	"Get the old/new boundary in scratchReg"
- 	cogit MoveCw: objectMemory storeCheckBoundary R: scratchReg.
- 	"Is target young?  If so we're done"
- 	cogit CmpR: scratchReg R: destReg. "N.B. FLAGS := destReg - scratchReg"
- 	jmpDestYoung := cogit JumpBelow: 0.
- 	"Is value stored old?  If so we're done."
- 	cogit CmpR: scratchReg R: valueReg. "N.B. FLAGS := valueReg - scratchReg"
- 	jmpSourceOld := cogit JumpAboveOrEqual: 0.
- 	"value is young and target is old.
- 	 Need to remember this only if the remembered bit is not already set.
- 	 Test the remembered bit.  Only need to fetch the byte containing it,
- 	 which reduces the size of the mask constant."
- 	rememberedBitByteOffset := jmpSourceOld isBigEndian
- 									ifTrue: [objectMemory baseHeaderSize - 1 - (objectMemory rememberedBitShift // 8)]
- 									ifFalse:[objectMemory rememberedBitShift // 8].
- 	mask := 1 << (objectMemory rememberedBitShift \\ 8).
- 	cogit MoveMb: rememberedBitByteOffset r: destReg R: scratchReg.
- 	cogit AndCq: mask R: scratchReg.
- 	jmpAlreadyRemembered := cogit JumpNonZero: 0.
- 	"Remembered bit is not set.  Call store check to insert dest into remembered table."
- 	self assert: destReg == ReceiverResultReg.
- 	cogit
- 		CallRT: ceStoreCheckTrampoline
- 		registersToBeSavedMask: (((cogit registerMaskFor: valueReg)
- 										bitOr: cogit callerSavedRegMask)
- 										bitClear: (cogit registerMaskFor: ReceiverResultReg)).
- 	jmpImmediate jmpTarget:
- 	(jmpDestYoung jmpTarget:
- 	(jmpSourceOld jmpTarget:
- 	(jmpAlreadyRemembered jmpTarget:
- 		cogit Label))).
- 	^0!

Item was added:
+ ----- Method: CogObjectRepresentationForSpur>>genStoreCheckReceiverReg:valueReg:scratchReg:inFrame: (in category 'compile abstract instructions') -----
+ genStoreCheckReceiverReg: destReg valueReg: valueReg scratchReg: scratchReg inFrame: inFrame
+ 	"Generate the code for a store check of valueReg into destReg."
+ 	| jmpImmediate jmpDestYoung jmpSourceOld jmpAlreadyRemembered mask rememberedBitByteOffset |
+ 	<var: #jmpImmediate type: #'AbstractInstruction *'>
+ 	<var: #jmpDestYoung type: #'AbstractInstruction *'>
+ 	<var: #jmpSourceOld type: #'AbstractInstruction *'>
+ 	<var: #jmpAlreadyRemembered type: #'AbstractInstruction *'>
+ 	"Is value stored an integer?  If so we're done"
+ 	cogit MoveR: valueReg R: scratchReg.
+ 	cogit AndCq: objectMemory tagMask R: scratchReg.
+ 	jmpImmediate := cogit JumpNonZero: 0.
+ 	"Get the old/new boundary in scratchReg"
+ 	cogit MoveCw: objectMemory storeCheckBoundary R: scratchReg.
+ 	"Is target young?  If so we're done"
+ 	cogit CmpR: scratchReg R: destReg. "N.B. FLAGS := destReg - scratchReg"
+ 	jmpDestYoung := cogit JumpBelow: 0.
+ 	"Is value stored old?  If so we're done."
+ 	cogit CmpR: scratchReg R: valueReg. "N.B. FLAGS := valueReg - scratchReg"
+ 	jmpSourceOld := cogit JumpAboveOrEqual: 0.
+ 	"value is young and target is old.
+ 	 Need to remember this only if the remembered bit is not already set.
+ 	 Test the remembered bit.  Only need to fetch the byte containing it,
+ 	 which reduces the size of the mask constant."
+ 	rememberedBitByteOffset := jmpSourceOld isBigEndian
+ 									ifTrue: [objectMemory baseHeaderSize - 1 - (objectMemory rememberedBitShift // 8)]
+ 									ifFalse:[objectMemory rememberedBitShift // 8].
+ 	mask := 1 << (objectMemory rememberedBitShift \\ 8).
+ 	cogit MoveMb: rememberedBitByteOffset r: destReg R: scratchReg.
+ 	cogit AndCq: mask R: scratchReg.
+ 	jmpAlreadyRemembered := cogit JumpNonZero: 0.
+ 	"Remembered bit is not set.  Call store check to insert dest into remembered table."
+ 	self assert: destReg == ReceiverResultReg.
+ 	inFrame
+ 		ifTrue:
+ 			[cogit
+ 				CallRT: ceStoreCheckTrampoline
+ 				registersToBeSavedMask: (((cogit registerMaskFor: valueReg)
+ 												bitOr: cogit callerSavedRegMask)
+ 												bitClear: (cogit registerMaskFor: ReceiverResultReg))]
+ 		ifFalse:
+ 			[cogit backEnd saveAndRestoreLinkRegAround:
+ 				[cogit
+ 					CallRT: ceStoreCheckTrampoline
+ 					registersToBeSavedMask: (((cogit registerMaskFor: valueReg)
+ 													bitOr: cogit callerSavedRegMask)
+ 													bitClear: (cogit registerMaskFor: ReceiverResultReg))]].
+ 	jmpImmediate jmpTarget:
+ 	(jmpDestYoung jmpTarget:
+ 	(jmpSourceOld jmpTarget:
+ 	(jmpAlreadyRemembered jmpTarget:
+ 		cogit Label))).
+ 	^0!

Item was changed:
  ----- Method: CogObjectRepresentationForSpur>>genStoreSourceReg:slotIndex:destReg:scratchReg: (in category 'compile abstract instructions') -----
  genStoreSourceReg: sourceReg slotIndex: index destReg: destReg scratchReg: scratchReg
  	"do the store"
  	cogit MoveR: sourceReg
  		   Mw: index * objectMemory wordSize + objectMemory baseHeaderSize
  		   r: destReg.
  	"now the check"
+ 	^self genStoreCheckReceiverReg: destReg valueReg: sourceReg scratchReg: scratchReg inFrame: true!
- 	^self genStoreCheckReceiverReg: destReg valueReg: sourceReg scratchReg: scratchReg!

Item was added:
+ ----- Method: CogObjectRepresentationForSpur>>genStoreSourceReg:slotIndex:destReg:scratchReg:inFrame: (in category 'compile abstract instructions') -----
+ genStoreSourceReg: sourceReg slotIndex: index destReg: destReg scratchReg: scratchReg inFrame: inFrame
+ 	"do the store"
+ 	cogit MoveR: sourceReg
+ 		   Mw: index * objectMemory wordSize + objectMemory baseHeaderSize
+ 		   r: destReg.
+ 	"now the check"
+ 	^self genStoreCheckReceiverReg: destReg valueReg: sourceReg scratchReg: scratchReg inFrame: inFrame!

Item was removed:
- ----- Method: CogObjectRepresentationForSqueakV3>>genStoreSourceReg:slotIndex:destReg:scratchReg: (in category 'compile abstract instructions') -----
- genStoreSourceReg: sourceReg slotIndex: index destReg: destReg scratchReg: scratchReg
- 	| jmpImmediate jmpDestYoung jmpSourceOld jmpAlreadyRoot mask rootBitByteOffset |
- 	<var: #jmpImmediate type: #'AbstractInstruction *'>
- 	<var: #jmpDestYoung type: #'AbstractInstruction *'>
- 	<var: #jmpSourceOld type: #'AbstractInstruction *'>
- 	<var: #jmpAlreadyRoot type: #'AbstractInstruction *'>
- 	"do the store"
- 	cogit MoveR: sourceReg Mw: index * objectMemory wordSize + objectMemory baseHeaderSize r: destReg.
- 	"now the check.  Is value stored an integer?  If so we're done"
- 	cogit MoveR: sourceReg R: scratchReg.
- 	cogit AndCq: 1 R: scratchReg.
- 	jmpImmediate := cogit JumpNonZero: 0.
- 	"Get the old/new boundary in scratchReg"
- 	cogit MoveAw: objectMemory youngStartAddress R: scratchReg.
- 	"Is target young?  If so we're done"
- 	cogit CmpR: scratchReg R: destReg. "N.B. FLAGS := destReg - scratchReg"
- 	jmpDestYoung := cogit JumpAboveOrEqual: 0.
- 	"Is value stored old?  If so we're done."
- 	cogit CmpR: scratchReg R: sourceReg. "N.B. FLAGS := sourceReg - scratchReg"
- 	jmpSourceOld := cogit JumpBelow: 0.
- 	"value is young and target is old.
- 	 Need to make this a root if the root bit is not already set.
- 	 Test the root bit.  Only need to fetch the byte containing it,
- 	 which reduces the size of the mask constant."
- 	rootBitByteOffset := jmpSourceOld isBigEndian
- 							ifTrue: [objectMemory wordSize - RootBitDigitLength]
- 							ifFalse:[RootBitDigitLength - 1].
- 	mask := RootBitDigitLength > 1
- 				ifTrue: [RootBit >> (RootBitDigitLength - 1 * 8)]
- 				ifFalse: [RootBit].
- 	cogit MoveMb: rootBitByteOffset r: destReg R: scratchReg.
- 	cogit AndCq: mask R: scratchReg.
- 	jmpAlreadyRoot := cogit JumpNonZero: 0.
- 	"Root bit is not set.  Call store check to insert dest into root table."
- 	self assert: destReg == ReceiverResultReg.
- 	cogit
- 		CallRT: ceStoreCheckTrampoline
- 		registersToBeSavedMask: (((cogit registerMaskFor: sourceReg)
- 										bitOr: cogit callerSavedRegMask)
- 										bitClear: (cogit registerMaskFor: ReceiverResultReg)).
- 	jmpImmediate jmpTarget:
- 	(jmpDestYoung jmpTarget:
- 	(jmpSourceOld jmpTarget:
- 	(jmpAlreadyRoot jmpTarget:
- 		cogit Label))).
- 	^0!

Item was added:
+ ----- Method: CogObjectRepresentationForSqueakV3>>genStoreSourceReg:slotIndex:destReg:scratchReg:inFrame: (in category 'compile abstract instructions') -----
+ genStoreSourceReg: sourceReg slotIndex: index destReg: destReg scratchReg: scratchReg inFrame: inFrame
+ 	| jmpImmediate jmpDestYoung jmpSourceOld jmpAlreadyRoot mask rootBitByteOffset |
+ 	<var: #jmpImmediate type: #'AbstractInstruction *'>
+ 	<var: #jmpDestYoung type: #'AbstractInstruction *'>
+ 	<var: #jmpSourceOld type: #'AbstractInstruction *'>
+ 	<var: #jmpAlreadyRoot type: #'AbstractInstruction *'>
+ 	"do the store"
+ 	cogit MoveR: sourceReg Mw: index * objectMemory wordSize + objectMemory baseHeaderSize r: destReg.
+ 	"now the check.  Is value stored an integer?  If so we're done"
+ 	cogit MoveR: sourceReg R: scratchReg.
+ 	cogit AndCq: 1 R: scratchReg.
+ 	jmpImmediate := cogit JumpNonZero: 0.
+ 	"Get the old/new boundary in scratchReg"
+ 	cogit MoveAw: objectMemory youngStartAddress R: scratchReg.
+ 	"Is target young?  If so we're done"
+ 	cogit CmpR: scratchReg R: destReg. "N.B. FLAGS := destReg - scratchReg"
+ 	jmpDestYoung := cogit JumpAboveOrEqual: 0.
+ 	"Is value stored old?  If so we're done."
+ 	cogit CmpR: scratchReg R: sourceReg. "N.B. FLAGS := sourceReg - scratchReg"
+ 	jmpSourceOld := cogit JumpBelow: 0.
+ 	"value is young and target is old.
+ 	 Need to make this a root if the root bit is not already set.
+ 	 Test the root bit.  Only need to fetch the byte containing it,
+ 	 which reduces the size of the mask constant."
+ 	rootBitByteOffset := jmpSourceOld isBigEndian
+ 							ifTrue: [objectMemory wordSize - RootBitDigitLength]
+ 							ifFalse:[RootBitDigitLength - 1].
+ 	mask := RootBitDigitLength > 1
+ 				ifTrue: [RootBit >> (RootBitDigitLength - 1 * 8)]
+ 				ifFalse: [RootBit].
+ 	cogit MoveMb: rootBitByteOffset r: destReg R: scratchReg.
+ 	cogit AndCq: mask R: scratchReg.
+ 	jmpAlreadyRoot := cogit JumpNonZero: 0.
+ 	"Root bit is not set.  Call store check to insert dest into root table."
+ 	self assert: destReg == ReceiverResultReg.
+ 	inFrame
+ 		ifTrue:
+ 			[cogit
+ 				CallRT: ceStoreCheckTrampoline
+ 				registersToBeSavedMask: (((cogit registerMaskFor: sourceReg)
+ 												bitOr: cogit callerSavedRegMask)
+ 												bitClear: (cogit registerMaskFor: ReceiverResultReg))]
+ 		ifFalse:
+ 			[cogit backEnd saveAndRestoreLinkRegAround:
+ 				[cogit
+ 					CallRT: ceStoreCheckTrampoline
+ 					registersToBeSavedMask: (((cogit registerMaskFor: sourceReg)
+ 													bitOr: cogit callerSavedRegMask)
+ 													bitClear: (cogit registerMaskFor: ReceiverResultReg))]].
+ 	jmpImmediate jmpTarget:
+ 	(jmpDestYoung jmpTarget:
+ 	(jmpSourceOld jmpTarget:
+ 	(jmpAlreadyRoot jmpTarget:
+ 		cogit Label))).
+ 	^0!

Item was changed:
  ----- Method: SimpleStackBasedCogit>>genStorePop:LiteralVariable: (in category 'bytecode generator support') -----
  genStorePop: popBoolean LiteralVariable: litVarIndex
  	<inline: false>
  	| association |
  	self assert: needsFrame.
  	association := self getLiteral: litVarIndex.
  	self annotate: (self MoveCw: association R: ReceiverResultReg) objRef: association.
  	objectRepresentation
  		genEnsureObjInRegNotForwarded: ReceiverResultReg
  		scratchReg: TempReg.
  	popBoolean
  		ifTrue: [self PopR: ClassReg]
  		ifFalse: [self MoveMw: 0 r: SPReg R: ClassReg].
  	traceStores > 0 ifTrue:
  		[self CallRT: ceTraceStoreTrampoline].
  	^objectRepresentation
  		genStoreSourceReg: ClassReg
  		slotIndex: ValueIndex
  		destReg: ReceiverResultReg
+ 		scratchReg: TempReg
+ 		inFrame: needsFrame!
- 		scratchReg: TempReg!

Item was changed:
  ----- Method: SimpleStackBasedCogit>>genStorePop:MaybeContextReceiverVariable: (in category 'bytecode generator support') -----
  genStorePop: popBoolean MaybeContextReceiverVariable: slotIndex
  	<inline: false>
  	| jmpSingle jmpDone |
  	<var: #jmpSingle type: #'AbstractInstruction *'>
  	<var: #jmpDone type: #'AbstractInstruction *'>
  	self assert: needsFrame.
  	self MoveMw: FoxMFReceiver r: FPReg R: ReceiverResultReg.
  	objectRepresentation
  		genLoadSlot: SenderIndex
  		sourceReg: ReceiverResultReg
  		destReg: TempReg.
  	self MoveMw: 0 r: SPReg R: ClassReg.
  	jmpSingle := objectRepresentation genJumpNotSmallIntegerInScratchReg: TempReg.
  	self MoveCq: slotIndex R: SendNumArgsReg.
  	self CallRT: ceStoreContextInstVarTrampoline.
  	jmpDone := self Jump: 0.
  	jmpSingle jmpTarget: self Label.
  	traceStores > 0 ifTrue:
  		[self CallRT: ceTraceStoreTrampoline].
  	objectRepresentation
  		genStoreSourceReg: ClassReg
  		slotIndex: slotIndex
  		destReg: ReceiverResultReg
+ 		scratchReg: TempReg
+ 		inFrame: true.
- 		scratchReg: TempReg.
  	jmpDone jmpTarget: self Label.
  	popBoolean ifTrue:
  		[self AddCq: objectMemory wordSize R: SPReg].
  	^0!

Item was changed:
  ----- Method: SimpleStackBasedCogit>>genStorePop:ReceiverVariable: (in category 'bytecode generator support') -----
  genStorePop: popBoolean ReceiverVariable: slotIndex
  	<inline: false>
  	needsFrame ifTrue:
  		[self MoveMw: FoxMFReceiver r: FPReg R: ReceiverResultReg].
  	popBoolean
  		ifTrue: [self PopR: ClassReg]
  		ifFalse: [self MoveMw: 0 r: SPReg R: ClassReg].
  	traceStores > 0 ifTrue:
  		[self CallRT: ceTraceStoreTrampoline].
  	^objectRepresentation
  		genStoreSourceReg: ClassReg
  		slotIndex: slotIndex
  		destReg: ReceiverResultReg
+ 		scratchReg: TempReg
+ 		inFrame: needsFrame!
- 		scratchReg: TempReg!

Item was changed:
  ----- Method: SimpleStackBasedCogit>>genStorePop:RemoteTemp:At: (in category 'bytecode generator support') -----
  genStorePop: popBoolean RemoteTemp: slotIndex At: remoteTempIndex
  	<inline: false>
  	self assert: needsFrame.
  	popBoolean
  		ifTrue: [self PopR: ClassReg]
  		ifFalse: [self MoveMw: 0 r: SPReg R: ClassReg].
  	self MoveMw: (self frameOffsetOfTemporary: remoteTempIndex) r: FPReg R: ReceiverResultReg.
  	traceStores > 0 ifTrue:
  		[self CallRT: ceTraceStoreTrampoline].
  	^objectRepresentation
  		genStoreSourceReg: ClassReg
  		slotIndex: slotIndex
  		destReg: ReceiverResultReg
+ 		scratchReg: TempReg
+ 		inFrame: needsFrame!
- 		scratchReg: TempReg!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genFramelessStorePop:ReceiverVariable: (in category 'bytecode generator support') -----
  genFramelessStorePop: popBoolean ReceiverVariable: slotIndex
  	<inline: false>
  	| topReg valueReg constVal |
  	self assert: needsFrame not.
  	self ssFlushUpThroughReceiverVariable: slotIndex.
  	"Avoid store check for immediate values"
  	constVal := self ssTop maybeConstant.
  	(self ssTop type = SSConstant
  	 and: [(objectRepresentation shouldAnnotateObjectReference: constVal) not]) ifTrue:
  		[self ensureReceiverResultRegContainsSelf.
  		 self ssStorePop: popBoolean toPreferredReg: TempReg.
  		 traceStores > 0 ifTrue:
  			[backEnd saveAndRestoreLinkRegAround:
  				[self CallRT: ceTraceStoreTrampoline]].
  		 ^objectRepresentation
  			genStoreImmediateInSourceReg: TempReg
  			slotIndex: slotIndex
  			destReg: ReceiverResultReg].
  	(topReg := self ssTop registerOrNil) isNil ifTrue:
  		[topReg := ClassReg].
  	valueReg := self ssStorePop: popBoolean toPreferredReg: topReg.
  	"Note that ReceiverResultReg remains live after ceStoreCheckTrampoline."
  	self ensureReceiverResultRegContainsSelf.
  	 traceStores > 0 ifTrue:
  		[self MoveR: valueReg R: TempReg.
  		 backEnd saveAndRestoreLinkRegAround:
  			[self CallRT: ceTraceStoreTrampoline]].
  	^objectRepresentation
  		genStoreSourceReg: valueReg
  		slotIndex: slotIndex
  		destReg: ReceiverResultReg
+ 		scratchReg: TempReg
+ 		inFrame: false!
- 		scratchReg: TempReg!

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 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!
- 		scratchReg: TempReg!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genStorePop:MaybeContextReceiverVariable: (in category 'bytecode generator support') -----
  genStorePop: popBoolean MaybeContextReceiverVariable: slotIndex
  	<inline: false>
  	| jmpSingle jmpDone valueReg |
  	<var: #jmpSingle type: #'AbstractInstruction *'>
  	<var: #jmpDone type: #'AbstractInstruction *'>
  	self assert: needsFrame.
  	self ssFlushUpThroughReceiverVariable: slotIndex.
  	"Note that ReceiverResultReg remains live after both
  	 ceStoreContextInstVarTrampoline and ceStoreCheckTrampoline."
  	self ensureReceiverResultRegContainsSelf.
  	self ssPop: 1.
  	self ssAllocateCallReg: ClassReg and: SendNumArgsReg. "for the ceStoreCheck call in genStoreSourceReg:... below"
  	self ssPush: 1.
  	objectRepresentation
  		genLoadSlot: SenderIndex
  		sourceReg: ReceiverResultReg
  		destReg: TempReg.
  	valueReg := self ssStorePop: popBoolean toPreferredReg: ClassReg.
  	valueReg ~= ClassReg ifTrue:
  		[self MoveR: valueReg R: ClassReg].
  	jmpSingle := objectRepresentation genJumpNotSmallIntegerInScratchReg: TempReg.
  	self MoveCq: slotIndex R: SendNumArgsReg.
  	self CallRT: ceStoreContextInstVarTrampoline.
  	jmpDone := self Jump: 0.
  	jmpSingle jmpTarget: self Label.
  	traceStores > 0 ifTrue:
  		[self MoveR: ClassReg R: TempReg.
  		 self CallRT: ceTraceStoreTrampoline].
  	objectRepresentation
  		genStoreSourceReg: ClassReg
  		slotIndex: slotIndex
  		destReg: ReceiverResultReg
+ 		scratchReg: TempReg
+ 		inFrame: true.
- 		scratchReg: TempReg.
  	jmpDone jmpTarget: self Label.
  	^0!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genStorePop:ReceiverVariable: (in category 'bytecode generator support') -----
  genStorePop: popBoolean ReceiverVariable: slotIndex
  	<inline: false>
  	| topReg valueReg constVal |
  	needsFrame ifFalse:
  		[^self genFramelessStorePop: popBoolean ReceiverVariable: slotIndex].
  	self ssFlushUpThroughReceiverVariable: slotIndex.
  	"Avoid store check for immediate values"
  	constVal := self ssTop maybeConstant.
  	(self ssTop type = SSConstant
  	 and: [(objectRepresentation shouldAnnotateObjectReference: constVal) not]) ifTrue:
  		[self ensureReceiverResultRegContainsSelf.
  		 self ssStorePop: popBoolean toPreferredReg: TempReg.
  		 traceStores > 0 ifTrue:
  			[self CallRT: ceTraceStoreTrampoline].
  		 ^objectRepresentation
  			genStoreImmediateInSourceReg: TempReg
  			slotIndex: slotIndex
  			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].
  	"Note that ReceiverResultReg remains live after ceStoreCheckTrampoline."
  	self ensureReceiverResultRegContainsSelf.
  	 traceStores > 0 ifTrue:
  		[self MoveR: topReg R: TempReg.
  		 self CallRT: ceTraceStoreTrampoline].
  	^objectRepresentation
  		genStoreSourceReg: topReg
  		slotIndex: slotIndex
  		destReg: ReceiverResultReg
+ 		scratchReg: TempReg
+ 		inFrame: true!
- 		scratchReg: TempReg!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genStorePop:RemoteTemp:At: (in category 'bytecode generator support') -----
  genStorePop: popBoolean RemoteTemp: slotIndex At: remoteTempIndex
  	<inline: false>
  	| topReg valueReg constVal topSpilled |
  	self assert: needsFrame.
  	optStatus isReceiverResultRegLive: false.
  	"N.B.  No need to check the stack for references because we generate code for
  	 remote temp loads that stores the result in a register, deferring only the register push."
  	"Avoid store check for immediate values"
  	constVal := self ssTop maybeConstant.
  	(self ssTop type = SSConstant
  	 and: [(objectRepresentation shouldAnnotateObjectReference: constVal) not]) ifTrue:
  		[self ssAllocateRequiredReg: ReceiverResultReg.
  		 self MoveMw: (self frameOffsetOfTemporary: remoteTempIndex) r: FPReg R: ReceiverResultReg.
  		 self ssStorePop: popBoolean toPreferredReg: TempReg.
  		 traceStores > 0 ifTrue:
  			[self CallRT: ceTraceStoreTrampoline].
  		 ^objectRepresentation
  			genStoreImmediateInSourceReg: TempReg
  			slotIndex: slotIndex
  			destReg: ReceiverResultReg].
  	((topReg := self ssTop registerOrNil) isNil
  	 or: [topReg = ReceiverResultReg]) ifTrue:
  		[topReg := ClassReg].
  	self ssPop: 1.
  	"for the ceStoreCheck call in genStoreSourceReg:... below"
  	self ssAllocateCallReg: topReg and: ReceiverResultReg.
  	self ssPush: 1.
  	topSpilled := self ssTop spilled.
  	valueReg := self ssStorePop: (popBoolean or: [topSpilled]) toPreferredReg: topReg.
  	valueReg = ReceiverResultReg ifTrue:
  		[self MoveR: valueReg R: topReg].
  	popBoolean ifFalse:
  		[topSpilled ifFalse: [self ssPop: 1].
  		 self ssPushRegister: topReg].
  	self MoveMw: (self frameOffsetOfTemporary: remoteTempIndex) r: FPReg R: ReceiverResultReg.
  	 traceStores > 0 ifTrue:
  		[self MoveR: topReg R: TempReg.
  		 self CallRT: ceTraceStoreTrampoline].
  	^objectRepresentation
  		genStoreSourceReg: topReg
  		slotIndex: slotIndex
  		destReg: ReceiverResultReg
+ 		scratchReg: TempReg
+ 		inFrame: needsFrame!
- 		scratchReg: TempReg!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genTrinaryInlinePrimitive: (in category 'inline primitive generators') -----
  genTrinaryInlinePrimitive: prim
  	"Unary 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>>#trinaryInlinePrimitive:"
  
  	| ra1 ra2 rr adjust |
  	"The store check requires rr to be ReceiverResultReg"
  	self allocateThreeRegistersInto: [:rTop :rNext :rThird | ra2 := rTop. ra1 := rNext. rr := rThird ] thirdIsReceiver: prim = 0.
  	self assert: (rr ~= ra1 and: [rr ~= ra2 and: [ra1 ~= ra2]]).
  	self ssTop popToReg: ra2.
  	self ssPop: 1.
  	self ssTop popToReg: ra1.
  	self ssPop: 1.
  	self ssTop popToReg: rr.
  	self ssPop: 1.
  	objectRepresentation genConvertSmallIntegerToIntegerInReg: ra1.
  	"Now: ra is the variable object, rr is long, TempReg holds the value to store."
  	prim caseOf: {
  		"0 - 1 pointerAt:put: and byteAt:Put:"
  		[0] ->	[ 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: ra1. ]. 
  				self MoveR: ra2 Xwr: ra1 R: rr.
+ 				objectRepresentation genStoreCheckReceiverReg: rr valueReg: ra2 scratchReg: TempReg inFrame: true].
- 				objectRepresentation genStoreCheckReceiverReg: rr valueReg: ra2 scratchReg: TempReg].
  		[1] ->	[ objectRepresentation genConvertSmallIntegerToIntegerInReg: ra2.
  				adjust := objectMemory baseHeaderSize - 1. "shift by baseHeaderSize and then move from 1 relative to zero relative"
  				self AddCq: adjust R: ra1.
  				self MoveR: ra2 Xbr: ra1 R: rr.
  				objectRepresentation genConvertIntegerToSmallIntegerInReg: ra2. ]
  	}
  	otherwise: [^EncounteredUnknownBytecode].
  	self ssPushRegister: ra2.
  	^0!



More information about the Vm-dev mailing list