[squeak-dev] FFI: FFI-Kernel-mt.191.mcz

commits at source.squeak.org commits at source.squeak.org
Mon Aug 9 16:50:43 UTC 2021


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.!



More information about the Squeak-dev mailing list