[Vm-dev] VM Maker: VMMaker.oscog-eem.1687.mcz
commits at source.squeak.org
commits at source.squeak.org
Sat Feb 20 20:09:02 UTC 2016
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.1687.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.1687
Author: eem
Time: 20 February 2016, 12:07:16.278693 pm
UUID: fde8cc46-be93-419f-8087-ef54c0b4f237
Ancestors: VMMaker.oscog-eem.1686
Fix the signature of characterbjectOf:.
Fix slips in ThreadedFFICalloutStateForX64>>initialize.
Fix 32-bit int vs 64-bit pointers issues in primitiveFFI[Allocate|Free].
Get X64SysVFFI plugin to deal with sixteen byte struct return.
=============== Diff against VMMaker.oscog-eem.1686 ===============
Item was changed:
----- Method: InterpreterProxy>>characterObjectOf: (in category 'object access') -----
characterObjectOf: characterCode
<option: #(atLeastVMProxyMajor:minor: 1 13)>
+ <var: #cPtr type: #int>
^StackInterpreter objectMemoryClass characterObjectOf: characterCode!
Item was changed:
----- Method: ThreadedFFICalloutStateForX64>>initialize (in category 'initialize-release') -----
initialize
super initialize.
+ integerRegisterIndex := floatRegisterIndex := 0.
- registerIndex := 0.
integerRegisters := CArrayAccessor on: (Array new: self class pluginClass numRegArgs).
floatRegisters := CArrayAccessor on: (Array new: self class pluginClass numFloatRegArgs)!
Item was changed:
----- Method: ThreadedFFIPlugin>>ffiCheckReturn:With:in: (in category 'callout support') -----
ffiCheckReturn: retSpec With: retClass in: calloutState
<var: #calloutState type: #'CalloutState *'>
"Make sure we can return an object of the given type"
<inline: true>
+ retClass = interpreterProxy nilObject ifFalse:
+ [(interpreterProxy
+ includesBehavior: retClass
+ ThatOf: interpreterProxy classExternalStructure) ifFalse:
+ [^FFIErrorBadReturn]].
- | ffiRetSpec |
- retClass = interpreterProxy nilObject ifFalse:[
- (interpreterProxy includesBehavior: retClass
- ThatOf: interpreterProxy classExternalStructure)
- ifFalse:[^FFIErrorBadReturn]].
+ ((interpreterProxy isWords: retSpec)
+ and: [(interpreterProxy slotSizeOf: retSpec) > 0]) ifFalse:
+ [^FFIErrorWrongType].
+
+ calloutState ffiRetHeader: (interpreterProxy fetchLong32: 0 ofObject: retSpec).
+ (self isAtomicType: calloutState ffiRetHeader) ifFalse:
+ [retClass = interpreterProxy nilObject ifTrue:
+ [^FFIErrorBadReturn]].
- (interpreterProxy isWords: retSpec)
- ifFalse:[^FFIErrorWrongType].
- (interpreterProxy slotSizeOf: retSpec) = 0 ifTrue:[^FFIErrorWrongType].
- ffiRetSpec := self cCoerce: (interpreterProxy firstIndexableField: retSpec) to: #int.
- calloutState ffiRetHeader: (interpreterProxy longAt: ffiRetSpec).
- (self isAtomicType: calloutState ffiRetHeader) ifFalse:[
- (retClass = interpreterProxy nilObject)
- ifTrue:[^FFIErrorBadReturn]].
(calloutState ffiRetHeader bitAnd: (FFIFlagPointer bitOr: FFIFlagStructure)) = FFIFlagStructure ifTrue:
[calloutState structReturnSize: (calloutState ffiRetHeader bitAnd: FFIStructSizeMask)].
^0!
Item was changed:
----- Method: ThreadedFFIPlugin>>primitiveFFIAllocate (in category 'primitives') -----
primitiveFFIAllocate
"Primitive. Allocate an object on the external heap."
| byteSize addr oop ptr |
<export: true>
<inline: false>
+ <var: #ptr type: #'long *'>
- <var: #ptr type:'int *'>
byteSize := interpreterProxy stackIntegerValue: 0.
+ interpreterProxy failed ifTrue:
+ [^nil].
- interpreterProxy failed ifTrue:[^nil].
addr := self ffiAlloc: byteSize.
+ addr = 0 ifTrue:
+ [^interpreterProxy primitiveFail].
- addr = 0 ifTrue:[^interpreterProxy primitiveFail].
oop := interpreterProxy
instantiateClass: interpreterProxy classExternalAddress
+ indexableSize: (self sizeof: #long).
- indexableSize: 4.
ptr := interpreterProxy firstIndexableField: oop.
ptr at: 0 put: addr.
^interpreterProxy pop: 2 thenPush: oop!
Item was changed:
----- Method: ThreadedFFIPlugin>>primitiveFFIFree (in category 'primitives') -----
primitiveFFIFree
"Primitive. Free the object pointed to on the external heap."
| addr oop ptr |
<export: true>
<inline: false>
+ <var: #ptr type: #'long *'>
- <var: #ptr type:'int *'>
oop := interpreterProxy stackObjectValue: 0.
+ ((interpreterProxy fetchClassOf: oop) = interpreterProxy classExternalAddress
+ and: [(interpreterProxy byteSizeOf: oop) = (self sizeof: #long)]) ifFalse:
+ [^interpreterProxy primitiveFail].
- interpreterProxy failed ifTrue:[^nil].
- (interpreterProxy fetchClassOf: oop) = (interpreterProxy classExternalAddress)
- ifFalse:[^interpreterProxy primitiveFail].
- (interpreterProxy byteSizeOf: oop) = 4
- ifFalse:[^interpreterProxy primitiveFail].
ptr := interpreterProxy firstIndexableField: oop.
addr := ptr at: 0.
"Don't you dare to free Squeak's memory!!"
+ (addr = 0
+ or: [(addr asUnsignedLong bitAnd: (self sizeof: #long) - 1) ~= 0
+ or: [interpreterProxy isInMemory: addr]]) ifTrue:
+ [^interpreterProxy primitiveFail].
- (addr = 0 or:[interpreterProxy isInMemory: addr])
- ifTrue:[^interpreterProxy primitiveFail].
self ffiFree: addr.
+ ^ptr at: 0 put: 0 "cleanup"!
- ^ptr at: 0 put: 0. "cleanup"
- !
Item was changed:
----- Method: ThreadedFFIPlugin>>primitiveLoadSymbolFromModule (in category 'primitives') -----
primitiveLoadSymbolFromModule
"Attempt to find the address of a symbol in a loaded library.
loadSymbol: aSymbol fromModule: moduleName
<primitive: 'primitiveLoadSymbolFromModule' error: errorCode module: 'SqueakFFIPrims'>
"
<export: true>
| symbol module moduleHandle address oop ptr |
<var: #address type: #'void *'>
<var: #ptr type:'unsigned int *'>
interpreterProxy methodArgumentCount = 2 ifFalse:
[^interpreterProxy primitiveFailFor: PrimErrBadNumArgs].
module := interpreterProxy stackValue: 0.
symbol := interpreterProxy stackValue: 1.
moduleHandle := self ffiLoadCalloutModule: module.
interpreterProxy failed ifTrue:
[^interpreterProxy primitiveFailFor: PrimErrNotFound].
address := interpreterProxy
ioLoadSymbol: (self cCoerce: (interpreterProxy firstIndexableField: symbol) to: #sqInt)
OfLength: (interpreterProxy byteSizeOf: symbol)
FromModule: moduleHandle.
(interpreterProxy failed
or: [address = 0]) ifTrue:
[^interpreterProxy primitiveFailFor: PrimErrNotFound].
oop := interpreterProxy
instantiateClass: interpreterProxy classExternalAddress
indexableSize: 4.
ptr := interpreterProxy firstIndexableField: oop.
ptr at: 0 put: address.
+ ^interpreterProxy methodReturnValue: oop!
- interpreterProxy methodReturnValue: oop!
Item was changed:
----- Method: ThreadedFFIPlugin>>primitiveSetManualSurfacePointer (in category 'primitives - surfaces') -----
primitiveSetManualSurfacePointer
"Create a 'manual surface' data-structure. See the ExternalForm class in the FFI package for example usage."
"arguments: name(type, stack offset)
surfaceID(Integer, 1)
+ ptr(uint32/uint64, 0)"
- ptr(uint32, 0)"
| surfaceID ptr result |
<export: true>
+ <var: #ptr type: #'unsigned long'>
- <var: #ptr type: #'unsigned int'>
+ interpreterProxy methodArgumentCount = 2 ifFalse: [^interpreterProxy primitiveFail].
- interpreterProxy methodArgumentCount == 2 ifFalse: [^interpreterProxy primitiveFail].
surfaceID := interpreterProxy stackIntegerValue: 1.
+ ptr := interpreterProxy positiveMachineIntegerValueOf: (interpreterProxy stackValue: 0).
- ptr := interpreterProxy positive32BitValueOf: (interpreterProxy stackValue: 0).
interpreterProxy failed ifTrue: [^nil].
self touch: surfaceID; touch: ptr.
+ result := self setManualSurface: surfaceID Pointer: ptr asVoidPointer.
- result := self cCode: 'setManualSurfacePointer(surfaceID, (void*)ptr)'.
result = 0 ifTrue: [^interpreterProxy primitiveFail].
^interpreterProxy pop: 2
!
Item was added:
+ ----- Method: ThreadedFFIX64SixteenByteReturn class>>instVarNamesAndTypesForTranslationDo: (in category 'translation') -----
+ instVarNamesAndTypesForTranslationDo: aBinaryBlock
+ "enumerate aBinaryBlock with the names and C type strings for the inst vars to include in a BlockStart struct."
+
+ self instVarNames do:
+ [:ivn|
+ aBinaryBlock value: ivn value: #sqInt]!
Item was added:
+ ----- Method: ThreadedFFIX64SixteenByteReturn>>a (in category 'accessing') -----
+ a
+
+ ^ a!
Item was added:
+ ----- Method: ThreadedFFIX64SixteenByteReturn>>a: (in category 'accessing') -----
+ a: anObject
+
+ ^a := anObject!
Item was added:
+ ----- Method: ThreadedFFIX64SixteenByteReturn>>b (in category 'accessing') -----
+ b
+
+ ^ b!
Item was added:
+ ----- Method: ThreadedFFIX64SixteenByteReturn>>b: (in category 'accessing') -----
+ b: anObject
+
+ ^b := anObject!
Item was added:
+ ----- Method: ThreadedX64SysVFFIPlugin class>>ancilliaryClasses: (in category 'translation') -----
+ ancilliaryClasses: options
+ ^{ self calloutStateClass. ThreadedFFIX64SixteenByteReturn }!
Item was changed:
----- Method: ThreadedX64SysVFFIPlugin>>ffiCalloutTo:SpecOnStack:in: (in category 'callout support') -----
ffiCalloutTo: procAddr SpecOnStack: specOnStack in: calloutState
<var: #procAddr type: #'void *'>
<var: #calloutState type: #'CalloutState *'>
<var: #loadFloatRegs declareC: 'extern void loadFloatRegs(double, double, double, double, double, double, double, double)'>
"Go out, call this guy and create the return value. This *must* be inlined because of
the alloca of the outgoing stack frame in ffiCall:WithFlags:NumArgs:Args:AndTypes:"
| myThreadIndex atomicType floatRet intRet loadFloatRegs oop |
<var: #floatRet type: #double>
<var: #intRet type: 'SixteenByteReturn'>
<inline: true>
self cCode: '' inSmalltalk: [loadFloatRegs := #used. loadFloatRegs class].
self cppIf: COGMTVM ifTrue:
[(calloutState callFlags anyMask: FFICallFlagThreaded) ifTrue:
[myThreadIndex := interpreterProxy disownVM: 0]].
self registerArgsSlop + self cStackAlignment > 0 ifTrue:
[self setsp: calloutState argVector].
calloutState floatRegisterIndex > 0 ifTrue:
[self
load: (calloutState floatRegisters at: 0)
Flo: (calloutState floatRegisters at: 1)
a: (calloutState floatRegisters at: 2)
t: (calloutState floatRegisters at: 3)
R: (calloutState floatRegisters at: 4)
e: (calloutState floatRegisters at: 5)
g: (calloutState floatRegisters at: 6)
s: (calloutState floatRegisters at: 7)].
atomicType := self atomicTypeOf: calloutState ffiRetHeader.
(atomicType >> 1) = (FFITypeSingleFloat > 1)
ifTrue:
[atomicType = FFITypeSingleFloat
ifTrue:
[floatRet := self
dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'float (*)(long, long, long, long, long, long)')
with: (calloutState integerRegisters at: 0)
with: (calloutState integerRegisters at: 1)
with: (calloutState integerRegisters at: 2)
with: (calloutState integerRegisters at: 3)
with: (calloutState integerRegisters at: 4)
with: (calloutState integerRegisters at: 5)]
ifFalse: "atomicType = FFITypeDoubleFloat"
[floatRet := self
dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'double (*)(long, long, long, long, long, long)')
with: (calloutState integerRegisters at: 0)
with: (calloutState integerRegisters at: 1)
with: (calloutState integerRegisters at: 2)
with: (calloutState integerRegisters at: 3)
with: (calloutState integerRegisters at: 4)
with: (calloutState integerRegisters at: 5)]]
ifFalse:
[intRet := self
dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'SixteenByteReturn (*)(long, long, long, long, long, long)')
with: (calloutState integerRegisters at: 0)
with: (calloutState integerRegisters at: 1)
with: (calloutState integerRegisters at: 2)
with: (calloutState integerRegisters at: 3)
with: (calloutState integerRegisters at: 4)
with: (calloutState integerRegisters at: 5)].
"undo any callee argument pops because it may confuse stack management with the alloca."
(self isCalleePopsConvention: calloutState callFlags) ifTrue:
[self setsp: calloutState argVector].
self cppIf: COGMTVM ifTrue:
[(calloutState callFlags anyMask: FFICallFlagThreaded) ifTrue:
[interpreterProxy ownVM: myThreadIndex]].
(calloutState ffiRetHeader anyMask: FFIFlagPointer+FFIFlagStructure) ifTrue:
["Note: Order is important here since FFIFlagPointer + FFIFlagStructure is used to represent
'typedef void* VoidPointer' and VoidPointer must be returned as pointer *not* as struct."
(calloutState ffiRetHeader anyMask: FFIFlagPointer)
ifTrue:
+ [oop := self ffiReturnPointer: intRet a ofType: (self ffiReturnType: specOnStack) in: calloutState]
- [oop := self ffiReturnPointer: intRet ofType: (self ffiReturnType: specOnStack) in: calloutState]
ifFalse:
[oop := self ffiReturnStruct: intRet ofType: (self ffiReturnType: specOnStack) in: calloutState].
^oop].
(atomicType >> 1) = (FFITypeSingleFloat > 1)
ifTrue:
[oop := interpreterProxy floatObjectOf: floatRet]
ifFalse:
+ [oop := self ffiCreateIntegralResultOop: intRet a
- [oop := self ffiCreateIntegralResultOop: intRet
ofAtomicType: atomicType
in: calloutState].
^interpreterProxy methodReturnValue: oop!
Item was changed:
----- Method: ThreadedX64SysVFFIPlugin>>ffiReturnStruct:ofType:in: (in category 'callout support') -----
ffiReturnStruct: sixteenByteRet ofType: ffiRetType in: calloutState
<var: #sixteenByteRet type: 'SixteenByteReturn'>
<var: #calloutState type: #'CalloutState *'>
"Create a structure return value from an external function call. The value has been stored in
alloca'ed space pointed to by the calloutState or in the return value."
| retOop retClass oop |
<inline: true>
retClass := interpreterProxy fetchPointer: 1 ofObject: ffiRetType.
retOop := interpreterProxy instantiateClass: retClass indexableSize: 0.
self remapOop: retOop
in: [oop := interpreterProxy
instantiateClass: interpreterProxy classByteArray
indexableSize: calloutState structReturnSize].
self mem: (interpreterProxy firstIndexableField: oop)
cp: ((self returnStructInRegisters: calloutState structReturnSize)
+ ifTrue: [(self addressOf: sixteenByteRet) asVoidPointer]
- ifTrue: [self addressOf: sixteenByteRet]
ifFalse: [calloutState limit])
y: calloutState structReturnSize.
interpreterProxy storePointer: 0 ofObject: retOop withValue: oop.
^interpreterProxy methodReturnValue: retOop!
More information about the Vm-dev
mailing list