Marcel Taeumel uploaded a new version of FFI-Kernel to project FFI:
http://source.squeak.org/FFI/FFI-Kernel-mt.193.mcz
==================== Summary ====================
Name: FFI-Kernel-mt.193
Author: mt
Time: 9 August 2021, 7:13:55.720391 pm
UUID: 57c1d500-fd24-7c40-adfb-767cdd35e6da
Ancestors: FFI-Kernel-mt.192
Fix bug in compilation order of ExternalStructure fields.
=============== Diff against FFI-Kernel-mt.192 ===============
Item was changed:
----- Method: ExternalStructure class>>allStructuresInCompilationOrder (in category 'system startup') -----
allStructuresInCompilationOrder
"Answers a list of all known structure (and packed structures and unions) in ascending order of field compilation."
| unordered ordered |
self == ExternalStructure
ifFalse: [self error: 'Correct compilation order cannot be guaranteed for a partial list of structure classes.'].
unordered := self allSubclasses reject: [:ea | ea isSkipped].
ordered := OrderedCollection new: unordered size.
[unordered notEmpty] whileTrue:
[ | structClass prevStructClass references |
structClass := unordered anyOne.
[references := structClass referencedTypeNames.
+ references := references collect: [:ea | ea copyWithoutAll: '([0123456789])*'].
prevStructClass := unordered detect: [:c | c ~~ structClass and: [references includes: c name]] ifNone: [nil].
prevStructClass isNil]
whileFalse: [structClass := prevStructClass].
"we found a structure/alias which does not depend on other structures/aliases"
ordered add: (unordered remove: structClass)].
^ ordered!
Marcel Taeumel uploaded a new version of FFI-Kernel to project FFI:
http://source.squeak.org/FFI/FFI-Kernel-mt.192.mcz
==================== Summary ====================
Name: FFI-Kernel-mt.192
Author: mt
Time: 9 August 2021, 6:52:50.835391 pm
UUID: 8e441056-c6fe-8d44-ad2c-d03174df9cd6
Ancestors: FFI-Kernel-mt.191
Fix typo. Sorry for the noise.
=============== Diff against FFI-Kernel-mt.191 ===============
Item was changed:
----- Method: ExternalStructure class>>doneCompiling (in category 'class management') -----
doneCompiling
"Base class changed to something that is an external structure now."
self isSkipped ifTrue: [^ self].
+ ExternalStructure triggerDefineAllFields.!
- self triggerDefineAllFields.!
Marcel Taeumel uploaded a new version of FFI-Kernel to project FFI:
http://source.squeak.org/FFI/FFI-Kernel-mt.191.mcz
==================== Summary ====================
Name: FFI-Kernel-mt.191
Author: mt
Time: 9 August 2021, 6:50:42.395391 pm
UUID: 89175a32-7b5e-744d-ae32-06f23674d61d
Ancestors: FFI-Kernel-mt.190
Fixes several code-loading bugs around ExternalStructure.
#doneCompiling needs to recompile/redefine *all* fields. The entire hierarchy of ExternalStructure. Note that #doneCompiling is also currently the hook for loading the methods #fields or #originalTypeName via Monticello. We cannot know the effects of any changed field spec. Local re-compilation/re-definition will not do it.
Therefore, offer a simple way to ensure that re-compilation is only done once for multiple changed field spec. Rely on deferred UI messages. In a CI setting, #tryDefineAllFIelds might need to be called after loading the code. In an interactive setting, this won't be necessary because of the UI process.
=============== Diff against FFI-Kernel-mt.190 ===============
Item was changed:
----- Method: ExternalStructure class>>compileAllFields (in category 'system startup') -----
compileAllFields
"
ExternalStructure compileAllFields
"
| priorAuthorInitials fieldSpec |
priorAuthorInitials := Utilities authorInitialsPerSe.
[Utilities setAuthorInitials: 'FFI'.
self allStructuresInCompilationOrder do: [:structClass |
fieldSpec := structClass fields.
- self flag: #discuss. "mt: Why do we need that extra layout check? Performance gain is minimal..."
(structClass hasFieldLayoutChanged: fieldSpec)
+ ifTrue: [structClass compileFields: fieldSpec].
- ifTrue: [structClass compileFieldsSilently: fieldSpec].
- structClass externalType "asNonPointerType"
- compiledSpec: structClass compiledSpec;
- byteAlignment: structClass byteAlignment.
structClass organization removeEmptyCategories].
"Compilation of fields only needs external types temporarily. Non-weak references to external types are only in methods with FFI calls."
ExternalType cleanupUnusedTypes.
] ensure: [Utilities setAuthorInitials: priorAuthorInitials]!
Item was changed:
----- Method: ExternalStructure class>>compileFields: (in category 'field definition') -----
compileFields: fieldSpec
"Private. Use #compileFields."
+ self compileFields: fieldSpec withAccessors: #generated.
- self compileFieldsSilently: fieldSpec.
ExternalType noticeModificationOf: self.!
Item was removed:
- ----- Method: ExternalStructure class>>compileFieldsSilently: (in category 'field definition') -----
- compileFieldsSilently: fieldSpec
- "Private. Use #compileFields."
-
- self compileFields: fieldSpec withAccessors: #generated.!
Item was changed:
----- Method: ExternalStructure class>>defineAllFields (in category 'system startup') -----
defineAllFields
+ "
- "For convenience.
ExternalStructure defineAllFields
"
+ | priorAuthorInitials fieldSpec |
+ priorAuthorInitials := Utilities authorInitialsPerSe.
+ [Utilities setAuthorInitials: 'FFI'.
+
+ self allStructuresInCompilationOrder do: [:structClass |
+ fieldSpec := structClass fields.
+ (structClass hasFieldLayoutChanged: fieldSpec)
+ ifTrue: [structClass defineFields: fieldSpec].
+ structClass organization removeEmptyCategories].
+ "Compilation of fields only needs external types temporarily. Non-weak references to external types are only in methods with FFI calls."
+ ExternalType cleanupUnusedTypes.
+
+ ] ensure: [Utilities setAuthorInitials: priorAuthorInitials]!
- self allStructuresInCompilationOrder
- do: [:structClass |
- structClass defineFields.
- structClass organization removeEmptyCategories].!
Item was added:
+ ----- Method: ExternalStructure class>>defineFieldsSafely (in category 'field definition') -----
+ defineFieldsSafely
+
+ [self defineFields]
+ ifError: [:msg | Transcript showln: '[FFI] Field definition failed: ', msg].!
Item was changed:
----- Method: ExternalStructure class>>doneCompiling (in category 'class management') -----
doneCompiling
"Base class changed to something that is an external structure now."
self isSkipped ifTrue: [^ self].
+ self triggerDefineAllFields.!
- self compileFieldsSafely.
- self externalType becomeKnownTypeSafely.!
Item was changed:
----- Method: ExternalStructure class>>hasFieldLayoutChanged: (in category 'system startup') -----
hasFieldLayoutChanged: fieldSpec
"Answers whether all fields should be re-compiled (and hence accessors re-generated). This is useful at system startup time if a platform change was detected, which can influence alignment and size of pointers.
!!!!!! Note that this method depends on all referenced types to be checked for field-layout changes first !!!!!!"
+ | oldCompiledSpec oldByteAlignment result |
- | oldCompiledSpec oldByteAlignment |
(oldCompiledSpec := self compiledSpec) ifNil: [^ true].
(oldByteAlignment := self byteAlignment) ifNil: [^ true].
self compileFields: fieldSpec withAccessors: #never.
- self assert: [self isTypeAlias or: [oldCompiledSpec ~~ self compiledSpec]].
-
self flag: #bug. "mt: Changed type aliasing for pointers not noticed unless that alias hides a pointer type."
+ result := self isTypeAlias or: [oldCompiledSpec ~= self compiledSpec].
+
+ self
+ setCompiledSpec: oldCompiledSpec
+ byteAlignment: oldByteAlignment.
+
+ ^ result!
- [^ oldCompiledSpec ~= self compiledSpec]
- ensure: [
- self
- setCompiledSpec: oldCompiledSpec
- byteAlignment: oldByteAlignment]!
Item was changed:
----- Method: ExternalStructure class>>platformChangedFrom:to: (in category 'system startup') -----
platformChangedFrom: lastPlatform to: currentPlatform
+ "The system is coming up on a new platform. Compile all field specs and install them in the respective struct types. Also re-generate all struct-field accessors if necessary."
- "The system is coming up on a new platform. Compile all field specs and install them in the respective struct types."
+ self defineAllFields.!
- self compileAllFields.!
Item was added:
+ ----- Method: ExternalStructure class>>triggerDefineAllFields (in category 'field definition - deferred') -----
+ triggerDefineAllFields
+
+ self environment at: #'FFIDeferredTask_DefineAllFields' put: true.
+ Project current addDeferredUIMessage: [self tryDefineAllFields].!
Item was added:
+ ----- Method: ExternalStructure class>>tryDefineAllFields (in category 'field definition - deferred') -----
+ tryDefineAllFields
+
+ (self environment includesKey: #'FFIDeferredTask_DefineAllFields')
+ ifTrue: [self environment removeKey: #'FFIDeferredTask_DefineAllFields']
+ ifFalse: [^ self].
+
+ self defineAllFields.!
Marcel Taeumel uploaded a new version of FFI-Kernel to project FFI:
http://source.squeak.org/FFI/FFI-Kernel-mt.190.mcz
==================== Summary ====================
Name: FFI-Kernel-mt.190
Author: mt
Time: 9 August 2021, 5:54:44.510391 pm
UUID: 6936522e-daaf-404a-86b6-f21a36197f8d
Ancestors: FFI-Kernel-mt.189
Improves initialization of type aliases during initial code loading. Note that "self defineFields" is still required after changing/implementing #originalTypeName in the alias' referentClass.
=============== Diff against FFI-Kernel-mt.189 ===============
Item was changed:
+ ----- Method: ExternalAtomicType>>newTypeAlias (in category 'private') -----
- ----- Method: ExternalAtomicType>>newTypeAlias (in category 'testing') -----
newTypeAlias
+ "Only support switching between atomic types for now."
+ self isTypeAlias ifFalse: [^ self].
+
+ compiledSpec := referentClass compiledSpec.
+ byteAlignment := referentClass byteAlignment.!
- "self isTypeAlias ifFalse: [^ self]."
- "Nothing to do. My referentClass was already upated."
- !
Item was changed:
----- Method: ExternalStructureType>>newTypeAlias (in category 'private') -----
newTypeAlias
+ "Only support switching between struct types for now."
+ self isTypeAlias ifFalse: [^ self].
+
+ compiledSpec := referentClass compiledSpec.
+ byteAlignment := referentClass byteAlignment.!
- "self isTypeAlias ifFalse: [^ self]."
- "Nothing to do. My referentClass was already upated."
- !
Item was changed:
----- Method: ExternalType class>>newTypeNamed: (in category 'instance creation') -----
newTypeNamed: aTypeName
"Create a new struct type or array type. Not needed for atomic types; see #initializeDefaultTypes."
| structClass arraySpec |
self
assert: [aTypeName last ~~ $*]
description: 'Pointer type will be created automatically'.
self
assert: [aTypeName first ~~ $*]
description: 'Non-pointer type for alias-to-pointer types will be created automatically'.
aTypeName last == $] ifTrue: [ "array type, e.g., char[50]"
arraySpec := self parseArrayTypeName: aTypeName.
arraySpec second ifNil: [arraySpec at: 2 put: (self newTypeNamed: arraySpec first)].
^ self
newTypeForContentType: arraySpec second
size: arraySpec third].
structClass := (self environment classNamed: aTypeName)
ifNotNil: [:class | (class includesBehavior: ExternalStructure) ifTrue: [class]].
+ ^ (structClass isNil or: [structClass isSkipped "i.e., not yet ready, see ExternalTypeAlias"])
+ ifTrue: [self newTypeForUnknownNamed: aTypeName]
+ ifFalse: [self newTypeForStructureClass: structClass]!
- ^ structClass
- ifNil: [self newTypeForUnknownNamed: aTypeName]
- ifNotNil: [self newTypeForStructureClass: structClass]!
Item was changed:
----- Method: ExternalTypeAlias class>>isSkipped (in category 'field definition') -----
isSkipped
+ "Skip this class and all subclasses that have not yet implemented #originalTypeName."
+ ^ self == ExternalTypeAlias
+ or: [(self class lookupSelector: #originalTypeName) hasLiteral: #subclassResponsibility]!
- ^ self == ExternalTypeAlias!
Item was changed:
----- Method: ExternalUnknownType>>newTypeAlias (in category 'construction') -----
newTypeAlias
+ "A type alias is done compiling and its type can now be initialized completely. See ExternalTypeAlias class >> #originalTypeName and #isSkipped."
+ self assert: [referentClass isBehavior].
+
+ referentClass isTypeAlias
+ ifTrue: [^ self becomeKnownType].
+
+ self error: '[FFI] Only type aliases can become a known type later on'.!
- self shouldNotImplement.!
Marcel Taeumel uploaded a new version of FFI-Pools to project FFI:
http://source.squeak.org/FFI/FFI-Pools-mt.32.mcz
==================== Summary ====================
Name: FFI-Pools-mt.32
Author: mt
Time: 9 August 2021, 4:09:34.890391 pm
UUID: e88ddc3c-116f-c44e-9a38-72b380f8011a
Ancestors: FFI-Pools-mt.31
Fix package preamble to declare known class names upfront to avoid unnecessary warnings in the Transcript.
=============== Diff against FFI-Pools-mt.31 ===============
Item was added:
+ (PackageInfo named: 'FFI-Pools') preamble: '"To avoid warnings, declare classes that will be loaded from FFI-Kernel, immediately after loading this package."
+ #(ExternalType ExternalAddress FFIPlatformDescription)
+ do: [:className | | environment |
+ environment := Environment default.
+ (environment declarationOf: className)
+ ifNil: [environment bind: className to: nil]].'!
Marcel Taeumel uploaded a new version of FFI-Tests to project FFI:
http://source.squeak.org/FFI/FFI-Tests-mt.55.mcz
==================== Summary ====================
Name: FFI-Tests-mt.55
Author: mt
Time: 9 August 2021, 12:01:19.708535 pm
UUID: 869cfb3f-b03d-fc41-a6b0-70ee61eae5ca
Ancestors: FFI-Tests-mt.54
Refactor the one test that fails only on macOS to get better error message in CI.
=============== Diff against FFI-Tests-mt.54 ===============
Item was changed:
----- Method: FFIPluginTests>>testChars (in category 'tests - atomics') -----
testChars
| result |
result := self invoke: 'ffiTestChars' with: $A with: 65 with: 65.0 with: true.
self assert: result isCharacter.
+ self assert: 130 equals: result asciiValue.!
- self assert: result asciiValue = 130.!