Branch: refs/heads/Cog
Home: https://github.com/OpenSmalltalk/opensmalltalk-vm
Commit: 9ca32c716e693ad776958ed91fa0694e7517bfab
https://github.com/OpenSmalltalk/opensmalltalk-vm/commit/9ca32c716e693ad776…
Author: Eliot Miranda <eliot.miranda(a)gmail.com>
Date: 2021-09-22 (Wed, 22 Sep 2021)
Changed paths:
M platforms/win32/vm/sqImageFileAccess.h
M platforms/win32/vm/sqWin32Main.c
M platforms/win32/vm/sqWin32Prefs.c
Log Message:
-----------
Win64: get closer to functional first-chance exception handler, and hence stack
dump & ffi exception handling.
Use alloca to avoid frees in fileHandleType.
Fix reading the image from the ini file; certain absolute paths were not
recognised.
Fix reporting errors before the image is loaded; in doing o the old code tried
to dump the SMalltalk stack, even though there was no state, causing a crash.
Branch: refs/heads/Cog
Home: https://github.com/OpenSmalltalk/opensmalltalk-vm
Commit: fd4f2ce0063a50173ae06d3b7d9f73cc0631dcd5
https://github.com/OpenSmalltalk/opensmalltalk-vm/commit/fd4f2ce0063a50173a…
Author: David T. Lewis <lewis(a)mail.msen.com>
Date: 2021-09-22 (Wed, 22 Sep 2021)
Changed paths:
M src/plugins/VectorEnginePlugin/VectorEnginePlugin.c
Log Message:
-----------
Generated source for VectorEnginePlugin-dtl.15
commit 929a0f9cc59d339751db9566e3258f0ee5773c36
Author: Juan Vuletich <juan(a)jvuletich.org>
Date: Wed Sep 22 10:18:03 2021 -0300
Fix a possible crash in VectorEnginePlugin when resizing Cuis main window.
Branch: refs/heads/Cog
Home: https://github.com/OpenSmalltalk/opensmalltalk-vm
Commit: bdb66451e05399b9d81c8333ec4935463de7c668
https://github.com/OpenSmalltalk/opensmalltalk-vm/commit/bdb66451e05399b9d8…
Author: Eliot Miranda <eliot.miranda(a)gmail.com>
Date: 2021-09-22 (Wed, 22 Sep 2021)
Changed paths:
M building/win32x86/common/Makefile.msvc.clang.rules
M building/win32x86/common/Makefile.msvc.msvc.rules
M building/win64x64/common/Makefile.msvc.rules
M platforms/win32/vm/sqWin32Window.c
Log Message:
-----------
Don't include system headers in Windows msvc makefile dependency generation.
Fix a typo. [ci skip]
Branch: refs/heads/Cog
Home: https://github.com/OpenSmalltalk/opensmalltalk-vm
Commit: 61e6b0ef5287cf36e42bf47ed7ec568367f608fc
https://github.com/OpenSmalltalk/opensmalltalk-vm/commit/61e6b0ef5287cf36e4…
Author: Eliot Miranda <eliot.miranda(a)gmail.com>
Date: 2021-09-22 (Wed, 22 Sep 2021)
Changed paths:
M platforms/iOS/vm/Common/Classes/sqSqueakMainApp.m
M platforms/iOS/vm/Common/Classes/sqSqueakMainApplication.m
M platforms/iOS/vm/OSX/sqSqueakOSXApplication.m
M src/spur32.cog/cointerp.c
M src/spur32.cog/cointerp.h
M src/spur32.cog/gcc3x-cointerp.c
M src/spur32.sista/cointerp.c
M src/spur32.sista/cointerp.h
M src/spur32.sista/gcc3x-cointerp.c
M src/spur64.cog/cointerp.c
M src/spur64.cog/cointerp.h
M src/spur64.cog/gcc3x-cointerp.c
M src/spur64.sista/cointerp.c
M src/spur64.sista/cointerp.h
M src/spur64.sista/gcc3x-cointerp.c
M src/v3.cog/cointerp.c
M src/v3.cog/cointerp.h
M src/v3.cog/gcc3x-cointerp.c
Log Message:
-----------
CogVM source as per VMMaker.oscog-eem.3074
CoInterpreter:
Fix bad bug in justActivateNewMethod:. If newMethod was cogged and the method
must be activated as an interpreter method (ie primitiveFailForFFIException:at:)then the old code did not access the true methodHeader, causing a crash.
Eliminate unnecessary instructionPointer casts; it is unsigned.
On Mac reorganize setting signals to eliminate unnecessary call in stack VMs
and add a secret option to cause the VM to wait for a debugger to attach on
receiving a sigsegv (a limitation of lldb on MACH). This allowed the above issue
to be debugged.
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.3074.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.3074
Author: eem
Time: 22 September 2021, 9:30:01.013156 am
UUID: fc13f6e9-1cc3-4535-a31d-5e7f5dafe75f
Ancestors: VMMaker.oscog-eem.3073
CoInterpreter:
Fix bad bug in justActivateNewMethod:. If newMethod was cogged and the method must be activated as an interpreter method (i.e. primitiveFailForFFIException:at:) then the old code did not access the true methodHeader, causing a crash.
Eliminate unnecessary instructionPointer casts; it is unsigned.
=============== Diff against VMMaker.oscog-eem.3073 ===============
Item was changed:
----- Method: CoInterpreter>>activateFailingPrimitiveMethod (in category 'primitive support') -----
activateFailingPrimitiveMethod
+ "Assuming the primFailCode and any other relevant failure
+ state has been set, switch the VM to the interpreter, and
+ activate newMethod (which is expected to have a primitive)."
- "Assuming the primFailCode (and any other relevant failure state) has been set,
- switch the VM to the interpreter if necessary (if in the CoInterpreter executing machine code),
- and activate the newMethod (which is expected to have a primitive)."
self assert: primFailCode ~= 0.
self assert: (objectMemory addressCouldBeObj: newMethod).
self assert: (objectMemory isCompiledMethod: newMethod).
self assert: (self primitiveIndexOf: newMethod) ~= 0.
self justActivateNewMethod: true. "Frame must be interpreted"
cogit ceInvokeInterpret.
"NOTREACHED"
^nil!
Item was changed:
----- Method: CoInterpreter>>callbackEnter: (in category 'callback support') -----
callbackEnter: callbackID
"Re-enter the interpreter for executing a callback"
| currentCStackPointer currentCFramePointer wasInMachineCode calledFromMachineCode |
<volatile>
<export: true>
<var: #currentCStackPointer type: #usqIntptr_t>
<var: #currentCFramePointer type: #usqIntptr_t>
<var: #callbackID type: #'sqInt *'>
"For now, do not allow a callback unless we're in a primitiveResponse"
(self asserta: primitiveFunctionPointer ~= 0) ifFalse:
[^false].
self assert: primFailCode = 0.
"Check if we've exceeded the callback depth"
(self asserta: jmpDepth < MaxJumpBuf) ifFalse:
[^false].
jmpDepth := jmpDepth + 1.
wasInMachineCode := self isMachineCodeFrame: framePointer.
calledFromMachineCode := instructionPointer <= objectMemory startOfMemory.
"Suspend the currently active process"
suspendedCallbacks at: jmpDepth put: self activeProcess.
"We need to preserve newMethod explicitly since it is not activated yet
and therefore no context has been created for it. If the caller primitive
for any reason decides to fail we need to make sure we execute the correct
method and not the one 'last used' in the call back"
suspendedMethods at: jmpDepth put: newMethod.
self flag: 'need to debug this properly. Conceptually it is the right thing to do but it crashes in practice'.
false
ifTrue:
["Signal external semaphores since a signalSemaphoreWithIndex: request may
have been issued immediately prior to this callback before the VM has any
chance to do a signalExternalSemaphores in checkForEventsMayContextSwitch:"
self signalExternalSemaphores.
"If no process is awakened by signalExternalSemaphores then transfer
to the highest priority runnable one."
(suspendedCallbacks at: jmpDepth) = self activeProcess ifTrue:
[self transferTo: self wakeHighestPriority from: CSCallbackLeave]]
ifFalse:
[self transferTo: self wakeHighestPriority from: CSCallbackLeave].
"Typically, invoking the callback means that some semaphore has been
signaled to indicate the callback. Force an interrupt check as soon as possible."
self forceInterruptCheck.
"Save the previous CStackPointers..."
currentCStackPointer := CStackPointer.
currentCFramePointer := CFramePointer.
cogit assertCStackWellAligned.
(self _setjmp: (jmpBuf at: jmpDepth)) = 0 ifTrue: "Fill in callbackID"
[callbackID at: 0 put: jmpDepth.
self enterSmalltalkExecutive.
self assert: false "NOTREACHED"].
"Restore the previous CStackPointers..."
self setCFramePointer: currentCFramePointer setCStackPointer: currentCStackPointer.
"Transfer back to the previous process so that caller can push result"
self putToSleep: self activeProcess yieldingIf: preemptionYields.
self transferTo: (suspendedCallbacks at: jmpDepth) from: CSCallbackLeave.
newMethod := suspendedMethods at: jmpDepth. "see comment above"
argumentCount := self argumentCountOf: newMethod.
self assert: wasInMachineCode = (self isMachineCodeFrame: framePointer).
calledFromMachineCode
ifTrue:
+ [instructionPointer >= objectMemory startOfMemory ifTrue:
- [instructionPointer asUnsignedInteger >= objectMemory startOfMemory ifTrue:
[self iframeSavedIP: framePointer put: instructionPointer.
instructionPointer := cogit ceReturnToInterpreterPC]]
ifFalse:
["Even if the context was flushed to the heap and rebuilt in transferTo:from:
above it will remain an interpreted frame because the context's pc would
remain a bytecode pc. So the instructionPointer must also be a bytecode pc."
self assert: (self isMachineCodeFrame: framePointer) not.
self assert: instructionPointer > objectMemory startOfMemory].
self assert: primFailCode = 0.
jmpDepth := jmpDepth-1.
^true!
Item was changed:
----- Method: CoInterpreter>>ensurePushedInstructionPointer (in category 'enilopmarts') -----
ensurePushedInstructionPointer
"We're about to make some transition to a machine code method which
requires the instructionPointer must be on the stack. 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. Make sure the instruction pointer is pushed and/or saved."
+ instructionPointer >= objectMemory startOfMemory
- instructionPointer asUnsignedInteger >= objectMemory startOfMemory
ifTrue:
"invoked directly from the interpreter"
[self iframeSavedIP: framePointer put: instructionPointer.
self push: cogit ceReturnToInterpreterPC]
ifFalse:
["instructionPointer == cogit ceReturnToInterpreterPC
ifTrue: [invoked from the interpreter via a machine code primitive]
ifFalse: [invoked from machine code].
If in the first case the bytecode instructionPointer has already been
saved in iframeSavedIP so all we need to do is push the instructionPointer."
self push: instructionPointer]!
Item was changed:
----- Method: CoInterpreter>>executeNewMethod (in category 'message sending') -----
executeNewMethod
"Execute newMethod - either primitiveFunctionPointer must be set directly
(i.e. from primitiveExecuteMethod et al), or it would have been set probing
the method cache (i.e. primitivePerform et al)."
| methodHeader inInterpreter |
inInterpreter := instructionPointer >= objectMemory startOfMemory.
primitiveFunctionPointer ~= 0 ifTrue:
[self isPrimitiveFunctionPointerAnIndex ifTrue:
[self externalQuickPrimitiveResponse.
self return: self popStack toExecutive: inInterpreter.
^nil].
"slowPrimitiveResponse may of course context-switch. If so we must reenter the
new process appopriately, returning only if we've reached here directly from the
interpreter and have found an interpreter frame. The instructionPointer tells us
from whence we came."
self slowPrimitiveResponse ifTrue:
[self return: self popStack toExecutive: inInterpreter.
^nil]].
methodHeader := self rawHeaderOf: newMethod.
"if not primitive, or primitive failed, activate the method"
(self isCogMethodReference: methodHeader)
ifTrue:
+ [instructionPointer >= objectMemory startOfMemory ifTrue:
- [instructionPointer asUnsignedInteger >= objectMemory startOfMemory ifTrue:
[self iframeSavedIP: framePointer put: instructionPointer asInteger.
instructionPointer := cogit ceReturnToInterpreterPC].
self activateNewCogMethod: (self cCoerceSimple: methodHeader to: #'CogMethod *') inInterpreter: inInterpreter]
ifFalse:
[self activateNewMethod]!
Item was changed:
----- Method: CoInterpreter>>executeNewMethodJitting (in category 'message sending') -----
executeNewMethodJitting
"Execute newMethod - either primitiveFunctionPointer must be set directly
(i.e. from primitiveExecuteMethod et al), or it would have been set probing
the method cache (i.e. primitivePerform et al).
Eagerly compile it if appropriate so that doits are fast."
| methodHeader inInterpreter |
inInterpreter := instructionPointer >= objectMemory startOfMemory.
primitiveFunctionPointer ~= 0 ifTrue:
[self isPrimitiveFunctionPointerAnIndex ifTrue:
[self externalQuickPrimitiveResponse.
self return: self popStack toExecutive: inInterpreter.
^nil].
"slowPrimitiveResponse may of course context-switch. If so we must reenter the
new process appopriately, returning only if we've reached here directly from the
interpreter and have found an interpreter frame. The instructionPointer tells us
from whence we came."
self slowPrimitiveResponse ifTrue:
[self return: self popStack toExecutive: inInterpreter.
^nil]].
"Eagerly compile it if appropriate so that doits are fast."
methodHeader := self rawHeaderOf: newMethod.
(self isCogMethodReference: methodHeader) ifFalse:
[(self methodWithHeaderShouldBeCogged: methodHeader)
ifTrue:
[cogit cog: newMethod selector: objectMemory nilObject.
methodHeader := self rawHeaderOf: newMethod]
ifFalse: [self maybeFlagMethodAsInterpreted: newMethod]].
"if not primitive, or primitive failed, activate the method"
(self isCogMethodReference: methodHeader)
ifTrue:
+ [instructionPointer >= objectMemory startOfMemory ifTrue:
- [instructionPointer asUnsignedInteger >= objectMemory startOfMemory ifTrue:
[self iframeSavedIP: framePointer put: instructionPointer asInteger.
instructionPointer := cogit ceReturnToInterpreterPC].
self activateNewCogMethod: (self cCoerceSimple: methodHeader to: #'CogMethod *') inInterpreter: inInterpreter]
ifFalse:
[self activateNewMethod]!
Item was changed:
----- Method: CoInterpreter>>justActivateNewMethod: (in category 'message sending') -----
justActivateNewMethod: mustBeInterpreterFrame
| methodHeader cogMethod numArgs numTemps rcvr initialIP |
- <var: #cogMethod type: #'CogMethod *'>
<var: #initialIP type: #usqInt>
<inline: true>
methodHeader := self rawHeaderOf: newMethod.
+ cogMethod := nil.
+ (self isCogMethodReference: methodHeader) ifTrue:
- (mustBeInterpreterFrame not
- and: [self isCogMethodReference: methodHeader]) ifTrue:
[cogMethod := self cCoerceSimple: methodHeader to: #'CogMethod *'.
+ methodHeader := cogMethod methodHeader.
+ mustBeInterpreterFrame ifTrue:
+ [cogMethod := nil]].
- methodHeader := cogMethod methodHeader].
numTemps := self temporaryCountOfMethodHeader: methodHeader.
numArgs := self argumentCountOfMethodHeader: methodHeader.
rcvr := self stackValue: numArgs. "could new rcvr be set at point of send?"
self assert: (objectMemory isOopForwarded: rcvr) not.
(cogMethod notNil
+ and: [(self isMachineCodeFrame: framePointer) not]) ifTrue:
+ [instructionPointer >= objectMemory startOfMemory ifTrue:
+ [self iframeSavedIP: framePointer put: instructionPointer].
- and: [instructionPointer asUnsignedInteger >= objectMemory startOfMemory]) ifTrue:
- [self iframeSavedIP: framePointer put: instructionPointer.
instructionPointer := cogit ceReturnToInterpreterPC].
self push: instructionPointer.
self push: framePointer.
framePointer := stackPointer.
initialIP := self initialIPForHeader: methodHeader method: newMethod.
cogMethod
ifNotNil:
[self push: cogMethod asUnsignedInteger.
self push: objectMemory nilObject. "FoxThisContext field"
instructionPointer := cogMethod asUnsignedInteger + cogMethod stackCheckOffset]
ifNil:
[self push: newMethod.
self setMethod: newMethod methodHeader: methodHeader.
self push: objectMemory nilObject. "FoxThisContext field"
self push: (self encodeFrameFieldHasContext: false isBlock: false numArgs: numArgs).
self push: 0. "FoxIFSavedIP"
instructionPointer := initialIP - 1].
self push: rcvr.
"clear remaining temps to nil"
+ numArgs + 1 to: numTemps do:
- numArgs+1 to: numTemps do:
[:i | self push: objectMemory nilObject].
(self methodHeaderHasPrimitive: methodHeader) ifTrue:
["Skip the CallPrimitive bytecode, if it's there, and store the error code if the method starts
with a long store temp. Strictly no need to skip the store because it's effectively a noop."
cogMethod ifNil:
[instructionPointer := instructionPointer + (self sizeOfCallPrimitiveBytecode: methodHeader)].
primFailCode ~= 0 ifTrue:
[self reapAndResetErrorCodeTo: stackPointer header: methodHeader]].
^methodHeader!
Item was changed:
----- Method: CoInterpreterMT>>preemptDisowningThread (in category 'vm scheduling') -----
preemptDisowningThread
"Set the relevant state for disowningVMThread so that it can resume after
being preempted and set disowningVMThread to nil to indicate preemption.
N.B. This should only be sent from checkPreemptionOfDisowningThread.
There are essentially four things to do.
a) save the VM's notion of the current C stack pointers; these are pointers
into a thread's stack and must be saved and restored in thread switch.
b) save the VM's notion of the current Smalltalk execution point. This is
simply the suspend half of a process switch that saves the current context
in the current process.
c) add the process to the thread's set of AWOL processes so that the scheduler
won't try to run the process while the thread has disowned the VM.
d) save the in-primitive VM state, newMethod and argumentCount
ownVM: will restore the VM context as of disownVM: from the above when it
finds it has been preempted."
| activeProc activeContext preemptedThread |
<var: #preemptedThread type: #'CogVMThread *'>
<inline: false>
self assert: disowningVMThread notNil.
self assert: (disowningVMThread state = CTMUnavailable
or: [disowningVMThread state = CTMWantingOwnership]).
self assertCStackPointersBelongToDisowningThread.
cogit recordEventTrace ifTrue:
[self recordTrace: TracePreemptDisowningThread
thing: (objectMemory integerObjectOf: disowningVMThread index)
source: 0].
disowningVMThread cStackPointer: CStackPointer.
disowningVMThread cFramePointer: CFramePointer.
activeProc := self activeProcess.
self assert: (objectMemory fetchPointer: MyListIndex ofObject: activeProc) = objectMemory nilObject.
objectMemory
storePointer: MyListIndex
ofObject: activeProc
withValue: (objectMemory splObj: ProcessInExternalCodeTag).
activeContext := self ensureFrameIsMarried: framePointer SP: stackPointer.
objectMemory
storePointer: SuspendedContextIndex
ofObject: activeProc
withValue: activeContext.
"The instructionPointer must be pushed because the convention for inactive stack pages is that the
instructionPointer is top of stack. We need to know if this primitive is called from machine code
because the invariant that the return pc of an interpreter callee calling a machine code caller is
ceReturnToInterpreterPC must be maintained."
self push: instructionPointer.
self externalWriteBackHeadFramePointers.
"Since pushing the awol process may realloc disowningVMThread we need to reassign.
But since we're going to nil disowningVMThread anyway we can assign to a local."
preemptedThread := cogThreadManager pushAWOLProcess: activeProc on: disowningVMThread.
disowningVMThread := nil.
preemptedThread priority: (self quickFetchInteger: PriorityIndex ofObject: activeProc).
(self ownerIndexOfProcess: activeProc) = 0
ifTrue: [self setOwnerIndexOfProcess: activeProc to: preemptedThread index bind: false]
ifFalse: [self assert: (self ownerIndexOfProcess: activeProc) = preemptedThread index].
preemptedThread
newMethodOrNull: newMethod;
argumentCount: argumentCount;
primitiveFunctionPointer: primitiveFunctionPointer;
+ inMachineCode: instructionPointer <= objectMemory startOfMemory!
- inMachineCode: instructionPointer asUnsignedInteger <= objectMemory startOfMemory!
Item was changed:
----- Method: CoInterpreterMT>>saveVMStateFor:threadIndexAndFlags: (in category 'vm scheduling') -----
saveVMStateFor: vmThread threadIndexAndFlags: threadIndexAndFlags
"Save the VM state for the disowning thread."
vmThread
newMethodOrNull: newMethod;
argumentCount: argumentCount;
primitiveFunctionPointer: primitiveFunctionPointer;
+ inMachineCode: instructionPointer < objectMemory startOfMemory!
- inMachineCode: instructionPointer asUnsignedInteger <= objectMemory startOfMemory!
Item was changed:
----- Method: CogThreadManager>>vmThreadAt: (in category 'public api') -----
vmThreadAt: index
+ <returnTypeC: #'CogVMThread *'>
self assert: (index between: 0 and: numThreads).
^index > 0 ifTrue: [threads at: index]!
Branch: refs/heads/Cog
Home: https://github.com/OpenSmalltalk/opensmalltalk-vm
Commit: 4792edb5e22256d5a594ea0e8b40224f116ac1db
https://github.com/OpenSmalltalk/opensmalltalk-vm/commit/4792edb5e22256d5a5…
Author: Eliot Miranda <eliot.miranda(a)gmail.com>
Date: 2021-09-21 (Tue, 21 Sep 2021)
Changed paths:
M building/macos32x86/common/Makefile.rules
M building/macos64ARMv8/common/Makefile.rules
M building/macos64x64/common/Makefile.rules
M platforms/Cross/plugins/IA32ABI/AlienSUnitTestProcedures.c
M platforms/Cross/plugins/SqueakFFIPrims/sqFFI.h
A platforms/Cross/plugins/SqueakFFIPrims/sqFFITestFuncExports.h
M platforms/Cross/vm/sqNamedPrims.c
M src/plugins/SqueakFFIPrims/ARM32FFIPlugin.c
M src/plugins/SqueakFFIPrims/ARM64FFIPlugin.c
M src/plugins/SqueakFFIPrims/IA32FFIPlugin.c
M src/plugins/SqueakFFIPrims/X64SysVFFIPlugin.c
M src/plugins/SqueakFFIPrims/X64Win64FFIPlugin.c
Log Message:
-----------
CogVM source as per VMMaker.oscog-eem.3073
Slang: add mechanism for an internal plugin to include additional exports, hence allowing the functions in sqFFITestFunctions.c to be exported from SqueakFFIPrims when compiled as an internal plugin.
SqueakFFIPrims: add sqFFITestFuncExports.h which exports the test functions when
SqueakFFIPrims is compiled as an internal plugin. Move the declarations and
types to sqFFI.h.
Don't compile/export test functions in IA32ABI unless ALIEN_TEST_FUNCTIONS is
defined on the command line, hence resolving conflict with SqueakFFIPrims'
test functions.
Add a hack to sqNamedPrims.c to allow it to answer an internal module from
ioLoadModuleOfLength. Note that search through internal exports in
findInternalFunctionIn is exhaustive (!!). This cannot stand ;-)
Fix the Mac makefiles to remove the dependence on the dep file,
as this was forcing recompilation all the time.