Leon Matthes uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.threaded-LM.3347.mcz
==================== Summary ====================
Name: VMMaker.threaded-LM.3347
Author: LM
Time: 21 November 2023, 7:55:00.548716 pm
UUID: 164c9256-6fc6-4fbe-b07b-4931fecaddff
Ancestors: VMMaker.threaded-LM.3346
Add argument to ownVM to provide custom flags.
Required for FFI callout flag when an exception occurs.
=============== Diff against VMMaker.threaded-LM.3346 ===============
Item was changed:
----- Method: CoInterpreterMT>>ownVM: (in category 'vm scheduling') -----
ownVM: vmThreadHandle
<public>
<inline: false>
<var: #vmThreadHandle type: #'void *'>
+ ^ self ownVM: vmThreadHandle withFlags: 0!
- <var: #vmThread type: #'CogVMThread *'>
- "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."
- | flags vmThread |
- vmThread := self cCoerce: vmThreadHandle to: #'CogVMThread *'.
- vmThread ifNil:
- [^self ownVMFromUnidentifiedThread].
-
- self assert: vmThread = (cogThreadManager vmThreadAt: vmThread index).
-
- flags := vmThread disownFlags.
-
- (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].
-
- vmThread := cogThreadManager acquireVMFor: vmThread.
- disownCount := disownCount - 1.
-
- disowningVMThread ifNotNil:
- [vmThread = disowningVMThread ifTrue:
- [self assert: (vmThread cFramePointer isNil
- or: [CFramePointer = vmThread cFramePointer and: [CStackPointer = vmThread cStackPointer]]).
- 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 andFlags: flags.
-
- cogit recordEventTrace ifTrue:
- [self recordTrace: TraceOwnVM thing: ConstTwo source: 0].
- ^flags bitAnd: OwnVMForeignThreadFlag!
Item was added:
+ ----- Method: CoInterpreterMT>>ownVM:withFlags: (in category 'vm scheduling') -----
+ ownVM: vmThreadHandle withFlags: additionalFlags
+ <public>
+ <inline: false>
+ <var: #vmThreadHandle type: #'void *'>
+ <var: #vmThread type: #'CogVMThread *'>
+ "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."
+ | flags vmThread |
+ vmThread := self cCoerce: vmThreadHandle to: #'CogVMThread *'.
+ vmThread ifNil:
+ [^self ownVMFromUnidentifiedThread].
+
+ self assert: vmThread = (cogThreadManager vmThreadAt: vmThread index).
+
+ flags := vmThread disownFlags bitOr: additionalFlags.
+
+ (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].
+
+ vmThread := cogThreadManager acquireVMFor: vmThread.
+ disownCount := disownCount - 1.
+
+ disowningVMThread ifNotNil:
+ [vmThread = disowningVMThread ifTrue:
+ [self assert: (vmThread cFramePointer isNil
+ or: [CFramePointer = vmThread cFramePointer and: [CStackPointer = vmThread cStackPointer]]).
+ 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 andFlags: flags.
+
+ cogit recordEventTrace ifTrue:
+ [self recordTrace: TraceOwnVM thing: ConstTwo source: 0].
+ ^flags bitAnd: OwnVMForeignThreadFlag!
Item was changed:
----- Method: InterpreterPrimitives>>primitiveFailForFFIException:at: (in category 'primitive support') -----
primitiveFailForFFIException: exceptionCode at: pc
<var: 'exceptionCode' type: #usqLong>
<var: 'pc' type: #usqInt>
"Set PrimErrFFIException primitive failure and associated exceptionCode (a.k.a.
secondaryErrorCode) and exceptionPC. Under control of the ffiExceptionResponse flag,
if in a primitive with an error code and the inFFIFlags indicate we're in an FFI call,
then fail the primitive.
ffiExceptionResponse < 0 never fail
ffiExceptionResponse = 0 fail if method has a primitive error code (default)
ffiExceptionResponse > 0 always fail"
<public>
((inFFIFlags noMask: DisownVMForFFICall) "i.e. not in an FFI call"
or: [ffiExceptionResponse < 0]) ifTrue: "i.e. never fail"
[^self].
secondaryErrorCode := self cCoerceSimple: exceptionCode to: #sqLong.
exceptionPC := pc.
primFailCode := PrimErrFFIException.
(ffiExceptionResponse > 0 "always fail..."
or: [(objectMemory isOopCompiledMethod: newMethod)
and: [self methodUsesPrimitiveErrorCode: newMethod]]) ifTrue:
+ [self ownVM: nil withFlags: DisownVMForFFICall. "To take ownership but importantly to reset inFFIFlags"
- [self ownVM: DisownVMForFFICall. "To take ownership but importantly to reset inFFIFlags"
self activateFailingPrimitiveMethod]!
Item was changed:
----- Method: StackInterpreter>>ownVM: (in category 'vm scheduling') -----
ownVM: threadIndexAndFlags
<public>
<inline: false>
+ ^ self ownVM: threadIndexAndFlags withFlags: 0!
- "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. While this exists for the threaded FFI VM we use it to reset newMethod and the
- argumentCount after a callback.
-
- Answer -1 if the current thread is unknown to the VM and fails to take ownership."
- <var: 'amInVMThread' declareC: 'extern sqInt amInVMThread(void)'>
- self cppIf: COGMTVM
- ifTrue:
- [self amInVMThread ifFalse:
- [^-1]].
-
- self assert: ((objectMemory isOopCompiledMethod: newMethod)
- and: [(self argumentCountOf: newMethod) = argumentCount]).
-
- "Hack encodings of client state. We use non-immediates (bottom three bits clear)
- for FFI/Plugin doing
- save := self disownVM: FLAGS. ... callout ... self ownVM: save.
- We use immediate integer (bottom bit 1) for callbacks doing
- save := self ownVM: 0. ... callback ... self disownVM: save. return to C"
-
- "If DisownVMForFFICall this is from the FFI plugin and we're returning from a callout."
- (threadIndexAndFlags anyMask: DisownVMForFFICall) ifTrue:
- [inFFIFlags := 0.
- ^threadIndexAndFlags].
-
- "Otherwise this is a callback; stash newMethod on the stack and encode
- argumentCount in the flags retrieved when the calback calls disownVM:."
- self assert: primFailCode = 0.
- self push: newMethod.
- ^objectMemory integerObjectOf: argumentCount!
Item was added:
+ ----- Method: StackInterpreter>>ownVM:withFlags: (in category 'vm scheduling') -----
+ ownVM: threadIndexAndFlags withFlags: additionalFlags
+ <public>
+ <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. While this exists for the threaded FFI VM we use it to reset newMethod and the
+ argumentCount after a callback.
+
+ Answer -1 if the current thread is unknown to the VM and fails to take ownership."
+ <var: 'amInVMThread' declareC: 'extern sqInt amInVMThread(void)'>
+ | flags |
+ flags := threadIndexAndFlags bitOr: additionalFlags.
+ self cppIf: COGMTVM
+ ifTrue:
+ [self amInVMThread ifFalse:
+ [^-1]].
+
+ self assert: ((objectMemory isOopCompiledMethod: newMethod)
+ and: [(self argumentCountOf: newMethod) = argumentCount]).
+
+ "Hack encodings of client state. We use non-immediates (bottom three bits clear)
+ for FFI/Plugin doing
+ save := self disownVM: FLAGS. ... callout ... self ownVM: save.
+ We use immediate integer (bottom bit 1) for callbacks doing
+ save := self ownVM: 0. ... callback ... self disownVM: save. return to C"
+
+ "If DisownVMForFFICall this is from the FFI plugin and we're returning from a callout."
+ (flags anyMask: DisownVMForFFICall) ifTrue:
+ [inFFIFlags := 0.
+ ^flags].
+
+ "Otherwise this is a callback; stash newMethod on the stack and encode
+ argumentCount in the flags retrieved when the calback calls disownVM:."
+ self assert: primFailCode = 0.
+ self push: newMethod.
+ ^objectMemory integerObjectOf: argumentCount!
Leon Matthes uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.threaded-LM.3347.mcz
==================== Summary ====================
Name: VMMaker.threaded-LM.3347
Author: LM
Time: 21 November 2023, 7:55:00.548716 pm
UUID: 164c9256-6fc6-4fbe-b07b-4931fecaddff
Ancestors: VMMaker.threaded-LM.3346
Add argument to ownVM to provide custom flags.
Required for FFI callout flag when an exception occurs.
=============== Diff against VMMaker.threaded-LM.3346 ===============
Item was changed:
----- Method: CoInterpreterMT>>ownVM: (in category 'vm scheduling') -----
ownVM: vmThreadHandle
<public>
<inline: false>
<var: #vmThreadHandle type: #'void *'>
+ ^ self ownVM: vmThreadHandle withFlags: 0!
- <var: #vmThread type: #'CogVMThread *'>
- "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."
- | flags vmThread |
- vmThread := self cCoerce: vmThreadHandle to: #'CogVMThread *'.
- vmThread ifNil:
- [^self ownVMFromUnidentifiedThread].
-
- self assert: vmThread = (cogThreadManager vmThreadAt: vmThread index).
-
- flags := vmThread disownFlags.
-
- (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].
-
- vmThread := cogThreadManager acquireVMFor: vmThread.
- disownCount := disownCount - 1.
-
- disowningVMThread ifNotNil:
- [vmThread = disowningVMThread ifTrue:
- [self assert: (vmThread cFramePointer isNil
- or: [CFramePointer = vmThread cFramePointer and: [CStackPointer = vmThread cStackPointer]]).
- 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 andFlags: flags.
-
- cogit recordEventTrace ifTrue:
- [self recordTrace: TraceOwnVM thing: ConstTwo source: 0].
- ^flags bitAnd: OwnVMForeignThreadFlag!
Item was added:
+ ----- Method: CoInterpreterMT>>ownVM:withFlags: (in category 'vm scheduling') -----
+ ownVM: vmThreadHandle withFlags: additionalFlags
+ <public>
+ <inline: false>
+ <var: #vmThreadHandle type: #'void *'>
+ <var: #vmThread type: #'CogVMThread *'>
+ "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."
+ | flags vmThread |
+ vmThread := self cCoerce: vmThreadHandle to: #'CogVMThread *'.
+ vmThread ifNil:
+ [^self ownVMFromUnidentifiedThread].
+
+ self assert: vmThread = (cogThreadManager vmThreadAt: vmThread index).
+
+ flags := vmThread disownFlags bitOr: additionalFlags.
+
+ (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].
+
+ vmThread := cogThreadManager acquireVMFor: vmThread.
+ disownCount := disownCount - 1.
+
+ disowningVMThread ifNotNil:
+ [vmThread = disowningVMThread ifTrue:
+ [self assert: (vmThread cFramePointer isNil
+ or: [CFramePointer = vmThread cFramePointer and: [CStackPointer = vmThread cStackPointer]]).
+ 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 andFlags: flags.
+
+ cogit recordEventTrace ifTrue:
+ [self recordTrace: TraceOwnVM thing: ConstTwo source: 0].
+ ^flags bitAnd: OwnVMForeignThreadFlag!
Item was changed:
----- Method: InterpreterPrimitives>>primitiveFailForFFIException:at: (in category 'primitive support') -----
primitiveFailForFFIException: exceptionCode at: pc
<var: 'exceptionCode' type: #usqLong>
<var: 'pc' type: #usqInt>
"Set PrimErrFFIException primitive failure and associated exceptionCode (a.k.a.
secondaryErrorCode) and exceptionPC. Under control of the ffiExceptionResponse flag,
if in a primitive with an error code and the inFFIFlags indicate we're in an FFI call,
then fail the primitive.
ffiExceptionResponse < 0 never fail
ffiExceptionResponse = 0 fail if method has a primitive error code (default)
ffiExceptionResponse > 0 always fail"
<public>
((inFFIFlags noMask: DisownVMForFFICall) "i.e. not in an FFI call"
or: [ffiExceptionResponse < 0]) ifTrue: "i.e. never fail"
[^self].
secondaryErrorCode := self cCoerceSimple: exceptionCode to: #sqLong.
exceptionPC := pc.
primFailCode := PrimErrFFIException.
(ffiExceptionResponse > 0 "always fail..."
or: [(objectMemory isOopCompiledMethod: newMethod)
and: [self methodUsesPrimitiveErrorCode: newMethod]]) ifTrue:
+ [self ownVM: nil withFlags: DisownVMForFFICall. "To take ownership but importantly to reset inFFIFlags"
- [self ownVM: DisownVMForFFICall. "To take ownership but importantly to reset inFFIFlags"
self activateFailingPrimitiveMethod]!
Item was changed:
----- Method: StackInterpreter>>ownVM: (in category 'vm scheduling') -----
ownVM: threadIndexAndFlags
<public>
<inline: false>
+ ^ self ownVM: threadIndexAndFlags withFlags: 0!
- "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. While this exists for the threaded FFI VM we use it to reset newMethod and the
- argumentCount after a callback.
-
- Answer -1 if the current thread is unknown to the VM and fails to take ownership."
- <var: 'amInVMThread' declareC: 'extern sqInt amInVMThread(void)'>
- self cppIf: COGMTVM
- ifTrue:
- [self amInVMThread ifFalse:
- [^-1]].
-
- self assert: ((objectMemory isOopCompiledMethod: newMethod)
- and: [(self argumentCountOf: newMethod) = argumentCount]).
-
- "Hack encodings of client state. We use non-immediates (bottom three bits clear)
- for FFI/Plugin doing
- save := self disownVM: FLAGS. ... callout ... self ownVM: save.
- We use immediate integer (bottom bit 1) for callbacks doing
- save := self ownVM: 0. ... callback ... self disownVM: save. return to C"
-
- "If DisownVMForFFICall this is from the FFI plugin and we're returning from a callout."
- (threadIndexAndFlags anyMask: DisownVMForFFICall) ifTrue:
- [inFFIFlags := 0.
- ^threadIndexAndFlags].
-
- "Otherwise this is a callback; stash newMethod on the stack and encode
- argumentCount in the flags retrieved when the calback calls disownVM:."
- self assert: primFailCode = 0.
- self push: newMethod.
- ^objectMemory integerObjectOf: argumentCount!
Item was added:
+ ----- Method: StackInterpreter>>ownVM:withFlags: (in category 'vm scheduling') -----
+ ownVM: threadIndexAndFlags withFlags: additionalFlags
+ <public>
+ <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. While this exists for the threaded FFI VM we use it to reset newMethod and the
+ argumentCount after a callback.
+
+ Answer -1 if the current thread is unknown to the VM and fails to take ownership."
+ <var: 'amInVMThread' declareC: 'extern sqInt amInVMThread(void)'>
+ | flags |
+ flags := threadIndexAndFlags bitOr: additionalFlags.
+ self cppIf: COGMTVM
+ ifTrue:
+ [self amInVMThread ifFalse:
+ [^-1]].
+
+ self assert: ((objectMemory isOopCompiledMethod: newMethod)
+ and: [(self argumentCountOf: newMethod) = argumentCount]).
+
+ "Hack encodings of client state. We use non-immediates (bottom three bits clear)
+ for FFI/Plugin doing
+ save := self disownVM: FLAGS. ... callout ... self ownVM: save.
+ We use immediate integer (bottom bit 1) for callbacks doing
+ save := self ownVM: 0. ... callback ... self disownVM: save. return to C"
+
+ "If DisownVMForFFICall this is from the FFI plugin and we're returning from a callout."
+ (flags anyMask: DisownVMForFFICall) ifTrue:
+ [inFFIFlags := 0.
+ ^flags].
+
+ "Otherwise this is a callback; stash newMethod on the stack and encode
+ argumentCount in the flags retrieved when the calback calls disownVM:."
+ self assert: primFailCode = 0.
+ self push: newMethod.
+ ^objectMemory integerObjectOf: argumentCount!
Branch: refs/heads/Cog
Home: https://github.com/OpenSmalltalk/opensmalltalk-vm
Commit: b88b0008bd169bfa2d1fa5b69aa56377eb165eb3
https://github.com/OpenSmalltalk/opensmalltalk-vm/commit/b88b0008bd169bfa2d…
Author: Marcel Taeumel <marcel.taeumel(a)hpi.de>
Date: 2023-11-21 (Tue, 21 Nov 2023)
Changed paths:
M src/spur32.cog.newspeak/cogit.h
M src/spur32.cog.newspeak/cogitARMv5.c
M src/spur32.cog.newspeak/cogitIA32.c
M src/spur32.cog.newspeak/cointerp.c
M src/spur32.cog.newspeak/gcc3x-cointerp.c
M src/spur32.stack.newspeak/gcc3x-interp.c
M src/spur32.stack.newspeak/interp.c
M src/spur64.cog.newspeak/cogit.h
M src/spur64.cog.newspeak/cogitARMv8.c
M src/spur64.cog.newspeak/cogitX64SysV.c
M src/spur64.cog.newspeak/cogitX64WIN64.c
M src/spur64.cog.newspeak/cointerp.c
M src/spur64.cog.newspeak/gcc3x-cointerp.c
M src/spur64.stack.newspeak/gcc3x-interp.c
M src/spur64.stack.newspeak/interp.c
Log Message:
-----------
NewspeakVM source as per VMMaker.oscog-eem.3339 [ci skip]
Commit: 5b1e8d92688d2093d7c9bc37a88fae5be4317117
https://github.com/OpenSmalltalk/opensmalltalk-vm/commit/5b1e8d92688d2093d7…
Author: Marcel Taeumel <marcel.taeumel(a)hpi.de>
Date: 2023-11-21 (Tue, 21 Nov 2023)
Changed paths:
M .github/workflows/extra-arm.yml
Log Message:
-----------
Merge remote-tracking branch 'origin/Cog' into Cog [ci skip]
Compare: https://github.com/OpenSmalltalk/opensmalltalk-vm/compare/5788e4222687...5b…