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

commits at source.squeak.org commits at source.squeak.org
Tue May 4 10:22:49 UTC 2021


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

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

Name: FFI-Kernel-mt.128
Author: mt
Time: 4 May 2021, 12:22:47.736881 pm
UUID: b1af22ec-1c21-a544-82f7-af8466544ab9
Ancestors: FFI-Kernel-mt.127

Renames byte-array writer to read-writer because it can improve reading by avoiding intermediate copies.

Fixes and refactors #from:to: in ExternalData to support ByteArrayReadWriter by just re-using #structAt:length:, which works as expected on ByteArray and ExternalAddress.

Signal an exception when trying to instantiate external data without a type.

Adds some common accessors known from sequenceable collections to external data to help write more compact tests.

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

Item was changed:
  SystemOrganization addCategory: #'FFI-Kernel'!
+ SystemOrganization addCategory: #'FFI-Kernel-Support'!

Item was added:
+ ProtoObject subclass: #ByteArrayReadWriter
+ 	instanceVariableNames: 'byteOffset byteSize byteArray'
+ 	classVariableNames: ''
+ 	poolDictionaries: ''
+ 	category: 'FFI-Kernel-Support'!
+ 
+ !ByteArrayReadWriter commentStamp: 'mt 5/3/2021 17:44' prior: 0!
+ I am a transparent wrapper over byte-array handles to allow access and manipulation just like through an external address.!

Item was added:
+ ----- Method: ByteArrayReadWriter class>>on: (in category 'instance creation') -----
+ on: handle
+ 	"Wraps the given handle into a read-writer. Avoid double-wrapping."
+ 	
+ 	self assert: [handle isInternalMemory].
+ 	
+ 	^ (thisContext objectClass: handle) == self
+ 		ifTrue: [handle]
+ 		ifFalse: [self new setArray: handle]!

Item was added:
+ ----- Method: ByteArrayReadWriter>>doesNotUnderstand: (in category 'system primitives') -----
+ doesNotUnderstand: aMessage
+ 
+ 	| selector args |
+ 	selector := aMessage selector.
+ 	args := aMessage arguments.
+ 	args size caseOf: {
+ 		[ 1 ] -> [ (selector endsWith: 'At:') ifTrue: [ args at: 1 put: args first  + byteOffset ] ].
+ 		[ 2 ] -> [ (selector endsWith: 'length:')
+ 			ifTrue: [
+ 				args at: 1 put: args first + byteOffset.
+ 				args first + args second > byteSize
+ 					ifTrue: [self errorSubscriptBounds: args first + args second] ]
+ 			ifFalse: [(selector endsWith: 'put:') ifTrue: [
+ 				args at: 1 put: args first + byteOffset	]] ].
+ 		[ 3 ] -> [ (selector endsWith: 'length:')
+ 			ifTrue: [
+ 				args at: 1 put: args first + byteOffset.
+ 				args first + args third > byteSize
+ 					ifTrue: [self errorSubscriptBounds: args first + args third]]] 
+ 		} otherwise: []. 				
+ 	^ aMessage sendTo: byteArray!

Item was added:
+ ----- Method: ByteArrayReadWriter>>errorSubscriptBounds: (in category 'initialization') -----
+ errorSubscriptBounds: index
+ 
+ 	Error signal: 'subscript is out of bounds: ' , index printString.!

Item was added:
+ ----- Method: ByteArrayReadWriter>>setArray: (in category 'initialization') -----
+ setArray: aByteArray
+ 
+ 	byteArray := aByteArray.
+ 	byteOffset := 0.
+ 	byteSize := aByteArray size.!

Item was added:
+ ----- Method: ByteArrayReadWriter>>setArray:offset:size: (in category 'initialization') -----
+ setArray: aByteArray offset: aByteOffset size: aByteSize
+ 
+ 	byteArray := aByteArray.
+ 	byteOffset := aByteOffset.
+ 	byteSize := aByteSize.
+ 	
+ 	(byteOffset + byteSize > byteArray size)
+ 		ifTrue: [self errorSubscriptBounds: byteOffset + byteSize].!

Item was added:
+ ----- Method: ByteArrayReadWriter>>structAt:length: (in category 'accessing') -----
+ structAt: newByteOffset length: newLength
+ 
+ 	^ ByteArrayReadWriter new
+ 		setArray: byteArray
+ 		offset: byteOffset + newByteOffset - 1
+ 		size: newLength!

Item was added:
+ ----- Method: ByteArrayReadWriter>>structAt:put:length: (in category 'accessing') -----
+ structAt: newByteOffset put: value length: newLength
+ 
+ 	(newByteOffset + newLength > byteSize)
+ 		ifTrue: [self errorSubscriptBounds: newByteOffset + newLength].
+ 
+ 	^ byteArray
+ 		structAt: byteOffset + newByteOffset - 1
+ 		put: value
+ 		length: newLength!

Item was removed:
- ProtoObject subclass: #ByteArrayWriter
- 	instanceVariableNames: 'byteOffset byteSize byteArray'
- 	classVariableNames: ''
- 	poolDictionaries: ''
- 	category: 'FFI-Kernel'!
- 
- !ByteArrayWriter commentStamp: 'mt 5/3/2021 17:44' prior: 0!
- I am a transparent wrapper over byte-array handles to allow access and manipulation just like through an external address.!

Item was removed:
- ----- Method: ByteArrayWriter class>>on: (in category 'instance creation') -----
- on: handle
- 
- 	self assert: [handle isInternalMemory].
- 	^ self new setArray: handle!

Item was removed:
- ----- Method: ByteArrayWriter>>doesNotUnderstand: (in category 'system primitives') -----
- doesNotUnderstand: aMessage
- 
- 	| selector args |
- 	selector := aMessage selector.
- 	args := aMessage arguments.
- 	args size caseOf: {
- 		[ 1 ] -> [ (selector endsWith: 'At:') ifTrue: [ args at: 1 put: args first  + byteOffset ] ].
- 		[ 2 ] -> [ (selector endsWith: 'length:')
- 			ifTrue: [
- 				args at: 1 put: args first + byteOffset.
- 				args first + args second > byteSize
- 					ifTrue: [self errorSubscriptBounds: args first + args second] ]
- 			ifFalse: [(selector endsWith: 'put:') ifTrue: [
- 				args at: 1 put: args first + byteOffset	]] ].
- 		[ 3 ] -> [ (selector endsWith: 'length:')
- 			ifTrue: [
- 				args at: 1 put: args first + byteOffset.
- 				args first + args third > byteSize
- 					ifTrue: [self errorSubscriptBounds: args first + args third]]] 
- 		} otherwise: []. 				
- 	^ aMessage sendTo: byteArray!

Item was removed:
- ----- Method: ByteArrayWriter>>errorSubscriptBounds: (in category 'initialization') -----
- errorSubscriptBounds: index
- 
- 	Error signal: 'subscript is out of bounds: ' , index printString.!

Item was removed:
- ----- Method: ByteArrayWriter>>setArray: (in category 'initialization') -----
- setArray: aByteArray
- 
- 	byteArray := aByteArray.
- 	byteOffset := 0.
- 	byteSize := aByteArray size.!

Item was removed:
- ----- Method: ByteArrayWriter>>setArray:offset:size: (in category 'initialization') -----
- setArray: aByteArray offset: aByteOffset size: aByteSize
- 
- 	byteArray := aByteArray.
- 	byteOffset := aByteOffset.
- 	byteSize := aByteSize.
- 	
- 	(byteOffset + byteSize > byteArray size)
- 		ifTrue: [self errorSubscriptBounds: byteOffset + byteSize].!

Item was removed:
- ----- Method: ByteArrayWriter>>structAt:length: (in category 'accessing') -----
- structAt: newByteOffset length: newLength
- 
- 	^ ByteArrayWriter new
- 		setArray: byteArray
- 		offset: byteOffset + newByteOffset - 1
- 		size: newLength!

Item was removed:
- ----- Method: ByteArrayWriter>>structAt:put:length: (in category 'accessing') -----
- structAt: newByteOffset put: value length: newLength
- 
- 	(newByteOffset + newLength > byteSize)
- 		ifTrue: [self errorSubscriptBounds: newByteOffset + newLength].
- 
- 	^ byteArray
- 		structAt: byteOffset + newByteOffset - 1
- 		put: value
- 		length: newLength!

Item was added:
+ ----- Method: ExternalData class>>fromHandle: (in category 'instance creation') -----
+ fromHandle: aHandle
+ 	"We need type information. See #fromHandle:type:"
+ 	self shouldNotImplement.!

Item was added:
+ ----- Method: ExternalData>>eighth (in category 'accessing - convenience') -----
+ eighth
+ 
+ 	^ self at: 8!

Item was added:
+ ----- Method: ExternalData>>fifth (in category 'accessing - convenience') -----
+ fifth
+ 
+ 	^ self at: 5!

Item was added:
+ ----- Method: ExternalData>>first (in category 'accessing - convenience') -----
+ first
+ 
+ 	^ self at: 1!

Item was added:
+ ----- Method: ExternalData>>fourth (in category 'accessing - convenience') -----
+ fourth
+ 
+ 	^ self at: 4!

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 newType |
  	((1 > firstIndex) or: [size notNil and: [lastIndex > size]])
  		ifTrue: [^ self errorSubscriptBounds: lastIndex].
  
  	byteOffset := ((firstIndex-1) * self contentType byteSize)+1.
+ 	numElements := lastIndex - firstIndex + 1 max: 0.
- 	numElements := lastIndex - firstIndex + 1.
  	byteSize := numElements * self contentType byteSize.
  	
  	"For portions of a null-terminated C string, change the type from char* to byte* to avoid confusion."
  	newType := self containerType = ExternalType string
  		ifTrue: [ExternalType byte asPointerType]
  		ifFalse: [self containerType "No change"].
  
+ 	^ (ExternalData
+ 		fromHandle: (handle structAt: byteOffset length: byteSize)
+ 		type: newType) size: numElements; yourself!
- 	^ lastIndex < firstIndex
- 		ifTrue: [
- 			handle isExternalAddress
- 				ifTrue: [(ExternalData
- 							fromHandle: handle + (byteOffset - 1) "Keep pointer."
- 							type: newType) size: 0; yourself]
- 				ifFalse: [(ExternalData
- 							fromHandle: #[] "Empty memory"
- 							type: newType) size: 0; yourself]]
- 		ifFalse: [
- 			handle isExternalAddress
- 				ifTrue: [(ExternalData
- 							fromHandle: handle + (byteOffset - 1)
- 							type: newType) size: numElements; yourself]
- 				ifFalse: [(ExternalData
- 							fromHandle: (handle copyFrom: byteOffset to: byteOffset+byteSize-1)
- 							type: newType) size: numElements; yourself]]!

Item was added:
+ ----- Method: ExternalData>>ninth (in category 'accessing - convenience') -----
+ ninth
+ 
+ 	^ self at: 9!

Item was added:
+ ----- Method: ExternalData>>second (in category 'accessing - convenience') -----
+ second
+ 
+ 	^ self at: 2!

Item was added:
+ ----- Method: ExternalData>>seventh (in category 'accessing - convenience') -----
+ seventh
+ 
+ 	^ self at: 7!

Item was added:
+ ----- Method: ExternalData>>sixth (in category 'accessing - convenience') -----
+ sixth
+ 
+ 	^ self at: 6!

Item was added:
+ ----- Method: ExternalData>>third (in category 'accessing - convenience') -----
+ third
+ 
+ 	^ self at: 3!

Item was added:
+ ----- Method: ExternalData>>writer (in category 'accessing') -----
+ writer
+ 	"Overwritten to preserve type and size."
+ 	handle isInternalMemory ifFalse: [^ self].
+ 	
+ 	^ (self class
+ 		fromHandle: (ByteArrayReadWriter on: handle)
+ 		type: type) size: size; yourself!

Item was added:
+ ----- Method: ExternalStructure>>reader (in category 'accessing') -----
+ reader
+ 
+ 	^ self writer!

Item was changed:
  ----- Method: ExternalStructure>>writer (in category 'accessing') -----
  writer
  
  	^ handle isInternalMemory
  		"Wrap handle into helper to address offsets in the byte array."
+ 		ifTrue: [self class fromHandle: (ByteArrayReadWriter on: handle)]
- 		ifTrue: [self class fromHandle: (ByteArrayWriter on: handle)]
  		"Either alias-to-atomic or already in external memory."
  		ifFalse: [self]!



More information about the Squeak-dev mailing list