Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2899.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.2899
Author: eem
Time: 25 November 2020, 7:36:40.903792 pm
UUID: 977272e3-1e46-496a-ad49-a29453fce189
Ancestors: VMMaker.oscog-eem.2898
MTVM: Minor cleanup. In the simulator the REPL is able to compute 3+4, 3*4, 3<<4, 3 raisedTo: 4, etc, without error.
=============== Diff against VMMaker.oscog-eem.2898 ===============
Item was changed:
----- Method: CogThreadManager>>setVMOwner: (in category 'public api') -----
+ setVMOwner: indexOrZero
+ "An ugly accessor used in only three cases:
+ 1. by ownVMFromUnidentifiedThread when the VM is first locked to the thread id
+ of the unidentified thread, and then, once identified, to the thread's index.
+ 2. by wakeVMThreadFor: used by the two-level scheduler to switch threads when
+ a Smalltalk process switch occurs to a process affined to another thread.
+ 3. to release the VM (set the owner to zero)"
+ <inline: #always>
+ vmOwner := indexOrZero.
- setVMOwner: index
- <inline: false>
- vmOwner := index.
self sqLowLevelMFence!
Item was changed:
----- Method: CogThreadManager>>startThreadSubsystem (in category 'public api') -----
startThreadSubsystem
"Initialize the threading subsystem, aborting if there is an error."
| vmThread |
<inline: false>
self assert: threads = nil.
vmOSThread := self ioCurrentOSThread.
numThreadsIncrement := (self ioNumProcessors max: 2) min: 16.
(self growThreadInfosToAtLeast: numThreadsIncrement * 2) ifFalse:
[self error: 'no memory to start thread system'].
+ vmThread := threads at: (vmOwner := 1).
- vmThread := threads at: 1.
vmThread state: CTMInitializing.
self registerVMThread: vmThread.
+ vmThread state: CTMAssignableOrInVM!
- vmThread state: CTMAssignableOrInVM.
- self setVMOwner: 1!
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2898.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.2898
Author: eem
Time: 25 November 2020, 11:35:52.726014 am
UUID: 3d8515f6-7807-4eca-9e5d-9b8f30bca350
Ancestors: VMMaker.oscog-eem.2897
Slang:
Don't use forceNewFileNamed:. It is destructive in complex source configurations such as the one used in Terf where we overlay a repository over the opensmalltalk-vm one.
=============== Diff against VMMaker.oscog-eem.2897 ===============
Item was changed:
----- Method: CCodeGenerator>>storeCodeOnFile:doInlining:doAssertions: (in category 'public') -----
storeCodeOnFile: fileName doInlining: inlineFlag doAssertions: assertionFlag
+ "Store C code for this code base on the given file.
+ Try and reuse the file if it already exists."
- "Store C code for this code base on the given file."
| stream |
+ stream := VMMaker fileNamed: fileName.
- stream := VMMaker forceNewFileNamed: fileName.
stream ifNil: [Error signal: 'Could not open C code file: ', fileName].
+ stream truncate.
self emitCCodeOn: stream doInlining: inlineFlag doAssertions: assertionFlag.
stream close!
Item was added:
+ ----- Method: VMMaker class>>fileNamed: (in category 'file utilities') -----
+ fileNamed: aFilename
+ "Always output files in unix lf format.
+ A single format is friendlier to e.g. external version control systems.
+ The Microsoft and old MacOS classic C compilers all accept lf format files."
+
+ ^(MultiByteFileStream fileNamed: aFilename)
+ lineEndConvention: #lf;
+ yourself!
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2897.mcz
==================== 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
Simulaiton:
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
<api>
<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].
^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.
^vmThread!
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:
[^self].
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
address
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
<doNotGenerate>
+ (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
<doNotGenerate>
address < methodZone freeStart ifTrue:
+ [^address >= methodZoneBase
- [address >= methodZoneBase
ifTrue:
[(methodZone methodFor: address) ifNotNil:
[:cogMethod|
+ ((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)]]
ifFalse:
+ [(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]
ifFalse:
[address = self cFramePointerAddress ifTrue:
[#CFramePointer]]]!
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!
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2896.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.2896
Author: eem
Time: 24 November 2020, 7:08:08.082966 pm
UUID: 0f15d287-0675-49c0-8fed-925890a76ffc
Ancestors: VMMaker.oscog-eem.2895
An alloca version of stackStringValue: (stackEphemeralStringValue:) could be generally useful.
=============== Diff against VMMaker.oscog-eem.2895 ===============
Item was added:
+ ----- Method: InterpreterPlugin>>stackEphemeralStringValue: (in category 'API access') -----
+ stackEphemeralStringValue: index
+ "Convenience to answer a given argument as a C string using stack allocation.
+ Fails if the argument is not a string or there is no memory."
+ <returnTypeC: #'char *'>
+ <inline: #always>
+ | obj sz dstPtr |
+ <var: 'dstPtr' type: #'char *'>
+ obj := interpreterProxy stackValue: index.
+ (interpreterProxy isBytes: obj) ifFalse:
+ [interpreterProxy primitiveFailFor: PrimErrBadArgument.
+ ^nil].
+ sz := interpreterProxy byteSizeOf: obj.
+ dstPtr := self alloca: sz+1.
+ dstPtr ifNil:
+ [interpreterProxy primitiveFailFor: PrimErrNoCMemory.
+ ^nil].
+ self memcpy: dstPtr _: (interpreterProxy firstIndexableField: obj) _: sz.
+ dstPtr at: sz put: 0.
+ ^dstPtr!
Branch: refs/heads/Cog
Home: https://github.com/OpenSmalltalk/opensmalltalk-vm
Commit: dc384cdd1b3df1580af0329b8e9caac73c696866
https://github.com/OpenSmalltalk/opensmalltalk-vm/commit/dc384cdd1b3df1580a…
Author: Eliot Miranda <eliot.miranda(a)gmail.com>
Date: 2020-11-23 (Mon, 23 Nov 2020)
Changed paths:
M platforms/iOS/vm/OSX/sqSqueakOSXApplication+attributes.m
Log Message:
-----------
On MacOS the minor version number needs to be printed with two characters
other wise Smalltalk getSystemAttribute: 1002 answers 110.1 on Big Sur 11.0
instead of 1100.1 as expected.