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

commits at source.squeak.org commits at source.squeak.org
Tue Jun 8 09:53:54 UTC 2021


Marcel Taeumel uploaded a new version of FFI-Kernel to project FFI:
http://source.squeak.org/FFI/FFI-Kernel-mt.181.mcz

==================== Summary ====================

Name: FFI-Kernel-mt.181
Author: mt
Time: 8 June 2021, 11:53:52.533752 am
UUID: d7c02d46-f7b6-4d41-a63a-dd327d60367a
Ancestors: FFI-Kernel-mt.180

Fixes and clean-up in array types. No need for #isPointerTypeForArray because #referentClass is used only for alias-to-array types as in other types. The #contentType has its own instVar.

=============== Diff against FFI-Kernel-mt.180 ===============

Item was changed:
  ----- Method: ExternalArrayType class>>newTypeForContentType:size: (in category 'instance creation') -----
  newTypeForContentType: contentType size: numElements
  	"!!!!!! Be aware that only the pointer type can be used in calls. As of SqueakFFIPrims VMMaker.oscog-eem.2950, there is no actual support for array types in the FFI plugin !!!!!!"
  
  	| type pointerType headerWord byteSize |	
  	self
  		flag: #contentVsContainer;
  		assert: [contentType isTypeAlias or: [contentType isArrayType not]]
  		description: 'No support for direct multi-dimensional containers yet. Use type aliases.'.
  
  	self
  		assert: [contentType isVoid not]
  		description: 'No array types for void type!!'.
  
  	self
  		assert: [
  			(ArrayTypes at: contentType typeName
  				ifPresent: [:sizes | sizes at: numElements ifAbsent: [nil]]
  				ifAbsent: [nil] ) isNil]
  		description: 'Array type already exists. Use #typeNamed: to access it.'.
  
  	type := ExternalArrayType basicNew.
  	pointerType := ExternalPointerType basicNew.
  	
  	"1) Regular type"
  	byteSize := numElements
  		ifNil: [0] ifNotNil: [numElements * contentType byteSize].
  	headerWord := contentType headerWord.
  	headerWord := headerWord bitClear: FFIStructSizeMask.
  	headerWord := headerWord bitOr: (byteSize min: FFIStructSizeMask).
  	type
  		setReferencedType: pointerType;
  		compiledSpec: (WordArray with: headerWord);
  		byteAlignment: (numElements ifNil: [0] ifNotNil: [contentType byteAlignment]);
+ 		setReferentClass: nil; "Like atomics and pointers-to-atomics, no dedicated class exists."
- 		setReferentClass: contentType referentClass;
  		setContentType: contentType;
  		setSize: numElements;
  		setByteSize: byteSize.
  
  	"2) Pointer type. Reuse the compiledSpec of the content-type's pointer type."
  	pointerType
  		setReferencedType: type;
  		compiledSpec: (WordArray with: (self pointerSpec bitOr: FFIFlagAtomic "HACK!! To deceive the FFI plugin :)"));
  		byteAlignment: self pointerAlignment;
  		setReferentClass: nil.
  	
  	"3) Remember this new array type."
  	(ArrayTypes at: contentType typeName ifAbsentPut: [WeakValueDictionary new])
  		at: numElements put: type.
  		
  	^ type!

Item was changed:
  ----- Method: ExternalArrayType>>allocate (in category 'external data') -----
  allocate
+ 	"Overwritten to allocate specific to contentType and size. Check referentClass to consider #isTypeAlias."
+ 	
- 
  	| data |
  	data := self contentType allocate: self size.
+ 	^ referentClass
+ 		ifNil: [data "genuine arrays"]
+ 		ifNotNil: [referentClass fromHandle: data getHandle]!
- 	^ self isTypeAlias
- 		ifTrue: [referentClass fromHandle: data getHandle]
- 		ifFalse: [data]!

Item was changed:
  ----- Method: ExternalArrayType>>allocateExternal (in category 'external data') -----
  allocateExternal
+ 	"Overwritten to allocate specific to contentType and size. Check referentClass to consider #isTypeAlias."
+ 	
- 
  	| data |
  	data := self contentType allocateExternal: self size.
+ 	^ referentClass
+ 		ifNil: [data "genuine arrays"]
+ 		ifNotNil: [referentClass fromHandle: data getHandle]!
- 	^ self isTypeAlias
- 		ifTrue: [referentClass fromHandle: data getHandle]
- 		ifFalse: [data]!

Item was changed:
  ----- Method: ExternalArrayType>>handle:at: (in category 'external data') -----
  handle: handle at: byteOffset
  
  	| resultHandle |
  	resultHandle := handle structAt: byteOffset length: self byteSize.
+ 	^ referentClass
+ 		ifNotNil: [referentClass fromHandle: resultHandle]
+ 		ifNil: [ExternalData fromHandle: resultHandle type: self]!
- 	^ self isTypeAlias
- 		ifTrue: [referentClass fromHandle: resultHandle]
- 		ifFalse: [ExternalData fromHandle: resultHandle type: self]!

Item was added:
+ ----- Method: ExternalArrayType>>newContentType: (in category 'private') -----
+ newContentType: typeOrNil
+ 	"My content type has changed. Update my byteSize."
+ 
+ 	| newByteSize newHeaderWord |
+ 	(contentType := typeOrNil)
+ 		ifNil: [ "my class has been removed - make me empty"
+ 			compiledSpec := WordArray with: self class structureSpec.
+ 			byteAlignment := 1]
+ 		ifNotNil: [ "my class has been changed - update my compiledSpec"
+ 			newHeaderWord := contentType headerWord.
+ 			newByteSize := size ifNil: [0] ifNotNil: [size * (newHeaderWord bitAnd: FFIStructSizeMask)].
+ 			newHeaderWord := newHeaderWord bitClear: FFIStructSizeMask.
+ 			newHeaderWord := newHeaderWord bitOr: (newByteSize min: FFIStructSizeMask).
+ 			compiledSpec := WordArray with: newHeaderWord.
+ 			byteAlignment := contentType byteAlignment.
+ 			byteSize := newByteSize]!

Item was changed:
  ----- Method: ExternalArrayType>>newReferentClass: (in category 'private') -----
  newReferentClass: classOrNil
  	"The class I'm referencing has changed, which affects arrays of structs. Update my byteSize."
  
- 	| newByteSize newHeaderWord |
  	(referentClass := classOrNil)
+ 		ifNil: [ "my class has been removed - make me 'struct { void }'"
- 		ifNil: [ "my class has been removed - make me empty"
  			compiledSpec := WordArray with: self class structureSpec.
+ 			byteAlignment := 1.
+ 			contentType := size := byteSize := nil]
+ 		ifNotNil: [ "I am an alias-to-array type. Update my specs."
+ 			| originalType |
+ 			originalType := referentClass originalType.
+ 			self assert: [originalType isArrayType].
+ 			
+ 			compiledSpec := originalType compiledSpec.
+ 			byteAlignment := originalType byteAlignment.
+ 			
+ 			contentType := originalType contentType.
+ 			size := originalType size.
+ 			byteSize := originalType byteSize]!
- 			byteAlignment := 1]
- 		ifNotNil: [ "my class has been changed - update my compiledSpec"
- 			newHeaderWord := referentClass compiledSpec first.
- 			newByteSize := size ifNil: [0] ifNotNil: [size * (newHeaderWord bitAnd: FFIStructSizeMask)].
- 			newHeaderWord := newHeaderWord bitClear: FFIStructSizeMask.
- 			newHeaderWord := newHeaderWord bitOr: (newByteSize min: FFIStructSizeMask).
- 			compiledSpec := WordArray with: newHeaderWord.
- 			byteAlignment := referentClass byteAlignment.
- 			byteSize := newByteSize]!

Item was changed:
  ----- Method: ExternalArrayType>>readFieldAt: (in category 'external structure') -----
  readFieldAt: byteOffset
  
+ 	^ referentClass
+ 		ifNotNil: [
- 	^ self isTypeAlias
- 		ifTrue: [
  			'^ {1} fromHandle: (handle structAt: {1} length: {2})'
  				format: {
  					referentClass name.
  					byteOffset.
  					self byteSize}]
+ 		ifNil: [
- 		ifFalse: [
  			'^ ExternalData fromHandle: (handle structAt: {1} length: {2}) type: {3}'
  				format: {
  					byteOffset.
  					self byteSize.
  					self storeStringForField}]!

Item was changed:
  ----- Method: ExternalArrayType>>storeOn: (in category 'printing') -----
  storeOn: aStream
  
+ 	referentClass ifNotNil: [
- 	self isTypeAlias ifTrue: [
  		^ aStream
  			nextPutAll: referentClass name;
  			nextPutAll: ' externalType'].
  			
  	aStream nextPut: $(.
  	self contentType storeOn: aStream.
  	aStream nextPutAll: ' asArrayType: '.
  	aStream nextPutAll: self size asString.
  	aStream nextPut: $).!

Item was changed:
  ----- Method: ExternalArrayType>>typeName (in category 'accessing') -----
  typeName
  
+ 	referentClass
+ 		ifNotNil: [^ super typeName].
- 	self isTypeAlias
- 		ifTrue: [^ super typeName].
  
  	^ String streamContents: [:stream | | inParentheses |
  		(inParentheses := self contentType isPointerType not
  			and: [self contentType asPointerType isTypeAlias])
  				ifTrue: [stream nextPut: $(. "e.g. (*DoublePtr)[5]"].		
  		
  		stream nextPutAll: self contentType typeName.
  		
  		inParentheses ifTrue: [stream nextPut: $)].
  		
  		stream nextPut: $[.
  		self size ifNotNil: [stream nextPutAll: self size asString].
  		stream nextPut: $]. ]!

Item was changed:
  ----- Method: ExternalPointerType>>handle:at: (in category 'external data') -----
  handle: handle at: byteOffset
  
+ 	^ referentClass
- 	| referentClassToUse |
- 	referentClassToUse := self isPointerTypeForArray
- 		ifFalse: [referentClass]
- 		ifTrue: [self asNonPointerType isTypeAlias
- 			ifTrue: [self asNonPointerType referentClass] ifFalse: [nil]].
- 	^ referentClassToUse
  			ifNotNil: [
+ 				referentClass fromHandle: (handle pointerAt: byteOffset length: self byteSize)]
- 				referentClassToUse fromHandle: (handle pointerAt: byteOffset length: self byteSize)]
  			ifNil: [
  				ExternalData
  					fromHandle: (handle pointerAt: byteOffset length: self byteSize)
  					type: self asNonPointerType "content type"]!

Item was removed:
- ----- Method: ExternalPointerType>>isPointerTypeForArray (in category 'testing') -----
- isPointerTypeForArray
- 	"referentClass is currently nil for pointer-to-array types. All operations on referentClass should check this to then use the referentClass from the non-pointer type. Might be changed once array information are encoded in the headerWord."
- 	
- 	^ self asNonPointerType isArrayType!

Item was removed:
- ----- Method: ExternalPointerType>>newReferentClass: (in category 'private') -----
- newReferentClass: classOrNil
- 	"The class I'm referencing has changed. Keep pointer types for array types free of the referentClass so that FFI calls return ExternalData."
- 
- 	self isPointerTypeForArray
- 		ifTrue: [referentClass := nil]
- 		ifFalse: [referentClass := classOrNil].!

Item was changed:
  ----- Method: ExternalPointerType>>originalType (in category 'accessing - type alias') -----
  originalType
  	"Overwritten to look into my referencedType. See #isTypeAliasReferenced."
  
- 	self isPointerTypeForArray ifTrue: [
- 		^ self asNonPointerType originalType asPointerType].
- 
  	^ self "e.g. MyStructPtr" asNonPointerType isTypeAlias "e.g. *MyStructPtr"
  		ifTrue: [super originalType asPointerType "e.g. MyStruct*, not MyStruct"]
  		ifFalse: [super originalType]!

Item was changed:
  ----- Method: ExternalPointerType>>readFieldAt: (in category 'external structure') -----
  readFieldAt: byteOffset
  
- 	| referentClassToUse |
- 	referentClassToUse := self isPointerTypeForArray
- 		ifFalse: [referentClass]
- 		ifTrue: [self asNonPointerType isTypeAlias
- 			ifTrue: [self asNonPointerType referentClass] ifFalse: [nil]].
  	^ '^ {1} fromHandle: (handle pointerAt: {2} length: {3}){4}'
  		format: {
+ 			(referentClass ifNil: [ExternalData]) name.
- 			(referentClassToUse ifNil: [ExternalData]) name.
  			byteOffset.
  			self byteSize.
+ 			referentClass ifNotNil: [''] ifNil: [
- 			referentClassToUse ifNotNil: [''] ifNil: [
  				' type: ', self asNonPointerType "content type" storeStringForField]}!

Item was changed:
  ----- Method: ExternalType class>>noticeModificationOf: (in category 'housekeeping') -----
  noticeModificationOf: aClass
+ 	"A subclass of ExternalStructure has been redefined."
- 	"A subclass of ExternalStructure has been redefined.
- 	Clean out any obsolete references to its type."
  
  	aClass withAllSubclassesDo: [:cls | | typeName type |
  		typeName := cls name.
  		
- 		ArrayTypes at: typeName ifPresent: [:sizes |
- 			sizes do: [:arrayType | arrayType ifNotNil: [
- 				arrayType newReferentClass: cls.
- 				arrayType asPointerType newReferentClass: cls]]].
- 		
  		(type := StructTypes at: typeName ifAbsent: [])
  			ifNotNil: [
  				type newReferentClass: cls.
  				type asPointerType newReferentClass: cls.
+ 				type newTypeAlias].
+ 			
+ 		ArrayTypes at: typeName ifPresent: [:sizes |
+ 			sizes do: [:arrayType | arrayType ifNotNil: [
+ 				arrayType newContentType: type]]].
+ 	
+ 		"Alias-to-array types, which are stored in StructTypes, will not update via #newContentType:. We scan StructTypes for #isArrayType to find such aliases to then call #newContentType:."
+ 		StructTypes do: [:each |
+ 			(each notNil and: [each isArrayType and: [each contentType == type]])
+ 				ifTrue: [each newContentType: type]]].!
- 				type newTypeAlias]]!

Item was changed:
  ----- Method: ExternalType class>>noticeRemovalOf: (in category 'housekeeping') -----
  noticeRemovalOf: aClass
  	"A subclass of ExternalStructure is being removed.
  	Clean out any obsolete references to its type."
+ 
+ 	| typeName type |
+ 	typeName := aClass name.
+ 	
+ 	(type := StructTypes at: typeName ifAbsent: [])
+ 		ifNotNil: [
+ 			type newReferentClass: nil.
+ 			type asPointerType newReferentClass: nil].
+ 		
- 	| type |
- 	type := StructTypes at: aClass name ifAbsent:[nil].
- 	type == nil ifFalse:[
- 		type newReferentClass: nil.
- 		type asPointerType newReferentClass: nil].
  	ArrayTypes at: aClass name ifPresent: [:sizes |
+ 		sizes do: [:arrayType | arrayType ifNotNil: [
+ 			arrayType newContentType: nil]].
+ 	
+ 	"Alias-to-array types, which are stored in StructTypes, will not update via #newContentType:. We scan StructTypes for #isArrayType to find such aliases to then call #newContentType:."
+ 	StructTypes do: [:each |
+ 		(each notNil and: [each isArrayType and: [each contentType == type]])
+ 			ifTrue: [each newContentType: type]]].!
- 		sizes do: [:arrayType |
- 			arrayType newReferentClass: nil.
- 			arrayType asPointerType newReferentClass: nil]].!

Item was changed:
  ----- Method: ExternalUnknownType>>becomeArrayType (in category 'construction') -----
  becomeArrayType
  	"I am now positive on #isTypeAliasForArray :-) Make myself an array type. Not that easy because Arraytype as extra instVars #size and #contentType."
  	
  	| newArrayType |	
  	newArrayType := ExternalArrayType basicNew
  		compiledSpec: self compiledSpec;
  		byteAlignment: self byteAlignment;
  		setReferentClass: referentClass;
  		setReferencedType: referencedType;
  		setContentType: referentClass originalType contentType; "Hmm..."
  		setSize: referentClass originalType size; "Hmm..."
  		setByteSize: referentClass originalType byteSize; "Hmm..."
  		yourself.
  
- 	"No referentClass for pointer types of array types."
- 	referencedType setReferentClass: nil.
- 
  	self becomeForward: newArrayType.	
  
  	^ newArrayType!



More information about the Squeak-dev mailing list