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

commits at source.squeak.org commits at source.squeak.org
Sat Jan 22 01:10:57 UTC 2022


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

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

Name: VMMaker.oscog-eem.3142
Author: eem
Time: 21 January 2022, 5:10:43.282744 pm
UUID: ecaa84c0-26c9-440b-bc13-59a6e56c5e7c
Ancestors: VMMaker.oscog-eem.3141

Change the revised primitiveSuspend to behave clkoser to the original, always answeriong the list the receiver was on if bnlocked.  make the newer variant available as a named prim itive (primitiveSuspendV2).  AFAICT using primitiveSuspendV2 breaks lots of things (SqueakSSL tests hang, Virtend login hangs).  So while the idea is right, in practice answering nil if the receiver is suspended while waiting on a condition variable breaks more things than it fixes.

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

Item was changed:
  ----- Method: CoInterpreterPrimitives>>primitiveSuspend (in category 'process primitives') -----
  primitiveSuspend
  	"Primitive. Suspend the receiver, aProcess, such that it can be executed again
  	 by sending #resume. If the given process is not the active process, take it off
  	 its corresponding list. If the list was not its run queue assume it was on some
  	 condition variable (Semaphore, Mutex) and back up its pc to the send that
  	 invoked the wait state the process entered.  Hence when the process resumes
+ 	 it will reenter the wait state. Answer the list the receiver was previously on,
+ 	 unless it was the activ eProcess, in which case answer nil."
- 	 it will reenter the wait state. Answer the list the receiver was previously on iff
- 	 it was not active and not blocked, otherwise answer nil."
  	| process myList myContext ok |
  	process := self stackTop.
  	process = self activeProcess ifTrue:
  		[| inInterpreter |
  		"We're going to switch process, either to an interpreted frame or a machine
  		 code frame. To know whether to return or enter machine code we have to
  		 know from whence we came.  We could have come from the interpreter,
  		 either directly or via a machine code primitive.  We could have come from
  		 machine code.  The instructionPointer tells us where from:"
  		self pop: 1 thenPush: objectMemory nilObject.
  		inInterpreter := instructionPointer >= objectMemory startOfMemory.
  		self transferTo: self wakeHighestPriority from: CSSuspend.
  		^self forProcessPrimitiveReturnToExecutivePostContextSwitch: inInterpreter].
  	myList := objectMemory fetchPointer: MyListIndex ofObject: process.
  	myContext := objectMemory fetchPointer: SuspendedContextIndex ofObject: process.
  	((objectMemory isPointers: myList)
  	 and: [(objectMemory numSlotsOf: myList) > LastLinkIndex
  	 and: [(objectMemory isContext: myContext)
  	 and: [self isResumableContext: myContext]]]) ifFalse:
  		[^self primitiveFailFor: PrimErrBadReceiver].
  	ok := self removeProcess: process fromList: myList.
  	ok ifFalse:
  		[^self primitiveFailFor: PrimErrOperationFailed].
  	objectMemory storePointerUnchecked: MyListIndex ofObject: process withValue: objectMemory nilObject.
  	self assert: RevisedSuspend.
  	(RevisedSuspend
+ 	 and: [(objectMemory fetchClassTagOfNonImm: myList) ~= classLinkedListClassTag]) ifTrue:
+ 		[self backupContext: myContext toBlockingSendTo: myList].
+ 	self pop: 1 thenPush: myList!
- 	 and: [(objectMemory fetchClassTagOfNonImm: myList) ~= classLinkedListClassTag])
- 		ifTrue:
- 			[self backupContext: myContext toBlockingSendTo: myList.
- 			 self pop: 1 thenPush: objectMemory nilObject]
- 		ifFalse:
- 			[self pop: 1 thenPush: myList]!

Item was added:
+ ----- Method: CoInterpreterPrimitives>>primitiveSuspendV2 (in category 'process primitives') -----
+ primitiveSuspendV2
+ 	"Primitive. Suspend the receiver, aProcess, such that it can be executed again
+ 	 by sending #resume. If the given process is not the active process, take it off
+ 	 its corresponding list. If the list was not its run queue assume it was on some
+ 	 condition variable (Semaphore, Mutex) and back up its pc to the send that
+ 	 invoked the wait state the process entered.  Hence when the process resumes
+ 	 it will reenter the wait state. Answer the list the receiver was previously on iff
+ 	 it was not active and not blocked, otherwise answer nil.
+ 	 c.f. primitiveSuspend, which always answers the list the process was on, if blocked."
+ 	<export: true>
+ 	| process myList myContext ok |
+ 	process := self stackTop.
+ 	process = self activeProcess ifTrue:
+ 		[| inInterpreter |
+ 		"We're going to switch process, either to an interpreted frame or a machine
+ 		 code frame. To know whether to return or enter machine code we have to
+ 		 know from whence we came.  We could have come from the interpreter,
+ 		 either directly or via a machine code primitive.  We could have come from
+ 		 machine code.  The instructionPointer tells us where from:"
+ 		self pop: 1 thenPush: objectMemory nilObject.
+ 		inInterpreter := instructionPointer >= objectMemory startOfMemory.
+ 		self transferTo: self wakeHighestPriority from: CSSuspend.
+ 		^self forProcessPrimitiveReturnToExecutivePostContextSwitch: inInterpreter].
+ 	myList := objectMemory fetchPointer: MyListIndex ofObject: process.
+ 	myContext := objectMemory fetchPointer: SuspendedContextIndex ofObject: process.
+ 	((objectMemory isPointers: myList)
+ 	 and: [(objectMemory numSlotsOf: myList) > LastLinkIndex
+ 	 and: [(objectMemory isContext: myContext)
+ 	 and: [self isResumableContext: myContext]]]) ifFalse:
+ 		[^self primitiveFailFor: PrimErrBadReceiver].
+ 	ok := self removeProcess: process fromList: myList.
+ 	ok ifFalse:
+ 		[^self primitiveFailFor: PrimErrOperationFailed].
+ 	objectMemory storePointerUnchecked: MyListIndex ofObject: process withValue: objectMemory nilObject.
+ 	self assert: RevisedSuspend.
+ 	(RevisedSuspend
+ 	 and: [(objectMemory fetchClassTagOfNonImm: myList) ~= classLinkedListClassTag])
+ 		ifTrue:
+ 			[self backupContext: myContext toBlockingSendTo: myList.
+ 			 self pop: 1 thenPush: objectMemory nilObject]
+ 		ifFalse:
+ 			[self pop: 1 thenPush: myList]!

Item was changed:
  ----- Method: CogVMSimulator class>>initialize (in category 'class initialization') -----
  initialize
  	"These are primitives that alter the state of the stack.  They are here simply for assert checking.
  	 After invocation the Cogit should not check for the expected stack delta when these primitives
  	 succeed, because the stack will usually have been modified."
  	StackAlteringPrimitives := #(	primitiveClosureValue primitiveClosureValueWithArgs primitiveClosureValueNoContextSwitch
  									primitiveClone primitiveInstVarAt primitiveSlotAt "because these can cause code compactions..."
  									primitiveEnterCriticalSection primitiveExitCriticalSection
  									primitiveFullClosureValue primitiveFullClosureValueWithArgs primitiveFullClosureValueNoContextSwitch
+ 									primitiveSignal primitiveWait primitiveResume primitiveSuspend primitiveSuspendV2 primitiveYield
- 									primitiveSignal primitiveWait primitiveResume primitiveSuspend primitiveYield
  									primitiveExecuteMethodArgsArray primitiveExecuteMethod
  									primitivePerform primitivePerformWithArgs primitivePerformInSuperclass
  									primitiveTerminateTo primitiveStoreStackp primitiveDoPrimitiveWithArgs) asIdentitySet!

Item was changed:
  ----- Method: StackInterpreterPrimitives>>primitiveSuspend (in category 'process primitives') -----
  primitiveSuspend
  	"Primitive. Suspend the receiver, aProcess, such that it can be executed again
  	 by sending #resume. If the given process is not the active process, take it off
  	 its corresponding list. If the list was not its run queue assume it was on some
  	 condition variable (Semaphore, Mutex) and back up its pc to the send that
  	 invoked the wait state the process entered.  Hence when the process resumes
+ 	 it will reenter the wait state. Answer the list the receiver was previously on,
+ 	 unless it was the activ eProcess, in which case answer nil."
- 	 it will reenter the wait state. Answer the list the receiver was previously on iff
- 	 it was not active and not blocked, otherwise answer nil."
  	| process myList myContext ok |
  	process := self stackTop.
  	process = self activeProcess ifTrue:
  		[self pop: 1 thenPush: objectMemory nilObject.
  		 ^self transferTo: self wakeHighestPriority].
  	myList := objectMemory fetchPointer: MyListIndex ofObject: process.
  	myContext := objectMemory fetchPointer: SuspendedContextIndex ofObject: process.
  	((objectMemory isPointers: myList)
  	 and: [(objectMemory numSlotsOf: myList) > LastLinkIndex
  	 and: [(objectMemory isContext: myContext)
  	 and: [self isResumableContext: myContext]]]) ifFalse:
  		[^self primitiveFailFor: PrimErrBadReceiver].
  	ok := self removeProcess: process fromList: myList.
  	ok ifFalse:
  		[^self primitiveFailFor: PrimErrOperationFailed].
  	objectMemory storePointerUnchecked: MyListIndex ofObject: process withValue: objectMemory nilObject.
  	self assert: RevisedSuspend.
  	(RevisedSuspend
+ 	 and: [(objectMemory fetchClassTagOfNonImm: myList) ~= classLinkedListClassTag]) ifTrue:
+ 		[self backupContext: myContext toBlockingSendTo: myList].
+ 	self pop: 1 thenPush: myList!
- 	 and: [(objectMemory fetchClassTagOfNonImm: myList) ~= classLinkedListClassTag])
- 		ifTrue:
- 			[self backupContext: myContext toBlockingSendTo: myList.
- 			 self pop: 1 thenPush: objectMemory nilObject]
- 		ifFalse:
- 			[self pop: 1 thenPush: myList]!

Item was added:
+ ----- Method: StackInterpreterPrimitives>>primitiveSuspendV2 (in category 'process primitives') -----
+ primitiveSuspendV2
+ 	"Primitive. Suspend the receiver, aProcess, such that it can be executed again
+ 	 by sending #resume. If the given process is not the active process, take it off
+ 	 its corresponding list. If the list was not its run queue assume it was on some
+ 	 condition variable (Semaphore, Mutex) and back up its pc to the send that
+ 	 invoked the wait state the process entered.  Hence when the process resumes
+ 	 it will reenter the wait state. Answer the list the receiver was previously on iff
+ 	 it was not active and not blocked, otherwise answer nil.
+ 	 c.f. primitiveSuspend, which always answers the list the process was on, if blocked."
+ 	<export: true>
+ 	| process myList myContext ok |
+ 	process := self stackTop.
+ 	process = self activeProcess ifTrue:
+ 		[self pop: 1 thenPush: objectMemory nilObject.
+ 		 ^self transferTo: self wakeHighestPriority].
+ 	myList := objectMemory fetchPointer: MyListIndex ofObject: process.
+ 	myContext := objectMemory fetchPointer: SuspendedContextIndex ofObject: process.
+ 	((objectMemory isPointers: myList)
+ 	 and: [(objectMemory numSlotsOf: myList) > LastLinkIndex
+ 	 and: [(objectMemory isContext: myContext)
+ 	 and: [self isResumableContext: myContext]]]) ifFalse:
+ 		[^self primitiveFailFor: PrimErrBadReceiver].
+ 	ok := self removeProcess: process fromList: myList.
+ 	ok ifFalse:
+ 		[^self primitiveFailFor: PrimErrOperationFailed].
+ 	objectMemory storePointerUnchecked: MyListIndex ofObject: process withValue: objectMemory nilObject.
+ 	self assert: RevisedSuspend.
+ 	(RevisedSuspend
+ 	 and: [(objectMemory fetchClassTagOfNonImm: myList) ~= classLinkedListClassTag])
+ 		ifTrue:
+ 			[self backupContext: myContext toBlockingSendTo: myList.
+ 			 self pop: 1 thenPush: objectMemory nilObject]
+ 		ifFalse:
+ 			[self pop: 1 thenPush: myList]!



More information about the Vm-dev mailing list