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.!
packages@lists.squeakfoundation.org