A new version of Kernel was added to project The Inbox:
http://source.squeak.org/inbox/Kernel-jar.1400.mcz
==================== Summary ====================
Name: Kernel-jar.1400
Author: jar
Time: 4 May 2021, 10:35:06.700121 pm
UUID: 048df236-d26f-434e-964d-7707b8f2a9a8
Ancestors: Kernel-nice.1397
Fix a bug causing a cannot return error when re-signalling an already signalled exception. The fix makes re-signalling equivalent to sending #outer. Examples follow.
Discussion see http://forum.world.st/The-Inbox-Kernel-jar-1399-mcz-tp5129370p5129434.html
=============== Diff against Kernel-nice.1397 ===============
Item was changed:
----- Method: Exception>>signal (in category 'signaling') -----
signal
"Ask ContextHandlers in the sender chain to handle this signal. The default is to execute and return my defaultAction."
+ signalContext ifNotNil: [^self outer]. "re-signalling an already signalled exception is equivalent to sending #outer"
signalContext := thisContext contextTag.
^(thisContext nextHandlerContextForSignal: self) handleSignal: self!
Marcel Taeumel uploaded a new version of FFI-Tools to project FFI:
http://source.squeak.org/FFI/FFI-Tools-mt.24.mcz
==================== Summary ====================
Name: FFI-Tools-mt.24
Author: mt
Time: 4 May 2021, 4:43:42.172881 pm
UUID: 411d91ef-c5dc-3643-b69f-8c9620d93201
Ancestors: FFI-Tools-mt.23
Make use of the byte-array writer to conveniently explore composite structures along with proper support for do-it. Both of which is fine for heap objects but challenging for handles that are byte arrays.
=============== Diff against FFI-Tools-mt.23 ===============
Item was changed:
----- Method: ExternalObjectHandleWrapper>>objectString (in category 'accessing') -----
objectString
+ | label handle |
+ label := super objectString.
+ handle := self getHandle.
- self getHandle class == ExternalAddress ifTrue: [^ super objectString].
- self getHandle class == ByteArray ifTrue: [^ super objectString].
+ handle isExternalAddress ifTrue: [^ label].
+ handle isInternalMemory ifTrue: [
+ ^ (thisContext objectClass: handle) == ByteArrayReadWriter
+ ifFalse: [label]
+ ifTrue: [ | begin end |
+ label :=(thisContext object: handle instVarAt: 3) printString.
+ label := label copyFrom: 3 to: (label size - 1).
+ begin := (thisContext object: handle instVarAt: 1) + 1.
+ end := begin + (thisContext object: handle instVarAt: 2) - 1.
+ String streamContents: [:stream |
+ stream nextPutAll: '#[ '.
+ (label findTokens: ' ' "#[0 0 0 0 0]") withIndexDo: [:token :index |
+ (index between: begin and: end)
+ ifTrue: [stream nextPutAll: token]
+ ifFalse: ["Skip byte info" stream nextPut: $.].
+ stream space].
+ stream nextPutAll: ']'.
+ ]]].
+
"Type aliases to atomic types store primitive Smalltalk objects in their handle. Indicate that role of actually being a handle for the FFI plugin with a small prefix."
+ ^ '-> ', label!
- ^ '-> ', super objectString!
Item was added:
+ ----- Method: ExternalStructure>>explore (in category '*FFI-Tools') -----
+ explore
+ "Sneak in a reader so that do-its will work better from the obeject explorer."
+
+ self reader perform: #explore withArguments: #() inSuperclass: ExternalObject.!
Marcel Taeumel uploaded a new version of FFI-Kernel to project FFI:
http://source.squeak.org/FFI/FFI-Kernel-mt.127.mcz
==================== Summary ====================
Name: FFI-Kernel-mt.127
Author: mt
Time: 4 May 2021, 9:54:26.141881 am
UUID: 143e5c5b-ccff-9143-823d-4d6657005d2c
Ancestors: FFI-Kernel-mt.126
Makes extra type checks optional, disabled by default. (This feature more care because some checks are wrong. Thanks to Ron for reporting this!)
(Also fixes Character zero, which should actually be the NUL character.)
=============== Diff against FFI-Kernel-mt.126 ===============
Item was changed:
----- Method: Character class>>zero (in category '*FFI-Kernel') -----
zero
"See ExternalStructure >> #zeroMemory."
+ ^ Character value: 0!
- ^ $0!
Item was changed:
----- Method: ExternalStructureType>>checkType (in category 'external structure') -----
checkType
+ self class extraTypeChecks ifFalse: [^ self].
+
self
assert: [self isPointerType not]
description: 'Convert to ExternalType to use this feature'.
referentClass ifNil: [self error: 'Unknown structure type'].
self isEmpty ifTrue: [self error: 'Empty structure'].
!
Item was changed:
----- Method: ExternalStructureType>>handle:at: (in category 'external data') -----
handle: handle at: byteOffset
"Read the receiver's external type using the given handle and the byteOffset. This is the dynamic version of #readFieldAt:."
| result |
+ self checkType.
- self
- assert: [self isPointerType not]
- description: 'Use ExternalStructure to use this feature.'.
- referentClass ifNil: [self error: 'Unknown structure type'].
- self isEmpty ifTrue: [self error: 'Empty structure'].
-
result := self isAtomic
ifTrue: [
handle "alias to atomic"
perform: (AtomicSelectors at: self atomicType)
with: byteOffset]
ifFalse: [
handle "regular struct or alias to struct or alias to pointer"
structAt: byteOffset length: self byteSize].
^ referentClass fromHandle: result!
Item was changed:
----- Method: ExternalStructureType>>handle:at:put: (in category 'external data') -----
handle: handle at: byteOffset put: value
"Write a value using the receiver's external type at the given handle and byteOffset. This is the dynamic version of #writeFieldAt:with:."
+ self checkType.
- self
- assert: [self isPointerType not]
- description: 'Use ExternalType to use this feature.'.
-
- referentClass ifNil: [self error: 'Unknown structure type'].
- self isEmpty ifTrue: [self error: 'Empty structure'].
self isAtomic
ifTrue: [ "alias to atomic"
self flag: #addTypeCheck. "mt: Note that there is currently no mapping from objects that represent valid atomics to atomic types."
^ handle
perform: ((AtomicSelectors at: self atomicType), 'put:') asSymbol
with: byteOffset
with: value getHandle]
ifFalse: [ "regular struct or alias to struct or alias to pointer"
self assert: [value externalType == self].
^ handle
structAt: byteOffset
put: value getHandle
length: self byteSize].!
Item was changed:
----- Method: ExternalStructureType>>writeAliasWith: (in category 'external structure') -----
writeAliasWith: valueName
"this is an aliased structure type"
"expect the value have that structure type with either byte array or external address as handle"
self checkType.
^ String streamContents: [:s |
+ self class extraTypeChecks ifTrue: [
+ s nextPutAll: ('self assert: [{1} class externalType == {2}].' format: {valueName. self storeString}); crtab].
- s nextPutAll: ('self assert: [{1} class externalType == {2}].' format: {valueName. self storeString}); crtab.
s nextPutAll:'handle := ', valueName,' getHandle']!
Item was changed:
----- Method: ExternalStructureType>>writeFieldAt:with: (in category 'external structure') -----
writeFieldAt: byteOffset with: valueName
"Answer a string defining the accessor to an entity of the receiver type starting at the given byte offset.
Private. Used for field definition only."
self checkType.
^String streamContents:[:s|
self isAtomic
ifTrue: [ "alias to atomic"
+ self class extraTypeChecks ifTrue: [
+ self flag: #addTypeCheck. "mt: Note that there is currently no mapping from objects that represent valid atomics to atomic types."].
- self flag: #addTypeCheck. "mt: Note that there is currently no mapping from objects that represent valid atomics to atomic types."
s nextPutAll:'handle ';
nextPutAll: (AtomicSelectors at: self atomicType);
space; print: byteOffset;
nextPutAll:' put: ';
nextPutAll: valueName;
nextPutAll: ' getHandle']
ifFalse: [ "regular struct or alias to struct or alias to pointer"
+ self class extraTypeChecks ifTrue: ["expect either byte array or external address as handle"
+ s nextPutAll: ('self assert: [{1} class externalType == {2}].' format: {valueName. self storeString}); crtab].
- "expect either byte array or external address as handle"
- s nextPutAll: ('self assert: [{1} class externalType == {2}].' format: {valueName. self storeString}); crtab.
self isTypeAliasForPointer
ifFalse: [
s nextPutAll:'handle structAt: ';
print: byteOffset;
nextPutAll:' put: ';
nextPutAll: valueName;
nextPutAll:' getHandle';
nextPutAll:' length: ';
print: self byteSize;
nextPutAll:'.']
ifTrue: [
s nextPutAll:'handle pointerAt: ';
print: byteOffset;
nextPutAll:' put: ';
nextPutAll: valueName;
nextPutAll:' getHandle asExternalPointer';
nextPutAll:' length: ';
print: self byteSize;
nextPutAll:'.']]].!
Item was changed:
Object subclass: #ExternalType
instanceVariableNames: 'compiledSpec referentClass referencedType byteAlignment'
+ classVariableNames: 'AtomicSelectors AtomicTypeNames AtomicTypes ExtraTypeChecks StructTypes'
- classVariableNames: 'AtomicSelectors AtomicTypeNames AtomicTypes StructTypes'
poolDictionaries: 'FFIConstants'
category: 'FFI-Kernel'!
!ExternalType commentStamp: 'mt 6/5/2020 18:25' prior: 0!
An external type represents the type of external objects.
Instance variables:
compiledSpec <WordArray> Compiled specification of the external type
referentClass <Behavior | nil> Class type of argument required
referencedType <ExternalType> Associated (non)pointer type with the receiver
byteAlignment <Integer | nil> The desired alignment for a field of the external type within a structure. If nil it has yet to be computed.
Compiled Spec:
The compiled spec defines the type in terms which are understood by the VM. Each word is defined as:
bits 0...15 - byte size of the entity
bit 16 - structure flag (FFIFlagStructure)
This flag is set if the following words define a structure
bit 17 - pointer flag (FFIFlagPointer)
This flag is set if the entity represents a pointer to another object
bit 18 - atomic flag (FFIFlagAtomic)
This flag is set if the entity represents an atomic type.
If the flag is set the atomic type bits are valid.
bits 19...23 - unused
bits 24...27 - atomic type (FFITypeVoid ... FFITypeDoubleFloat)
bits 28...31 - unused
Note that all combinations of the flags FFIFlagPointer, FFIFlagAtomic, and FFIFlagStructure are invalid, EXCEPT from the following:
FFIFlagPointer + FFIFlagAtomic:
This defines a pointer to an atomic type (e.g., 'char*', 'int*').
The actual atomic type is represented in the atomic type bits.
FFIFlagPointer + FFIFlagStructure:
This defines a structure which is a typedef of a pointer type as in
typedef void* VoidPointer;
typedef Pixmap* PixmapPtr;
It requires a byte size of four or eight (e.g. a 32-bit or 64-bit pointer) to work correctly.
[Note: Other combinations may be allowed in the future]
!
Item was added:
+ ----- Method: ExternalType class>>extraTypeChecks (in category 'preferences') -----
+ extraTypeChecks
+ <preference: 'Extra type checks'
+ categoryList: #('FFI Kernel')
+ description: 'When true, there will be extra type checks during dynamic or compiled access to external objects (e.g. structures, unions).'
+ type: #Boolean>
+ ^ExtraTypeChecks ifNil:[false]!
Item was added:
+ ----- Method: ExternalType class>>extraTypeChecks: (in category 'preferences') -----
+ extraTypeChecks: aBoolean
+
+ ExtraTypeChecks = aBoolean ifTrue: [^ self].
+
+ ExtraTypeChecks := aBoolean.
+
+ Cursor wait showWhile: [
+ "Recompile all compiled artifacts."
+ ExternalStructure defineAllFields].!
Item was changed:
----- Method: ExternalType>>checkType (in category 'external structure') -----
checkType
+ self class extraTypeChecks ifFalse: [^ self].
+
(self isPointerType not and: [referentClass notNil])
ifTrue: [self error: 'Must convert to ExternalStructureType before use'].
self
assert: [self isStructureType not]
description: 'Convert to ExternalStructureType to use this feature'.!
Item was changed:
----- Method: ExternalType>>writeAliasWith: (in category 'external structure') -----
writeAliasWith: valueName
self checkType.
^ String streamContents: [:s |
self isPointerType
ifFalse: [
"this is an aliased atomic non-pointer type"
+ self class extraTypeChecks ifTrue: [
+ self flag: #addTypeCheck. "mt: Note that there is currently no mapping from objects that represent valid atomics to atomic types."].
- self flag: #addTypeCheck. "mt: Note that there is currently no mapping from objects that represent valid atomics to atomic types."
s nextPutAll:'handle := ', valueName, '.']
ifTrue: [
"this is an aliased pointer type"
+ self class extraTypeChecks ifTrue: ["expect the value to be a structure/union/alias/data with an external address as handle"
+ s nextPutAll: ('self assert: [{1} externalType == {2}].' format: {valueName. self storeString}); crtab].
- "expect the value to be a structure/union/alias/data with an external address as handle"
- s nextPutAll: ('self assert: [{1} externalType == {2}].' format: {valueName. self storeString}); crtab.
s nextPutAll:'handle := ', valueName,' getHandle asByteArrayPointer']]!
Item was changed:
----- Method: ExternalType>>writeFieldAt:with: (in category 'external structure') -----
writeFieldAt: byteOffset with: valueName
"Answer a string defining the accessor to an entity of the receiver type starting at the given byte offset.
Private. Used for field definition only."
self checkType.
^ String streamContents: [:s |
self isPointerType
ifFalse: [
"Atomic value"
+ self class extraTypeChecks ifTrue: [
+ self flag: #addTypeCheck. "mt: Note that there is currently no mapping from objects that represent valid atomics to atomic types."].
- self flag: #addTypeCheck. "mt: Note that there is currently no mapping from objects that represent valid atomics to atomic types."
s nextPutAll:'handle ';
nextPutAll: (AtomicSelectors at: self atomicType);
space; print: byteOffset;
nextPutAll:' put: ';
nextPutAll: valueName]
ifTrue: [
"Pointer to structure, union, type alias, or external data."
+ self class extraTypeChecks ifTrue: [
+ s nextPutAll: ('self assert: [{1} externalType == {2}].' format: {valueName. self storeString}); crtab].
- s nextPutAll: ('self assert: [{1} externalType == {2}].' format: {valueName. self storeString}); crtab.
s nextPutAll:'handle pointerAt: ';
print: byteOffset;
nextPutAll:' put: ';
nextPutAll: valueName;
nextPutAll:' getHandle';
nextPutAll: ' length: ';
print: self byteSize;
nextPutAll: '.']]!
Item was changed:
(PackageInfo named: 'FFI-Kernel') postscript: 'Smalltalk removeFromStartUpList: ExternalAddress.
Smalltalk removeFromStartUpList: ExternalObject.
"Split up types for external structures from atomic types."
ExternalType resetAllStructureTypes.
+ "Re-generate all field accessors because type checks are now controlled by a new preference."
- "Re-generate all field accessors because there are now type checks, too."
ExternalStructure defineAllFields.
'!