Eliot Miranda uploaded a new version of FFI-Tests to project FFI:
http://source.squeak.org/FFI/FFI-Tests-eem.71.mcz
==================== Summary ====================
Name: FFI-Tests-eem.71
Author: eem
Time: 11 March 2023, 5:46:13.184007 pm
UUID: db60f962-7d44-48b3-bce4-734c13fe6641
Ancestors: FFI-Tests-mt.70
Update FFIPluginTests>>arm64Check now that the latest version of the plugin is ok.
=============== Diff against FFI-Tests-mt.70 ===============
Item was changed:
----- Method: FFIPluginTests>>arm64Check (in category 'support') -----
arm64Check
+ "If required, mark the current test as failure to avoid segmentation fault
+ due to issues in older versions of the plugin code."
- "Mark the current test as failure to avoid segmentation fault due to issues in the plugin code."
+ (FFIPlatformDescription current isARM
+ and: [FFIPlatformDescription current wordSize = 8
+ and: [Smalltalk vmVMMakerVersion < 3309]]) ifTrue:
+ [self fail: 'Not supported. Segmentation fault avoided.']!
- (FFIPlatformDescription current isARM and: [FFIPlatformDescription current wordSize = 8])
- ifTrue: [self fail: 'Not supported. Segmentation fault avoided.'].!
Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.2098.mcz
==================== Summary ====================
Name: Morphic-mt.2098
Author: mt
Time: 10 March 2023, 10:51:25.580811 am
UUID: 756190bd-216e-ae41-b60a-4f3a32df3ec4
Ancestors: Morphic-mt.2097
Whoops... forgot about EToys' cartesian origin...
=============== Diff against Morphic-mt.2097 ===============
Item was changed:
----- Method: ProportionalSplitterMorph>>splitterAbove (in category 'queries - adjacent splitters') -----
splitterAbove
| immediatelyAbove |
immediatelyAbove := nil.
self siblingSplittersDo:
+ [ : each |
+ each top < self top ifTrue:
- [ : each | "Splitter y's map 0 at the bottom."
- each top > self top ifTrue:
[ immediatelyAbove
ifNil: [ immediatelyAbove := each ]
ifNotNil:
+ [ each top > immediatelyAbove top ifTrue: [ immediatelyAbove := each ] ] ] ].
- [ each top < immediatelyAbove top ifTrue: [ immediatelyAbove := each ] ] ] ].
^ immediatelyAbove!
Item was changed:
----- Method: ProportionalSplitterMorph>>splitterBelow (in category 'queries - adjacent splitters') -----
splitterBelow
| immediatelyBelow |
immediatelyBelow := nil.
self siblingSplittersDo:
+ [ : each | each top > self top ifTrue:
- [ : each | each top < self top ifTrue:
[ immediatelyBelow
ifNil: [ immediatelyBelow := each ]
ifNotNil:
+ [ each top < immediatelyBelow top ifTrue: [ immediatelyBelow := each ] ] ] ].
- [ each top > immediatelyBelow top ifTrue: [ immediatelyBelow := each ] ] ] ].
^ immediatelyBelow!
Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.2097.mcz
==================== Summary ====================
Name: Morphic-mt.2097
Author: mt
Time: 10 March 2023, 10:47:19.416811 am
UUID: 685bb901-7e7e-4c4f-934f-92491a195850
Ancestors: Morphic-mt.2096
Fix similar to the recent one in #splitterLeft and #splitterRight.
=============== Diff against Morphic-mt.2096 ===============
Item was changed:
----- Method: ProportionalSplitterMorph>>splitterAbove (in category 'queries - adjacent splitters') -----
splitterAbove
| immediatelyAbove |
immediatelyAbove := nil.
self siblingSplittersDo:
[ : each | "Splitter y's map 0 at the bottom."
+ each top > self top ifTrue:
- each y > self y ifTrue:
[ immediatelyAbove
ifNil: [ immediatelyAbove := each ]
ifNotNil:
+ [ each top < immediatelyAbove top ifTrue: [ immediatelyAbove := each ] ] ] ].
- [ each y < immediatelyAbove y ifTrue: [ immediatelyAbove := each ] ] ] ].
^ immediatelyAbove!
Item was changed:
----- Method: ProportionalSplitterMorph>>splitterBelow (in category 'queries - adjacent splitters') -----
splitterBelow
| immediatelyBelow |
immediatelyBelow := nil.
self siblingSplittersDo:
+ [ : each | each top < self top ifTrue:
- [ : each | each y < self y ifTrue:
[ immediatelyBelow
ifNil: [ immediatelyBelow := each ]
ifNotNil:
+ [ each top > immediatelyBelow top ifTrue: [ immediatelyBelow := each ] ] ] ].
- [ each y > immediatelyBelow y ifTrue: [ immediatelyBelow := each ] ] ] ].
^ immediatelyBelow!
Eliot Miranda uploaded a new version of FFI-Kernel to project FFI:
http://source.squeak.org/FFI/FFI-Kernel-eem.227.mcz
==================== Summary ====================
Name: FFI-Kernel-eem.227
Author: eem
Time: 9 March 2023, 6:18:37.991467 pm
UUID: 9a37d6b3-7dc2-4d71-800b-8c5e834f88ad
Ancestors: FFI-Kernel-eem.226
Fix a bad thread safety bug with ExternalStructure and ExternalType class var StructTypes.
StructTypes is a WeakValueDIctionary from class name (subclass of ExternalStructure) to instance of ExternalStructureType. Because the associations in StructTypes have weak values and are the only reference in ther system to the manufactured ExternalStructureType instance, the garbage collector *will* set the association's valeu to nil sooner or later. This provides a nasty potential for the assert in ExternalUnknownType class>>#newTypeForUnknownNamed: to fail because two threads are both in the process of computing a new type via ExternalType class>>#structTypeNamed:.
The fix is to have ExternalStructure maintain a strong reference to the manufactured type in a class inst var, externalType, and to void this type, and the entry in StructTypes whenever a method is added or removed from the instance side of ExternalStructure.
=============== Diff against FFI-Kernel-eem.226 ===============
Item was changed:
ExternalObject subclass: #ExternalStructure
instanceVariableNames: ''
classVariableNames: 'LogAccessorSourceCode'
poolDictionaries: 'ExternalTypePool FFIConstants'
category: 'FFI-Kernel'!
ExternalStructure class
+ instanceVariableNames: 'compiledSpec byteAlignment externalType'!
- instanceVariableNames: 'compiledSpec byteAlignment'!
!ExternalStructure commentStamp: 'eem 6/26/2019 15:26' prior: 0!
An ExternalStructure is for representing external data that is
- either a structure composed of different fields (a struct of C language)
- or an alias for another type (like a typedef of C language)
It reserves enough bytes of data for representing all the fields.
The data is stored into the handle instance variable which can be of two different types:
- ExternalAddress
If the handle is an external address then the object described does not reside in the Smalltalk object memory.
- ByteArray
If the handle is a byte array then the object described resides in Smalltalk memory.
Instance Variables (class side)
byteAlignment: <Integer>
compiledSpec: <WordArray>
byteAlignment
- the required alignment for the structure
compiledSpec
- the bit-field definiton of the structure in the ExternalType encoding understood by the VM's FFI call marshalling machinery.
A specific structure is defined by subclassing ExternalStructure and specifying its #fields via a class side method.
For example if we define a subclass:
ExternalStructure subclass: #StructExample
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'garbage'.
Then declare the fields like this:
StructExample class compile: 'fields ^#( (name ''char*'') (color ''ulong'') )' classified: 'garbage'.
It means that this type is composed of two different fields:
- a string (accessed thru the field #name)
- and an unsigned 32bit integer (accessed thru the field #color).
It represents the following C type:
struct StructExample {char *name; uint32_t color; };
The accessors for those fields can be generated automatically like this:
StructExample defineFields.
As can be verified in a Browser:
StructExample browse.
We see that name and color fields are stored sequentially in different zones of data.
The total size of the structure can be verified with:
StructExample byteSize = (Smalltalk wordSize + 4).
An ExternalStructure can also be used for defining an alias.
The fields definition must contain only 2 elements: an eventual accessor (or nil) and the type.
For example, We can define a machine dependent 'unsigned long' like this:
ExternalStructure subclass: #UnsignedLong
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'garbage'.
Then set the fields like this:
UnsignedLong class compile: 'fields ^(Smalltalk wordSize=4 or: [Smalltalk platformName=''Win64''])
ifTrue: [#(nil ''ulong'')] ifFalse: [#(nil ''ulonglong'')]' classified: 'garbage'.
And verify the size on current platform:
UnsignedLong byteSize.
Then, the class names 'UnsignedLong' and 'StructExamples' acts as a type specification.
They can be used for composing other types, and for defining prototype of external functions:
LibraryExample>>initMyStruct: aStructExample name: name color: anInteger
<cdecl: void 'init_my_struct'( StructExample * char * UnsignedLong )>
self externalCallFailed
!
ExternalStructure class
+ instanceVariableNames: 'compiledSpec byteAlignment externalType'!
- instanceVariableNames: 'compiledSpec byteAlignment'!
Item was added:
+ ----- Method: ExternalStructure class>>addSelectorSilently:withMethod: (in category 'accessing method dictionary') -----
+ addSelectorSilently: selector withMethod: compiledMethod
+ "Override to void the strong reference to the externalType"
+ self voidExternalType.
+ ^super addSelectorSilently: selector withMethod: compiledMethod!
Item was changed:
----- Method: ExternalStructure class>>externalType (in category 'external type') -----
externalType
+ "Answer an external type describing the receiver as a structure.
+ Keep a strong reference to it so that it doesn't get garbage collected
+ from StructTypes immediately."
+ ^externalType := ExternalType structTypeNamed: self name!
- "Return an external type describing the receiver as a structure"
- ^ExternalType structTypeNamed: self name!
Item was added:
+ ----- Method: ExternalStructure class>>removeSelector: (in category 'accessing method dictionary') -----
+ removeSelector: selector
+ "Override to void the strong reference to the externalType"
+ self voidExternalType.
+ ^super removeSelector: selector!
Item was added:
+ ----- Method: ExternalStructure class>>voidExternalType (in category 'private') -----
+ voidExternalType
+ externalType := nil.
+ ExternalType voidStructTypeFor: self!
Item was added:
+ ----- Method: ExternalType class>>voidStructTypeFor: (in category 'housekeeping') -----
+ voidStructTypeFor: anExternalStructureClass
+ (StructTypes associationAt: anExternalStructureClass name ifAbsent: [^self]) value: nil!