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

commits at source.squeak.org commits at source.squeak.org
Wed May 19 09:47:00 UTC 2021

Marcel Taeumel uploaded a new version of FFI-Kernel to project FFI:

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

Name: FFI-Kernel-mt.161
Author: mt
Time: 19 May 2021, 11:46:59.622615 am
UUID: 711b5cef-0d3c-9e4b-98d5-79cc06662c70
Ancestors: FFI-Kernel-mt.160

Adds support for arrays with more than 65535 bytes. Note that this information cannot be encoded in the headerWord (yet) and is similar to the other information not encoded there (yet): size and contentType.

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

Item was changed:
  ExternalType subclass: #ExternalArrayType
+ 	instanceVariableNames: 'contentType size byteSize'
- 	instanceVariableNames: 'contentType size'
  	classVariableNames: ''
  	poolDictionaries: ''
  	category: 'FFI-Kernel'!

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 |	
  		flag: #contentVsContainer;
  		assert: [contentType isTypeAlias or: [contentType isArrayType not]]
  		description: 'No support for direct multi-dimensional containers yet. Use type aliases.'.
  		assert: [contentType isVoid not]
  		description: 'No array types for void type!!'.
  		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].
- 	self assert: [byteSize <= FFIStructSizeMask].
  	headerWord := contentType headerWord.
  	headerWord := headerWord bitClear: FFIStructSizeMask.
+ 	headerWord := headerWord bitOr: (byteSize min: FFIStructSizeMask).
- 	headerWord := headerWord bitOr: byteSize.
  		setReferencedType: pointerType;
  		compiledSpec: (WordArray with: headerWord);
  		byteAlignment: (numElements ifNil: [0] ifNotNil: [contentType byteAlignment]);
  		setReferentClass: contentType referentClass;
  		setContentType: contentType;
+ 		setSize: numElements;
+ 		setByteSize: byteSize.
- 		setSize: numElements.
  	"2) Pointer type. Reuse the compiledSpec of the content-type's pointer type."
  		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>>byteSize (in category 'accessing') -----
  	"For array types with an unknown size, also answer an unknown byte size."
+ 	^ size ifNotNil: [byteSize]!
- 	^ size ifNotNil: [super byteSize]!

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 empty"
  			compiledSpec := WordArray with: self class structureSpec.
  			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).
- 			newHeaderWord := newHeaderWord bitOr: newByteSize.
  			compiledSpec := WordArray with: newHeaderWord.
+ 			byteAlignment := referentClass byteAlignment.
+ 			byteSize := newByteSize]!
- 			byteAlignment := referentClass byteAlignment]!

Item was added:
+ ----- Method: ExternalArrayType>>setByteSize: (in category 'private') -----
+ setByteSize: newByteSize
+ 	byteSize := newByteSize.!

Item was added:
+ ----- Method: ExternalType>>asBasicType (in category 'converting') -----
+ asBasicType
+ 	"Construct a basic representation of the receiver. Can be used for testing the #headerWord and other basic properties that are accessible from within the FFI plugin for type checking etc. where polymorphic message sending cannot be applied."
+ 	| basicType basicReferencedType |
+ 	basicType := ExternalType basicNew
+ 		compiledSpec: compiledSpec;
+ 		setReferentClass: referentClass;
+ 		yourself.
+ 	basicReferencedType :=  ExternalType basicNew
+ 		compiledSpec: referencedType compiledSpec;
+ 		setReferentClass: referencedType referentClass;
+ 		yourself.
+ 	basicType setReferencedType: basicReferencedType.
+ 	basicReferencedType setReferencedType: basicType.
+ 	^ basicType!

Item was removed:
- ----- Method: ExternalType>>asExternalType (in category 'converting') -----
- asExternalType
- 	^ self!

Item was changed:
  ----- Method: ExternalType>>asPointerToPointerType (in category 'converting') -----
- 	"char** etc."
+ 	self flag: #todo. "mt: Maybe we might want to use double pointers such as void** to indicate address-of-a-pointer on call? So that domain-specific malloc functions can work such as void allocate(void** pointer, size_t size);. Otherwise map it to an array of pointers instead: void*[]."
+ 	^ (self asPointerType asArrayType: nil) asPointerType!
- 	self flag: #todo. "mt: We might want to cast this to something that holds multiple ExternalData. If null-terminated, that would be easy. But maybe also support extra arg for size as in main(argc int, char *argv[])	. Maybe we could add ExternalArray... I assume that such a type starts in the image anyway to be passed as argument in an FFI call. That is, can there be function that returns void** ?"
- 	^ self asPointerType!

Item was changed:
  ----- Method: ExternalUnknownType>>becomeArrayType (in category 'construction') -----
  	"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..."
  	"No referentClass for pointer types of array types."
  	referencedType setReferentClass: nil.
  	self becomeForward: newArrayType.	
  	^ newArrayType!

More information about the Squeak-dev mailing list