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

commits at source.squeak.org commits at source.squeak.org
Wed Nov 25 07:25:40 UTC 2020

Eliot Miranda uploaded a new version of VMMaker to project VM Maker:

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

Name: VMMaker.oscog-eem.2897
Author: eem
Time: 24 November 2020, 11:25:32.968954 pm
UUID: 7f4d1c8f-4546-451d-96dc-3c90be8edde6
Ancestors: VMMaker.oscog-eem.2896

Symbolic names for addresses on the rump C stack.
More asserts tracking c/processor stack pointers in the MT VM.

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

Item was changed:
  ----- Method: CoInterpreter>>setCFramePointer:setCStackPointer: (in category 'callback support') -----
  setCFramePointer: cFramePointer setCStackPointer: cStackPointer
  	<inline: #always>
+ 	self deny: (cFramePointer isNil or: [cStackPointer isNil]).
  	CStackPointer := cStackPointer.
  	CFramePointer := cFramePointer!

Item was added:
+ ----- Method: CoInterpreterMT>>assertValidExternalStackPointers (in category 'debug support') -----
+ assertValidExternalStackPointers
+ 	<doNotGenerate>
+ 	"For use *ONLY* by routines coming in to the VM,
+ 	 i.e. handleCallOrJumpSimulationTrap:.  This is because it nils localFP as a side-effect,
+ 	 and it does so so that the head frame can be determined reliably."
+ 	super assertValidExternalStackPointers.
+ 	self assertCStackPointersBelongToCurrentThread.
+ 	self assertProcessorStackPointersBelongToCurrentThread!

Item was changed:
  ----- Method: CoInterpreterMT>>ownVM: (in category 'vm scheduling') -----
  ownVM: threadIndexAndFlags
  	<inline: false>
  	"This is the entry-point for plugins and primitives that wish to reacquire the VM after having
  	 released it via disownVM or callbacks that want to acquire it without knowing their ownership
  	 status.  This call will block until the VM is owned by the current thread or an error occurs.
  	 The argument should be the value answered by disownVM, or 0 for callbacks that don't know
  	 if they have disowned or not.  This is both an optimization to avoid having to query thread-
  	 local storage for the current thread's index (since it can easily keep it in some local variable),
  	 and a record of when an unbound process becomes affined to a thread for the dynamic
  	 extent of some operation.
  	 Answer 0 if the current thread is known to the VM (and on return owns the VM).
  	 Answer 1 if the current thread is unknown to the VM and takes ownership.
  	 Answer -1 if the current thread is unknown to the VM and fails to take ownership."
  	| threadIndex flags vmThread |
  	threadIndexAndFlags = 0 ifTrue:
  		[^self ownVMFromUnidentifiedThread].
  	threadIndex := threadIndexAndFlags bitAnd: ThreadIdMask.
  	flags := threadIndexAndFlags >> DisownFlagsShift.
  	(flags anyMask: DisownVMForProcessorRelinquish) ifTrue:
  		["Presumably we have nothing to do; this primitive is typically called from the
  		  background process. So we should /not/ try and activate any threads in the
  		  pool; they will waste cycles finding there is no runnable process, and will
  		  cause a VM abort if no runnable process is found.  But we /do/ want to allow
  		  FFI calls that have completed, or callbacks a chance to get into the VM; they
  		  do have something to do.  DisownVMForProcessorRelinquish indicates this."
  		 relinquishing := false.
  		 self sqLowLevelMFence].
  	(threadIndexAndFlags anyMask: LockGUIThreadFlag) ifTrue:
  		[self assert: (noThreadingOfGUIThread and: [self inGUIThread]).
  		 self assert: disowningVMThread isNil.
  		 cogit recordEventTrace ifTrue:
  			[self recordTrace: TraceOwnVM thing: ConstZero source: 0].
  	vmThread := cogThreadManager acquireVMFor: threadIndex.
  	disownCount := disownCount - 1.
  	disowningVMThread ifNotNil:
  		[vmThread = disowningVMThread ifTrue:
+ 			[self assert: (vmThread cFramePointer isNil
+ 						or: [CFramePointer = vmThread cFramePointer and: [CStackPointer = vmThread cStackPointer]]).
- 			[self cCode: '' inSmalltalk:
- 					[| range | range := self cStackRangeForThreadIndex: threadIndex.
- 					 self assert: ((range includes: CStackPointer) and: [range includes: CFramePointer])].
  			 self assert: self successful.
  			 self assert: (objectMemory fetchPointer: MyListIndex ofObject: self activeProcess) = objectMemory nilObject.
  			 disowningVMThread := nil.
  			 cogit recordEventTrace ifTrue:
  				[self recordTrace: TraceOwnVM thing: ConstOne source: 0].
  			 ^0].  "if not preempted we're done."
  		self preemptDisowningThread].
  	"We've been preempted; we must restore state and update the threadId
  	 in our process, and may have to put the active process to sleep."
  	self restoreVMStateFor: vmThread threadIndexAndFlags: threadIndexAndFlags.
  	cogit recordEventTrace ifTrue:
  		[self recordTrace: TraceOwnVM thing: ConstTwo source: 0].
  	^threadIndexAndFlags bitAnd: OwnVMForeignThreadFlag!

Item was changed:
  ----- Method: CogThreadManager>>acquireVMFor: (in category 'public api') -----
  acquireVMFor: threadIndex
  	"Attempt to acquire the VM, eventually blocking until it becomes available.
  	 Spin until the maxWaitingPriority has been updated if it is lower than this thread's priority."
  	<returnTypeC: #'CogVMThread *'>
  	| vmThread |
  	<var: #vmThread type: #'CogVMThread *'>
  	self assert: threadIndex = self ioGetThreadLocalThreadIndex.
  	vmThread := self vmThreadAt: threadIndex.
  	self assert: (vmThread state = CTMUnavailable
  				or: [vmThread state = CTMWantingOwnership]).
  	(self tryLockVMOwnerTo: threadIndex) ifFalse:
  		[vmThread state: CTMWantingOwnership.
  		 [(self vmOwnerIs: threadIndex)
  		  or: [self tryLockVMOwnerTo: threadIndex]] whileFalse:
  			[vmThread priority ifNotNil:
  				[coInterpreter waitingPriorityIsAtLeast: vmThread priority].
  			 (self vmOwnerIs: threadIndex) ifFalse:
  				[self ioWaitOnOSSemaphore: (self addressOf: vmThread osSemaphore)]]].
+ 	coInterpreter assertProcessorStackPointersBelongToCurrentThread.
  	vmOSThread := vmThread osThread.
  	vmThread state: CTMAssignableOrInVM.

Item was added:
+ ----- Method: CogVMSimulator>>assertValidExternalStackPointers (in category 'multi-threading simulation switch') -----
+ assertValidExternalStackPointers
+ 	"This method includes or excludes CoInterpreterMT methods as required.
+ 	 Auto-generated by CogVMSimulator>>ensureMultiThreadingOverridesAreUpToDate"
+ 	^self perform: #assertValidExternalStackPointers
+ 		withArguments: {}
+ 		inSuperclass: (cogThreadManager ifNil: [CoInterpreterPrimitives] ifNotNil: [CoInterpreterMT])!

Item was changed:
  ----- Method: CogVMSimulator>>printRumpCStackForThread: (in category 'rump c stack') -----
  printRumpCStackForThread: thread
  	| range start coldTop |
  	range := self cStackRangeForThreadIndex: thread index.
  	start := range first bitClear: objectMemory tagMask.
  	coldTop := range last.
  	[start < coldTop and: [(objectMemory longAt: start) = 0]] whileTrue:
  		[start := start + objectMemory wordSize].
  	(start = coldTop and: [(objectMemory longAt: start) = 0]) ifTrue:
  	start := start - (2 * objectMemory wordSize) max: range start.
+ 	transcript nextPutAll: 'thread '; print: thread index.
+ 	thread index = cogThreadManager getVMOwner ifTrue: [transcript nextPut: $*].
+ 	transcript cr.
- 	transcript nextPutAll: 'thread '; print: thread index; cr.
  	self printRumpCStackFrom: start to: coldTop cfp: thread cFramePointer csp: thread cStackPointer.
  	range first < start ifTrue:
  		[self print: 'zeros...'; cr]!

Item was changed:
  ----- Method: CogVMSimulator>>printRumpCStackFrom:to:cfp:csp: (in category 'rump c stack') -----
  printRumpCStackFrom: start to: address cfp: cfp csp: csp
  		to: start
  		by: objectMemory wordSize negated
+ 		do: [:addr| | ptrName value |
- 		do: [:addr| | label |
  			self printHex: addr.
+ 			addr = cogit processor sp ifTrue: [ptrName := ' sp'].
+ 			addr = cogit processor fp ifTrue: [ptrName := (ptrName ifNil: [''] ifNotNil: [ptrName, ',']), 'fp'].
+ 			addr = csp ifTrue: [ptrName := (ptrName ifNil: [''] ifNotNil: [ptrName, ',']), 'CSP'].
+ 			addr = cfp ifTrue: [ptrName := (ptrName ifNil: [''] ifNotNil: [ptrName, ',']), 'CFP'].
+ 			ptrName ifNil: [self tab] ifNotNil: [self print: ' ', ptrName, '->'].
+ 			self tab; printHex: (value := objectMemory longAt: addr).
+ 			(cogit lookupAddress: value) ifNotNil:
+ 				[:label| self print: ' ', label].
+ 			self cr]!
- 			addr = cogit processor sp ifTrue: [label := ' sp'].
- 			addr = cogit processor fp ifTrue: [label := (label ifNil: [''] ifNotNil: [label, ',']), 'fp'].
- 			addr = csp ifTrue: [label := (label ifNil: [''] ifNotNil: [label, ',']), 'CSP'].
- 			addr = cfp ifTrue: [label := (label ifNil: [''] ifNotNil: [label, ',']), 'CFP'].
- 			label ifNil: [self tab] ifNotNil: [self print: ' ', label, '->'].
- 			self tab; printHex: (objectMemory longAt: addr); cr]!

Item was changed:
  ----- Method: Cogit>>disassembleTrampolineFor: (in category 'disassembly') -----
  disassembleTrampolineFor: pc
+ 	(self trampolineRangeFor: pc) ifNotNil:
+ 		[:range| self disassembleFrom: range first to: range last]!
- 	| limit |
- 	limit := methodZoneBase - 1.
- 	pc > methodZoneBase ifTrue: [^self].
- 	trampolineTableIndex - 1 to: 0 by: -2 do:
- 		[:i| | addr |
- 		pc >= (addr := (trampolineAddresses at: i) asInteger) ifTrue:
- 			[^self disassembleFrom: addr to: limit].
- 		limit := addr - 1]!

Item was changed:
  ----- Method: Cogit>>lookupAddress: (in category 'disassembly') -----
  lookupAddress: address
  	address < methodZone freeStart ifTrue:
+ 		[^address >= methodZoneBase
- 		[address >= methodZoneBase
  				[(methodZone methodFor: address) ifNotNil:
+ 					 ((cogMethod selector ~= objectMemory nilObject
- 					 ^((cogMethod selector ~= objectMemory nilObject
  					    and: [objectRepresentation couldBeObject: cogMethod selector])
  						ifTrue: [coInterpreter stringOf: cogMethod selector]
  						ifFalse: [cogMethod asInteger hex]),
  					   '@', ((address - cogMethod asInteger) hex allButFirst: 3)]]
+ 				[(self trampolineRangeFor: address) ifNotNil:
+ 					[:range|
+ 					 (self codeEntryNameFor: range first), (address = range first ifTrue: [''] ifFalse: [' + ', (address - range first) hex])]]].
- 				[^address = (self codeEntryFor: address) ifTrue:
- 					[self codeEntryNameFor: address]].
- 		 ^nil].
  	(simulatedTrampolines includesKey: address) ifTrue:
  		[^self labelForSimulationAccessor: (simulatedTrampolines at: address)].
  	(simulatedVariableGetters includesKey: address) ifTrue:
  		[^self labelForSimulationAccessor: (simulatedVariableGetters at: address)].
  	^(coInterpreter lookupAddress: address) ifNil:
  		[address = self cStackPointerAddress
  			ifTrue: [#CStackPointer]
  				[address = self cFramePointerAddress ifTrue:

Item was added:
+ ----- Method: Cogit>>trampolineRangeFor: (in category 'disassembly') -----
+ trampolineRangeFor: pc
+ 	<doNotGenerate>
+ 	| limit |
+ 	limit := methodZoneBase - 1.
+ 	pc > methodZoneBase ifTrue: [^nil].
+ 	trampolineTableIndex - 1 to: 0 by: -2 do:
+ 		[:i| | addr |
+ 		pc >= (addr := (trampolineAddresses at: i) asInteger) ifTrue:
+ 			[^addr to: limit].
+ 		limit := addr - 1].
+ 	^nil!

More information about the Vm-dev mailing list