VM Maker: Cog-eem.414.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

VM Maker: Cog-eem.414.mcz

commits-2
 
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)]!