[Vm-dev] VM Maker: Cog-eem.414.mcz

commits at source.squeak.org commits at source.squeak.org
Wed Oct 28 08:22:54 UTC 2020


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

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

Name: Cog-eem.414
Author: eem
Time: 28 October 2020, 1:22:52.353271 am
UUID: 12531e8d-e09b-4057-a626-60006375a14a
Ancestors: Cog-eem.413

Write code to stitch the stack together to preserve the continuation when raising the first of a pair of ProcessorSimulationTraps (from ARMv8 load/store pair) outside of the critical section inside MultiProcessor's doesNotUnderstand:.  But even though this code looks correct it appears not to work properly.  Boris has complained of a simular bug.  Hence, let's try and simulate the simulator and see what is happening with this bug.

Go some way to making the ProcessorSimulatorPlugins simulate :-)  So far implement primitiveNewCPU and primitiveIntegerRegisterState.

=============== Diff against Cog-eem.413 ===============

Item was added:
+ ----- Method: BochsIA32Plugin>>alienClass (in category 'simulation support') -----
+ alienClass
+ 	^BochsIA32Alien!

Item was added:
+ ----- Method: BochsX64Plugin>>alienClass (in category 'simulation support') -----
+ alienClass
+ 	^BochsX64Alien!

Item was added:
+ ----- Method: CogProcessorAlien>>nonVirtualProcessor (in category 'accessing-abstract') -----
+ nonVirtualProcessor
+ 	^self!

Item was added:
+ ----- Method: GdbARMv6Plugin>>alienClass (in category 'simulation support') -----
+ alienClass
+ 	^GdbARMAlien!

Item was added:
+ ----- Method: GdbARMv8Plugin>>alienClass (in category 'simulation support') -----
+ alienClass
+ 	^GdbARMv8Alien!

Item was added:
+ ----- Method: MIPSSimulator>>nonVirtualProcessor (in category 'accessing-abstract') -----
+ nonVirtualProcessor
+ 	^self!

Item was changed:
  ----- Method: MultiProcessor>>doesNotUnderstand: (in category 'message forwarding') -----
  doesNotUnderstand: aMessage
  	"Forward a message to the actual processor, managing a thread-switch if necessary.
  	 Catch ProcessorSimulationTraps and raise them outside of the critical section to
  	 avoid deadlock when reentering the VM from a trap and switching threads in the run-time."
+ 	| selector result trap contextInCritical |
- 	| selector result trap |
  	selector := aMessage selector.
  	(guardedProcessorProtocol includes: selector) ifFalse:
  		[^(unguardedProcessorProtocol includes: selector)
  			ifTrue: [processor perform: selector withArguments: aMessage arguments]
  			ifFalse: [super doesNotUnderstand: aMessage]].
  	result := [mutex critical:
+ 				[contextInCritical := thisContext.
+ 				 owner ~~ mutex owningProcess ifTrue:
- 				[owner ~~ mutex owningProcess ifTrue:
  					[owner ifNotNil:
  						[registerState at: owner put: processor registerState].
  					 (registerState at: (owner := mutex owningProcess) ifAbsent: nil)
  						ifNil: [coInterpreter initializeProcessorForThreadIndex: (threadIndex := threadIndex + 1)]
  						ifNotNil: [:newState| processor setRegisterState: newState]].
  				 processor perform: selector withArguments: aMessage arguments]]
  					on: ProcessorSimulationTrap, Error, AssertionFailure
  					do: [:ex|
  						ex class == ProcessorSimulationTrap ifFalse:
  							[ex pass].
+ 						"Alas things are not so simple with ARMv8 ldp/stp...
+ 						 The comments in these two methods explain..."
+ 						(self isAboutToReturn: ex signalerContext) ifFalse:
+ 							[self saveStackFor: ex signalerContext
+ 								above: contextInCritical
+ 								homeContext: thisContext home].
  						trap := ex].
  	^trap ifNil: [result] ifNotNil: [trap signal]!

Item was added:
+ ----- Method: MultiProcessor>>isAboutToReturn: (in category 'private-deep hackery') -----
+ isAboutToReturn: aContextRaisingProcessorSimulationTrap
+ 	"Answer if aContextRaisingProcessorSimulationTrap is about to return the result of raising
+ 	 a ProcessorSimulationTrap.  Such traps don't need special handling when continuing."
+ 	^aContextRaisingProcessorSimulationTrap willReturn
+ 	  or: [aContextRaisingProcessorSimulationTrap willJump
+ 		  and: [aContextRaisingProcessorSimulationTrap copy interpretJump; willReturn]]!

Item was added:
+ ----- Method: MultiProcessor>>nonVirtualProcessor (in category 'accessing-abstract') -----
+ nonVirtualProcessor
+ 	^processor!

Item was added:
+ ----- Method: MultiProcessor>>saveStackFor:above:homeContext: (in category 'private-deep hackery') -----
+ saveStackFor: signalerContext above: contextInCritical homeContext: doesNotUnderstandContext
+ 	"Some processors, notably ARMv8, support load/store pair instructions which may raise two
+ 	 ProcessorSimulationTraps. To handle this we must preserve the continuation following the
+ 	 raising of the first simulaiton trap.  This cuts up, and restitches the stack so that when the
+ 	 first ProcessorSimulationTrap is raised outside the critical: block in our doesNotUnderstand:
+ 	 method, control continues to the second trap." 
+ 	| contextAboveContextInCritical contextAboveSignalerContext |
+ 	contextAboveContextInCritical := signalerContext findContextSuchThat: [:ctxt| ctxt sender == contextInCritical].
+ 	"This is our continuation, which should be changed to continue back into the critical section."
+ 	contextAboveSignalerContext := thisContext findContextSuchThat: [:ctxt| ctxt sender == signalerContext].
+ 	self deny: contextAboveContextInCritical isNil.
+ 	self deny: contextAboveSignalerContext isNil.
+ 
+ 	"signalerContext through contextAboveContextInCritical is the stack that is the continuation
+ 	 for the trap.  This must be inserted between the doesNotUnderstandContext and its sender."
+ 	signalerContext cut: contextAboveContextInCritical.
+ 	contextAboveContextInCritical privSender: doesNotUnderstandContext sender.
+ 	doesNotUnderstandContext privSender: signalerContext.
+ 
+ 	"Now arrange that the handler returns to contextInCritical; and we're done."
+ 	contextAboveSignalerContext privSender: contextInCritical.
+ 	self deny: (thisContext findContextSuchThat: [:ctxt| ctxt == signalerContext]) isNil.
+ 	self deny: (thisContext findContextSuchThat: [:ctxt| ctxt == contextInCritical]) isNil.
+ 	self deny: (thisContext findContextSuchThat: [:ctxt| ctxt == doesNotUnderstandContext]) isNil!

Item was changed:
  SmartSyntaxInterpreterPlugin subclass: #ProcessorSimulatorPlugin
+ 	instanceVariableNames: 'prevInterruptCheckChain mySimulatorAlien'
- 	instanceVariableNames: 'prevInterruptCheckChain'
  	classVariableNames: 'NumIntegerRegisterStateFields'
  	poolDictionaries: 'VMBasicConstants'
  	category: 'Cog-ProcessorPlugins'!
  
  !ProcessorSimulatorPlugin commentStamp: 'eem 11/19/2019 09:32' prior: 0!
  ProcessorSimulatorPlugin is the abstract superclass for plugins that interface to a processor simulator that executes the machine code for some processor the Cog JIT generates code for.  These include the Bochs C++ IA32/x64 processor emulator, and the GDB simulator for the ARMv6 and ARMv8 architectures.
  
  Instance Variables
  	prevInterruptCheckChain:		<Symbol/function pointer>
  
  prevInterruptCheckChain
  	- the previous value of the interruptCheckChain function pointer
  !

Item was changed:
  ----- Method: ProcessorSimulatorPlugin class>>declareCVarsIn: (in category 'translation') -----
  declareCVarsIn: aCCodeGenerator
  	self ~~ ProcessorSimulatorPlugin ifTrue:
  		[super declareCVarsIn: aCCodeGenerator.
  		 aCCodeGenerator
  			removeVariable: 'prevInterruptCheckChain'; "lives in the platform support code."
+ 			removeConstant: #NumIntegerRegisterStateFields]. "defined by the header file"
+ 	aCCodeGenerator removeVariable: 'mySimulatorAlien' ifAbsent: nil!
- 			removeConstant: #NumIntegerRegisterStateFields] "defined by the header file"!

Item was added:
+ ----- Method: ProcessorSimulatorPlugin>>newCPU (in category 'simulation') -----
+ newCPU
+ 	"Isn't this deliciously recursive??"
+ 	<doNotGenerate>
+ 	((interpreterProxy coInterpreter isKindOf: CoInterpreter)
+ 	 and: [self alienClass = interpreterProxy coInterpreter cogit processor nonVirtualProcessor class]) ifTrue:
+ 		[self error: 'this isn''t going to work; choose a different simulator class to run the simulation...'].
+ 	mySimulatorAlien := self alienClass createNewCPU.
+ 	NumIntegerRegisterStateFields := mySimulatorAlien integerRegisterState size.
+ 	^mySimulatorAlien address!

Item was added:
+ ----- Method: ProcessorSimulatorPlugin>>storeIntegerRegisterStateOf:into: (in category 'simulation support') -----
+ storeIntegerRegisterStateOf: objOop into: aCArray
+ 	| state |
+ 	state := mySimulatorAlien integerRegisterState.
+ 	1 to: state size do:
+ 		[:i| aCArray at: i - 1 put: (objOop at: i)]!



More information about the Vm-dev mailing list