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

commits at source.squeak.org commits at source.squeak.org
Tue Jan 19 12:29:17 UTC 2016


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

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

Name: VMMaker.oscog-cb.1653
Author: cb
Time: 19 January 2016, 1:28:02.308 pm
UUID: c46f2c10-6886-4558-9cc7-ffaae87ba44f
Ancestors: VMMaker.oscog-cb.1652

Simplified the generated code and code generating the machine code to make it easier to understand.

Still I have some bugs (but less).

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

Item was changed:
  ----- Method: CogObjectRepresentationForSpur>>genImmutableCheck:slotIndex:sourceReg:scratchReg:popBoolean:needRestoreRcvr: (in category 'compile abstract instructions') -----
  genImmutableCheck: regHoldingObjectMutated slotIndex: index sourceReg: regHoldingValueToStore scratchReg: scratchReg popBoolean: popBoolean needRestoreRcvr: needRestoreRcvr
  	| mutableJump fail |
  	<var: #mutableJump type: #'AbstractInstruction *'>
  	<var: #fail type: #'AbstractInstruction *'>
  	<inline: true>
  	<option: #IMMUTABILITY>
  	"Trampoline convention: 
  	- objectMutated passed in ReceiverResultReg
  	- index (unboxed) passed in TempReg
  	- valueToStore passed in ClassReg.
+ 	Simulated stack is flushed, but if needRestoreRcvr is true 
+ 	the receiver has to be live after this operation."
- 	Simulated stack is flushed until simulatedStackPointer - 1, which implies full flush 
- 	if popBoolean is true, else top value may not be flushed.
- 	We spill the top value (the value to store) for the trampoline if needed."
  	self assert: regHoldingObjectMutated == ReceiverResultReg. 
  	self assert: scratchReg == TempReg.
  	self assert: regHoldingValueToStore == ClassReg.
+ 	mutableJump := self genJumpMutable: ReceiverResultReg scratchReg: TempReg.
- 	mutableJump := self genJumpMutable: ClassReg scratchReg: TempReg.
  	
  	"We reach this code if the object mutated is immutable."
- 	"simulatedStack state altered for the trampoline, spill top value if needed"
- 	(popBoolean or: [ cogit ssTop spilled ]) ifFalse:
- 		[ self assert: (cogit ssTop type = SSRegister and: [cogit ssTop register = ClassReg]).
- 		  cogit PushR: ClassReg ].
- 	"pass the unboxed index using TempReg"
  	cogit MoveCq: index R: TempReg.
  	"trampoline call and mcpc to bcpc annotation."
  	cogit CallRT: ceCannotAssignToWithIndexTrampoline.
  	cogit annotateBytecode: cogit Label.
+ 	"restore ReceiverResultReg state if needed, the rest of the state is spilled"
- 	"Top of stack is consumed by the trampoline. In case of store with non spilled value, 
- 	restore ClassReg to match simulated stack state"
- 	(popBoolean or: [ cogit ssTop spilled ]) ifFalse:
- 		[cogit popR: ClassReg].
- 	"restore ReceiverResultReg state if needed"
  	needRestoreRcvr ifTrue: [ cogit putSelfInReceiverResultReg ].
  	fail := cogit Jump: 0.
  	
  	"We reach this code is the object mutated is mutable"
  	mutableJump jmpTarget: cogit Label.
  	
  	^ fail!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genStorePop:LiteralVariable: (in category 'bytecode generator support') -----
  genStorePop: popBoolean LiteralVariable: litVarIndex
  	<inline: false>
  	| topReg association needStoreCheck immutabilityFailure |
  	"The only reason we assert needsFrame here is that in a frameless method
  	 ReceiverResultReg must and does contain only self, but the ceStoreCheck
  	 trampoline expects the target of the store to be in ReceiverResultReg.  So
  	 in a frameless method we would have a conflict between the receiver and
  	 the literal store, unless we we smart enough to realise that ReceiverResultReg
  	 was unused after the literal variable store, unlikely given that methods
  	 return self by default."
  	self assert: needsFrame.
  	self cppIf: IMMUTABILITY ifTrue: [ self ssFlushTo: simStackPtr - 1 ].
  	"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."
  	needStoreCheck := (objectRepresentation isUnannotatableConstant: self ssTop) not.
  	association := self getLiteral: litVarIndex.
  	optStatus isReceiverResultRegLive: false.
  	self ssAllocateRequiredReg: ReceiverResultReg. "for ceStoreCheck call in genStoreSourceReg: has to be ReceiverResultReg"
  	self genMoveConstant: association R: ReceiverResultReg.
  	objectRepresentation genEnsureObjInRegNotForwarded: ReceiverResultReg scratchReg: TempReg.
  	self 
  		cppIf: IMMUTABILITY
  		ifTrue: 
  			[ self ssAllocateRequiredReg: ClassReg.
  			  topReg := ClassReg.
  			  self ssStoreAndReplacePop: popBoolean toReg: ClassReg.
+ 			  "stack is flushed except maybe ssTop if popBoolean is false.
+ 			  ssTop is a SSregister in this case due to #ssStoreAndReplacePop:
+ 			  to avoid a second indirect read / annotation in case of SSConstant
+ 			  or SSBaseRegister"
+ 			  self ssFlushTo: simStackPtr.
  			  immutabilityFailure := objectRepresentation 
  				genImmutableCheck: ReceiverResultReg 
  				slotIndex: ValueIndex 
  				sourceReg: ClassReg 
  				scratchReg: TempReg 
  				popBoolean: popBoolean
  				needRestoreRcvr: false ]
  		ifFalse: 
  			[ topReg := self allocateRegForStackEntryAt: 0 notConflictingWith: (self registerMaskFor: ReceiverResultReg).
  			  self ssStorePop: popBoolean toReg: topReg ].
  	traceStores > 0 ifTrue:
  		[self MoveR: topReg R: TempReg.
  		 self CallRT: ceTraceStoreTrampoline].
  	objectRepresentation
  		genStoreSourceReg: topReg
  		slotIndex: ValueIndex
  		destReg: ReceiverResultReg
  		scratchReg: TempReg
  		inFrame: needsFrame
  		needsStoreCheck: needStoreCheck.
  	self cppIf: IMMUTABILITY ifTrue: [ immutabilityFailure jmpTarget: self Label ].
  	^ 0!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genStorePop:MaybeContextReceiverVariable: (in category 'bytecode generator support') -----
  genStorePop: popBoolean MaybeContextReceiverVariable: slotIndex
  	<inline: false>
  	| jmpSingle jmpDone needStoreCheck immutabilityFailure |
  	<var: #jmpSingle type: #'AbstractInstruction *'>
  	<var: #jmpDone type: #'AbstractInstruction *'>
  	"The reason we need a frame here is that assigning to an inst var of a context may
  	 involve wholesale reorganization of stack pages, and the only way to preserve the
  	 execution state of an activation in that case is if it has a frame."
  	self assert: needsFrame.
  	self cppIf: IMMUTABILITY ifTrue: [ self ssFlushTo: simStackPtr - 1 ].
  	self ssFlushUpThroughReceiverVariable: slotIndex.
  	needStoreCheck := (objectRepresentation isUnannotatableConstant: self ssTop) not.
  	"Note that ReceiverResultReg remains live after both
  	 ceStoreContextInstVarTrampoline and ceStoreCheckTrampoline."
  	self ensureReceiverResultRegContainsSelf.
  	self ssPop: 1.
  	self ssAllocateCallReg: ClassReg and: SendNumArgsReg. "for ceStoreContextInstVarTrampoline"
  	self ssPush: 1.
  	objectRepresentation
  		genLoadSlot: SenderIndex
  		sourceReg: ReceiverResultReg
  		destReg: TempReg.
  	self 
  		cppIf: IMMUTABILITY
+ 		ifTrue: 
+ 			[ self ssStoreAndReplacePop: popBoolean toReg: ClassReg.
+ 			  "stack is flushed except maybe ssTop if popBoolean is false.
+ 			  ssTop is a SSregister in this case due to #ssStoreAndReplacePop:
+ 			  to avoid a second indirect read / annotation in case of SSConstant
+ 			  or SSBaseRegister"
+ 			  self ssFlushTo: simStackPtr. ]
- 		ifTrue: [ self ssStoreAndReplacePop: popBoolean toReg: ClassReg. ]
  		ifFalse: [ self ssStorePop: popBoolean toReg: 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].
  	self 
  		cppIf: IMMUTABILITY
  		ifTrue: 
  			[ immutabilityFailure := objectRepresentation 
  				genImmutableCheck: ReceiverResultReg 
  				slotIndex: ValueIndex 
  				sourceReg: ClassReg 
  				scratchReg: TempReg 
  				popBoolean: popBoolean
  				needRestoreRcvr: true ].
  	objectRepresentation
  		genStoreSourceReg: ClassReg
  		slotIndex: slotIndex
  		destReg: ReceiverResultReg
  		scratchReg: TempReg
  		inFrame: true
  		needsStoreCheck: needStoreCheck.
  	jmpDone jmpTarget: self Label.
  	self cppIf: IMMUTABILITY ifTrue: [ immutabilityFailure jmpTarget: self Label ].
  	^0!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genStorePop:ReceiverVariable: (in category 'bytecode generator support') -----
  genStorePop: popBoolean ReceiverVariable: slotIndex
  	<inline: false>
  	| topReg needStoreCheck immutabilityFailure |
  	self cppIf: IMMUTABILITY ifTrue: [ self assert: needsFrame. self ssFlushTo: simStackPtr - 1 ].
  	self ssFlushUpThroughReceiverVariable: slotIndex.
  	needStoreCheck := (objectRepresentation isUnannotatableConstant: self ssTop) not.
  	"Note that ReceiverResultReg remains live after ceStoreCheckTrampoline."
  	self ensureReceiverResultRegContainsSelf.
  	self 
  		cppIf: IMMUTABILITY
  		ifTrue: 
  			[ self ssAllocateRequiredReg: ClassReg.
  			  topReg := ClassReg.
+ 			  self ssStoreAndReplacePop: popBoolean toReg: ClassReg.
+ 			  "stack is flushed except maybe ssTop if popBoolean is false.
+ 			  ssTop is a SSregister in this case due to #ssStoreAndReplacePop:
+ 			  to avoid a second indirect read / annotation in case of SSConstant
+ 			  or SSBaseRegister"
+ 			  self ssFlushTo: simStackPtr.
- 			  self ssStoreAndReplacePop: popBoolean toReg: topReg.
  			  immutabilityFailure := objectRepresentation 
  				genImmutableCheck: ReceiverResultReg 
  				slotIndex: slotIndex 
  				sourceReg: ClassReg 
  				scratchReg: TempReg
  				popBoolean: popBoolean
  				needRestoreRcvr: true ]
  		ifFalse: 
  			[ topReg := self allocateRegForStackEntryAt: 0 notConflictingWith: (self registerMaskFor: ReceiverResultReg). 
  			  self ssStorePop: popBoolean toReg: topReg ].
  	traceStores > 0 ifTrue: 
  		[ self MoveR: topReg R: TempReg.
  		self evaluateTrampolineCallBlock: [ self CallRT: ceTraceStoreTrampoline ] protectLinkRegIfNot: needsFrame ].
  	objectRepresentation
  		genStoreSourceReg: topReg
  		slotIndex: slotIndex
  		destReg: ReceiverResultReg
  		scratchReg: TempReg
  		inFrame: needsFrame
  		needsStoreCheck: needStoreCheck.
  	self cppIf: IMMUTABILITY ifTrue: [ immutabilityFailure jmpTarget: self Label ].
  	^ 0!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>ssStoreAndReplacePop:toReg: (in category 'simulation stack') -----
  ssStoreAndReplacePop: popBoolean toReg: reg
  	"In addition to ssStorePop:toReg:, if this is a store and not
+ 	a popInto I change the simulated stack to use the register 
+ 	for the top value"
- 	a popInto and the top of the simulated stack is not spilled,
- 	I change the simulated stack to use the register for the value"
  	| topSpilled |
  	topSpilled := self ssTop spilled.
  	self ssStorePop: (popBoolean or: [topSpilled]) toReg: reg.
  	popBoolean ifFalse: 
  		[ topSpilled ifFalse: [self ssPop: 1].
  		self ssPushRegister: reg ].!



More information about the Vm-dev mailing list