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

commits at source.squeak.org commits at source.squeak.org
Thu Aug 19 13:22:30 UTC 2021


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

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

Name: FFI-Kernel-mt.218
Author: mt
Time: 19 August 2021, 3:22:28.986186 pm
UUID: 214b5564-8fa9-5c47-9334-07e3fd038f60
Ancestors: FFI-Kernel-mt.217

Speed up mem-copy (i.e., #structAt:length: in ByteArray) by factor 10.

Speed up read/write pointers (i.e., ExternalAddress) by factor 20, given that you have primitives for #asInteger and #fromInteger in your plugin.

Use the same algorithm as in #zeroMemory:, which reduces the amount of primitive sends as much as possible.

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

Item was added:
+ ----- Method: ByteArray>>memoryAt:length: (in category '*FFI-Kernel-accessing') -----
+ memoryAt: byteOffset length: numBytes
+ 
+ 	| index size handle startByteOffset |
+ 	handle := ByteArray new: numBytes.
+ 	startByteOffset := byteOffset - 1.
+ 	index := 1.
+ 	size := numBytes - 7.
+ 	[index <= size] whileTrue:
+ 		[handle uint64At: index put: (self uint64At: startByteOffset + index).
+ 		 index := index + 8].
+ 	size := size + 4. "7 - 3, i.e. numBytes - 3"
+ 	index <= size ifTrue:
+ 		[handle uint32At: index put: (self uint32At: startByteOffset + index).
+ 		 index := index + 4].
+ 	size := size + 2. "3 - 1, i.e. numBytes - 1"
+ 	index <= size ifTrue:
+ 		[handle uint16At: index put: (self uint16At: startByteOffset + index).
+ 		 index := index + 2].
+ 	size := size + 1.
+ 	index <= size ifTrue:
+ 		[handle uint8At: index put: (self uint8At: startByteOffset + index)].
+ 	^ handle!

Item was added:
+ ----- Method: ByteArray>>memoryAt:put:length: (in category '*FFI-Kernel-accessing') -----
+ memoryAt: byteOffset put: handle length: numBytes
+ 
+ 	| index size startByteOffset |
+ 	startByteOffset := byteOffset - 1.
+ 	index := 1.
+ 	size := numBytes - 7.
+ 	[index <= size] whileTrue:
+ 		[self uint64At: startByteOffset + index put: (handle uint64At: index).
+ 		 index := index + 8].
+ 	size := size + 4. "7 - 3, i.e. numBytes - 3"
+ 	index <= size ifTrue:
+ 		[self uint32At: startByteOffset + index put: (handle uint32At: index).
+ 		 index := index + 4].
+ 	size := size + 2. "3 - 1, i.e. numBytes - 1"
+ 	index <= size ifTrue:
+ 		[self uint16At: startByteOffset + index put: (handle uint16At: index).
+ 		 index := index + 2].
+ 	size := size + 1.
+ 	index <= size ifTrue:
+ 		[self uint8At: startByteOffset + index put: (handle uint8At: index)].
+ 	^ handle!

Item was changed:
  ----- Method: ByteArray>>pointerAt:length: (in category '*FFI-Kernel-accessing') -----
  pointerAt: byteOffset length: length
  	"Return a pointer of the given length starting at the indicated byte offset."
  
+ 	^ ExternalAddress fromInteger: (self integerAt: byteOffset size: length signed: false)!
- 	| pointer startByteOffset |
- 	pointer := ExternalAddress basicNew: length.
- 	startByteOffset := byteOffset - 1.
- 	1 to: length do: [:pointerByteOffset |
- 		pointer
- 			basicAt: pointerByteOffset
- 			put: (self unsignedByteAt: startByteOffset + pointerByteOffset)].
- 	^ pointer!

Item was changed:
  ----- Method: ByteArray>>pointerAt:put:length: (in category '*FFI-Kernel-accessing') -----
+ pointerAt: byteOffset put: externalAddress length: length
- pointerAt: byteOffset put: pointer length: length
  	"Store a pointer of the given length starting at the indicated byte offset."
  
+ 	self integerAt: byteOffset put: externalAddress asInteger size: length signed: false.
+ 	^ externalAddress!
- 	| startByteOffset |
- 	self assert: [pointer isExternalAddress].
- 	startByteOffset := byteOffset - 1.
- 	1 to: length do: [:pointerByteOffset |
- 		self
- 			unsignedByteAt: startByteOffset + pointerByteOffset
- 			put: (pointer basicAt: pointerByteOffset)].
- 	^ pointer!

Item was changed:
  ----- Method: ByteArray>>structAt:length: (in category '*FFI-Kernel-accessing') -----
  structAt: byteOffset length: length
  	"Return a structure of the given length starting at the indicated byte offset."
+ 
+ 	^ self memoryAt: byteOffset length: length!
- 	
- 	| value startByteOffset |
- 	self flag: #todo. "mt: Better name #unsignedBytesAt:length:?"
- 	value := ByteArray new: length.
- 	startByteOffset := byteOffset - 1.
- 	1 to: length do: [:valueByteOffset |
- 		value
- 			unsignedByteAt: valueByteOffset
- 			put: (self unsignedByteAt: startByteOffset + valueByteOffset)].
- 	^ value!

Item was changed:
  ----- Method: ByteArray>>structAt:put:length: (in category '*FFI-Kernel-accessing') -----
  structAt: byteOffset put: value length: length
  	"Store a structure of the given length starting at the indicated byte offset."
  	
+ 	^ self memoryAt: byteOffset put: value length: length!
- 	| startByteOffset |
- 	self flag: #todo. "mt: Better name #unsignedBytesAt:put:length:?"
- 	startByteOffset := byteOffset - 1.
- 	1 to: length do: [:valueByteOffset |
- 		self
- 			unsignedByteAt: startByteOffset + valueByteOffset
- 			put: (value unsignedByteAt:valueByteOffset)].
- 	^ value!

Item was added:
+ ----- Method: ByteArrayReadWriter>>memoryAt:length: (in category 'read/write structs') -----
+ memoryAt: newByteOffset length: newLength
+ 
+ 	self checkAt: newByteOffset length: newLength.
+ 	^ ByteArrayReadWriter new
+ 		setArray: byteArray
+ 		offset: byteOffset + newByteOffset - 1
+ 		size: newLength!

Item was added:
+ ----- Method: ByteArrayReadWriter>>memoryAt:put:length: (in category 'read/write structs') -----
+ memoryAt: newByteOffset put: value length: newLength
+ 
+ 	self checkAt: newByteOffset length: newLength.
+ 	^ byteArray
+ 		structAt: byteOffset + newByteOffset - 1
+ 		put: value
+ 		length: newLength!

Item was changed:
  ----- Method: ByteArrayReadWriter>>structAt:length: (in category 'read/write structs') -----
  structAt: newByteOffset length: newLength
  
+ 	^ self memoryAt: newByteOffset length: newLength!
- 	self checkAt: newByteOffset length: newLength.
- 	^ ByteArrayReadWriter new
- 		setArray: byteArray
- 		offset: byteOffset + newByteOffset - 1
- 		size: newLength!

Item was changed:
  ----- Method: ByteArrayReadWriter>>structAt:put:length: (in category 'read/write structs') -----
  structAt: newByteOffset put: value length: newLength
  
+ 	^ self memoryAt: newByteOffset put: value length: newLength!
- 	self checkAt: newByteOffset length: newLength.
- 	^ byteArray
- 		structAt: byteOffset + newByteOffset - 1
- 		put: value
- 		length: newLength!

Item was added:
+ ----- Method: ExternalAddress>>memoryAt:length: (in category 'accessing') -----
+ memoryAt: byteOffset length: length
+ 	"Overwritten to not read bytes but just move the pointer. Ignore the length."
+ 	
+ 	^ ExternalAddress fromAddress: self movedBy: byteOffset - 1!

Item was removed:
- ----- Method: ExternalAddress>>structAt:length: (in category 'accessing') -----
- structAt: byteOffset length: length
- 	"Overwritten to not read bytes but just move the pointer. Ignore the length."
- 	
- 	^ ExternalAddress fromAddress: self movedBy: byteOffset - 1!

Item was changed:
  ----- Method: ExternalData>>from: (in category 'accessing') -----
  from: firstIndex
  	"Move the start of this array. Size not needed."
  
  	| byteOffset numElements byteSize |
  	byteOffset := ((firstIndex-1) * self contentType byteSize)+1.
  	numElements := (self size ifNotNil: [:sz | sz - firstIndex + 1 max: 0]).
  	byteSize := numElements
  		ifNil: [self contentType byteSize]
  		ifNotNil: [numElements * self contentType byteSize].
  
  	^ ExternalData
+ 		fromHandle: (handle memoryAt: byteOffset length: (byteSize ifNil: [1]))
- 		fromHandle: (handle structAt: byteOffset length: (byteSize ifNil: [1]))
  		type: self contentType
  		size: numElements!

Item was changed:
  ----- Method: ExternalData>>from:to: (in category 'accessing') -----
  from: firstIndex to: lastIndex
  	"Only copy data if already in object memory, that is, as byte array. Only check size if configured."
  
  	| byteOffset numElements byteSize |
  	ExtraSizeChecks == true ifTrue: [
  		self sizeCheck: firstIndex.
  		self sizeCheck: lastIndex].
  
  	byteOffset := ((firstIndex-1) * self contentType byteSize)+1.
  	numElements := lastIndex - firstIndex + 1 max: 0.
  	byteSize := numElements * self contentType byteSize.
  
  	^ ExternalData
+ 		fromHandle: (handle memoryAt: byteOffset length: byteSize)
- 		fromHandle: (handle structAt: byteOffset length: byteSize)
  		type: self contentType
  		size: numElements!

Item was changed:
  ----- Method: ExternalData>>postCopy (in category 'copying') -----
  postCopy
  	"Reads all bytes from external into object memory or duplicate the array within object memory. Note that this does not flatten all bytes into a single array by repeatedly calling it."
  
+ 	| newHandle numBytes |
- 	| bytes |
  	self sizeCheck.
  	
+ 	numBytes := self byteSize.
+ 	newHandle := ByteArray new: numBytes.
+ 	newHandle memoryAt: 1 put: handle length: numBytes.
- 	bytes := ByteArray new: self byteSize.
- 	1 to: bytes size do: [:index |
- 		bytes basicAt: index put: (handle unsignedByteAt: index)].
  	
+ 	handle := newHandle.
- 	handle := bytes.
  	self setType: type. "Change container type from pointer to non-pointer type."!

Item was changed:
  ----- Method: GenericIntegerReadWriteSend class>>useSpecificIntegerPrimitives: (in category 'preferences') -----
  useSpecificIntegerPrimitives: aBoolean
  
  	UseSpecificIntegerPrimitives = aBoolean ifTrue: [^ self].
  
+ 	aBoolean ==> [self canUseSpecificIntegerPrimitives]
+ 		ifFalse: [self notify: 'FFI plugin does not support specific integer primitives. Proceed to update atomic sends anyway. Fallback code will redirect to generic integer primitive. Performance might be affected.'].
- 	aBoolean ~= self canUseSpecificIntegerPrimitives
- 		ifTrue: [self notify: 'FFI plugin does not support specific integer primitives. Proceed to update atomic sends anyway. Fallback code will redirect to generic integer primitive. Performance might be affected.'].
  
  	UseSpecificIntegerPrimitives := aBoolean.
  	
  	Cursor wait showWhile: [
  		ExternalType initializeAtomicSends.
  		ExternalStructure defineAllFields].!



More information about the Squeak-dev mailing list