Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.1409.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.1409 Author: eem Time: 10 July 2015, 1:59:54.741 pm UUID: 428ff402-b7ce-44c6-a95d-5db172a1e43f Ancestors: VMMaker.oscog-eem.1408
Fix slangification of ThreadedFFIPlugin. Eliminate a few warnings there-in.
Make type of tenuringIncrementalGC agree with sqVirtualMachine.h.
Provide a back dorr for the ARM division routines diuring simulation.
=============== Diff against VMMaker.oscog-eem.1408 ===============
Item was added: + ----- Method: Cogit>>handleABICallOrJumpSimulationTrap:evaluable: (in category 'simulation only') ----- + handleABICallOrJumpSimulationTrap: aProcessorSimulationTrap evaluable: evaluable + self assert: aProcessorSimulationTrap type = #call. + processor + simulateLeafCallOf: aProcessorSimulationTrap address + nextpc: aProcessorSimulationTrap nextpc + memory: coInterpreter memory. + self recordInstruction: {'(simulated call of '. aProcessorSimulationTrap address. '/'. evaluable selector. ')'}. + evaluable valueWithArguments: (processor + postCallArgumentsNumArgs: evaluable numArgs + in: coInterpreter memory). + self recordInstruction: {'(simulated return to '. processor retpcIn: coInterpreter memory. ')'}. + processor + smashCallerSavedRegistersWithValuesFrom: 16r80000000 by: objectMemory wordSize; + simulateLeafReturnIn: coInterpreter memory!
Item was changed: ----- Method: Cogit>>handleCallOrJumpSimulationTrap: (in category 'simulation only') ----- handleCallOrJumpSimulationTrap: aProcessorSimulationTrap <doNotGenerate> | evaluable function result savedFramePointer savedStackPointer savedArgumentCount rpc | evaluable := simulatedTrampolines at: aProcessorSimulationTrap address. + function := evaluable isBlock + ifTrue: ['aBlock; probably some plugin primitive'] + ifFalse: + [evaluable receiver == backEnd ifTrue: + [^self handleABICallOrJumpSimulationTrap: aProcessorSimulationTrap evaluable: evaluable]. + evaluable selector]. - function := evaluable - isBlock ifTrue: ['aBlock; probably some plugin primitive'] - ifFalse: [evaluable selector]. function ~~ #ceBaseFrameReturn: ifTrue: [coInterpreter assertValidExternalStackPointers]. (function beginsWith: 'ceShort') ifTrue: [^self perform: function with: aProcessorSimulationTrap]. aProcessorSimulationTrap type = #call ifTrue: [processor simulateCallOf: aProcessorSimulationTrap address nextpc: aProcessorSimulationTrap nextpc memory: coInterpreter memory. self recordInstruction: {'(simulated call of '. aProcessorSimulationTrap address. '/'. function. ')'}] ifFalse: [processor simulateJumpCallOf: aProcessorSimulationTrap address memory: coInterpreter memory. self recordInstruction: {'(simulated jump to '. aProcessorSimulationTrap address. '/'. function. ')'}]. savedFramePointer := coInterpreter framePointer. savedStackPointer := coInterpreter stackPointer. savedArgumentCount := coInterpreter argumentCount. result := ["self halt: evaluable selector." evaluable valueWithArguments: (processor postCallArgumentsNumArgs: evaluable numArgs in: coInterpreter memory)] on: ReenterMachineCode do: [:ex| ex return: ex returnValue]. coInterpreter assertValidExternalStackPointers. "Verify the stack layout assumption compileInterpreterPrimitive: makes, provided we've not called something that has built a frame, such as closure value or evaluate method, or switched frames, such as primitiveSignal, primitiveWait, primitiveResume, primitiveSuspend et al." (function beginsWith: 'primitive') ifTrue: [coInterpreter checkForLastObjectOverwrite. coInterpreter primFailCode = 0 ifTrue: [(#( primitiveClosureValue primitiveClosureValueWithArgs primitiveClosureValueNoContextSwitch primitiveSignal primitiveWait primitiveResume primitiveSuspend primitiveYield primitiveExecuteMethodArgsArray primitiveExecuteMethod primitivePerform primitivePerformWithArgs primitivePerformInSuperclass primitiveTerminateTo primitiveStoreStackp primitiveDoPrimitiveWithArgs) includes: function) ifFalse: [self assert: savedFramePointer = coInterpreter framePointer. self assert: savedStackPointer + (savedArgumentCount * objectMemory wordSize) = coInterpreter stackPointer]] ifFalse: [self assert: savedFramePointer = coInterpreter framePointer. self assert: savedStackPointer = coInterpreter stackPointer]]. result ~~ #continueNoReturn ifTrue: [self recordInstruction: {'(simulated return to '. processor retpcIn: coInterpreter memory. ')'}. rpc := processor retpcIn: coInterpreter memory. self assert: (rpc >= codeBase and: [rpc < methodZone freeStart]). processor smashCallerSavedRegistersWithValuesFrom: 16r80000000 by: objectMemory wordSize; simulateReturnIn: coInterpreter memory]. self assert: (result isInteger "an oop result" or: [result == coInterpreter or: [result == objectMemory or: [#(nil continue continueNoReturn) includes: result]]]). processor cResultRegister: (result ifNil: [0] ifNotNil: [result isInteger ifTrue: [result] ifFalse: [16rF00BA222]])
"coInterpreter cr. processor sp + 32 to: processor sp - 32 by: -4 do: [:sp| sp = processor sp ifTrue: [coInterpreter print: 'sp->'; tab] ifFalse: [coInterpreter printHex: sp]. coInterpreter tab; printHex: (coInterpreter longAt: sp); cr]"!
Item was changed: ----- Method: InterpreterProxy>>tenuringIncrementalGC (in category 'other') ----- tenuringIncrementalGC + <returnTypeC: #void> - <returnTypeC: #sqInt> Smalltalk forceTenuring; garbageCollectMost!
Item was changed: ----- Method: ThreadedARMFFIPlugin>>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: #usqLong> <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: ((self cCoerceSimple: (self addressOf: (calloutState floatRegisters at: 0)) to: 'double *') at: 0) Flo: ((self cCoerceSimple: (self addressOf: (calloutState floatRegisters at: 2)) to: 'double *') at: 0) a: ((self cCoerceSimple: (self addressOf: (calloutState floatRegisters at: 4)) to: 'double *') at: 0) t: ((self cCoerceSimple: (self addressOf: (calloutState floatRegisters at: 6)) to: 'double *') at: 0) R: ((self cCoerceSimple: (self addressOf: (calloutState floatRegisters at: 8)) to: 'double *') at: 0) e: ((self cCoerceSimple: (self addressOf: (calloutState floatRegisters at: 10)) to: 'double *') at: 0) g: ((self cCoerceSimple: (self addressOf: (calloutState floatRegisters at: 12)) to: 'double *') at: 0) s: ((self cCoerceSimple: (self addressOf: (calloutState floatRegisters at: 14)) to: 'double *') at: 0)].
atomicType := self atomicTypeOf: calloutState ffiRetHeader. (atomicType >> 1) = (FFITypeSingleFloat > 1) ifTrue: [atomicType = FFITypeSingleFloat ifTrue: [floatRet := self dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'float (*)(int, int, int, int)') with: (calloutState integerRegisters at: 0) with: (calloutState integerRegisters at: 1) with: (calloutState integerRegisters at: 2) with: (calloutState integerRegisters at: 3)] ifFalse: "atomicType = FFITypeDoubleFloat" [floatRet := self dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'double (*)(int, int, int, int)') with: (calloutState integerRegisters at: 0) with: (calloutState integerRegisters at: 1) with: (calloutState integerRegisters at: 2) with: (calloutState integerRegisters at: 3)]] ifFalse: [intRet := self dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'usqLong (*)(int, int, int, int)') with: (calloutState integerRegisters at: 0) with: (calloutState integerRegisters at: 1) with: (calloutState integerRegisters at: 2) with: (calloutState integerRegisters at: 3)]. "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) - ^(calloutState ffiRetHeader anyMask: FFIFlagPointer) ifTrue: + [oop := self ffiReturnPointer: intRet ofType: (self ffiReturnType: specOnStack) in: calloutState] - [self ffiReturnPointer: intRet ofType: (self ffiReturnType: specOnStack) in: calloutState] ifFalse: + [oop := self ffiReturnStruct: intRet ofType: (self ffiReturnType: specOnStack) in: calloutState]. + ^oop]. - [self ffiReturnStruct: intRet ofType: (self ffiReturnType: specOnStack) in: calloutState]]. (atomicType >> 1) = (FFITypeSingleFloat > 1) ifTrue: [oop := interpreterProxy floatObjectOf: floatRet] ifFalse: [oop := self ffiCreateIntegralResultOop: intRet ofAtomicType: atomicType in: calloutState]. ^interpreterProxy methodReturnValue: oop!
Item was changed: ----- Method: ThreadedARMFFIPlugin>>ffiPushPointer:in: (in category 'marshalling') ----- ffiPushPointer: pointer in: calloutState <var: #pointer type: #'void *'> <var: #calloutState type: #'CalloutState *'> <inline: true> calloutState integerRegisterIndex < NumIntRegArgs ifTrue: + [calloutState integerRegisters at: calloutState integerRegisterIndex put: pointer asInteger. - [calloutState integerRegisters at: calloutState integerRegisterIndex put: pointer. calloutState integerRegisterIndex: calloutState integerRegisterIndex + 1] ifFalse: [calloutState currentArg + 4 > calloutState limit ifTrue: [^FFIErrorCallFrameTooBig]. interpreterProxy longAt: calloutState currentArg put: pointer. calloutState currentArg: calloutState currentArg + 4]. ^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:'int *'> byteSize := interpreterProxy stackIntegerValue: 0. interpreterProxy failed ifTrue:[^nil]. addr := self ffiAlloc: byteSize. addr = 0 ifTrue:[^interpreterProxy primitiveFail]. oop := interpreterProxy instantiateClass: interpreterProxy classExternalAddress indexableSize: 4. ptr := interpreterProxy firstIndexableField: oop. ptr at: 0 put: addr. + ^interpreterProxy pop: 2 thenPush: oop! - interpreterProxy pop: 2 thenPush: oop!
Item was changed: ----- Method: ThreadedFFIPlugin>>primitiveFFIDoubleAtPut (in category 'primitives') ----- primitiveFFIDoubleAtPut "Return a (signed or unsigned) n byte integer from the given byte offset." | byteOffset rcvr addr floatValue floatOop | <export: true> <inline: false> <var: #floatValue type:'double '> floatOop := interpreterProxy stackValue: 0. (interpreterProxy isIntegerObject: floatOop) ifTrue:[floatValue := self cCoerce: (interpreterProxy integerValueOf: floatOop) to:'double'] ifFalse:[floatValue := self cCoerce: (interpreterProxy floatValueOf: floatOop) to:'double']. byteOffset := interpreterProxy stackIntegerValue: 1. rcvr := interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^0]. addr := self ffiAddressOf: rcvr startingAt: byteOffset size: 8. interpreterProxy failed ifTrue:[^0]. self cCode:'((int*)addr)[0] = ((int*)(&floatValue))[0]'. self cCode:'((int*)addr)[1] = ((int*)(&floatValue))[1]'. + ^interpreterProxy pop: 3 thenPush: floatOop! - interpreterProxy pop: 3 thenPush: floatOop!
Item was changed: ----- Method: ThreadedFFIPlugin>>primitiveFFIFloatAtPut (in category 'primitives') ----- primitiveFFIFloatAtPut "Return a (signed or unsigned) n byte integer from the given byte offset." | byteOffset rcvr addr floatValue floatOop | <export: true> <inline: false> <var: #floatValue type:'float '> floatOop := interpreterProxy stackValue: 0. (interpreterProxy isIntegerObject: floatOop) ifTrue:[floatValue := self cCoerce: (interpreterProxy integerValueOf: floatOop) to:'float'] ifFalse:[floatValue := self cCoerce: (interpreterProxy floatValueOf: floatOop) to:'float']. byteOffset := interpreterProxy stackIntegerValue: 1. rcvr := interpreterProxy stackObjectValue: 2. interpreterProxy failed ifTrue:[^0]. addr := self ffiAddressOf: rcvr startingAt: byteOffset size: 4. interpreterProxy failed ifTrue:[^0]. self cCode:'((int*)addr)[0] = ((int*)(&floatValue))[0]'. + ^interpreterProxy pop: 3 thenPush: floatOop! - interpreterProxy pop: 3 thenPush: floatOop!
Item was changed: ----- Method: ThreadedFFIPlugin>>primitiveFFIIntegerAt (in category 'primitives') ----- primitiveFFIIntegerAt "Return a (signed or unsigned) n byte integer from the given byte offset." | isSigned byteSize byteOffset rcvr addr value mask | <export: true> <inline: false> isSigned := interpreterProxy booleanValueOf: (interpreterProxy stackValue: 0). byteSize := interpreterProxy stackIntegerValue: 1. byteOffset := interpreterProxy stackIntegerValue: 2. rcvr := interpreterProxy stackObjectValue: 3. interpreterProxy failed ifTrue:[^0]. (byteOffset > 0 and:[byteSize = 1 or:[byteSize = 2 or:[byteSize = 4]]]) ifFalse:[^interpreterProxy primitiveFail]. addr := self ffiAddressOf: rcvr startingAt: byteOffset size: byteSize. interpreterProxy failed ifTrue:[^0]. byteSize < 4 ifTrue:[ "short/byte" byteSize = 1 ifTrue:[value := interpreterProxy byteAt: addr] ifFalse:[ value := self cCode: '*((unsigned short int *) addr)' inSmalltalk: [interpreterProxy shortAt: addr]]. isSigned ifTrue:["sign extend value" mask := 1 << (byteSize * 8 - 1). value := (value bitAnd: mask-1) - (value bitAnd: mask)]. "note: byte/short never exceed SmallInteger range" value := interpreterProxy integerObjectOf: value. ] ifFalse:[ "general 32 bit integer" value := interpreterProxy longAt: addr. value := isSigned ifTrue:[interpreterProxy signed32BitIntegerFor: value] ifFalse:[interpreterProxy positive32BitIntegerFor: value]. ]. + ^interpreterProxy pop: 4 thenPush: value! - interpreterProxy pop: 4 thenPush: value!
Item was changed: ----- Method: ThreadedFFIPlugin>>primitiveFFIIntegerAtPut (in category 'primitives') ----- primitiveFFIIntegerAtPut "Store a (signed or unsigned) n byte integer at the given byte offset." | isSigned byteSize byteOffset rcvr addr value max valueOop | <export: true> <inline: false> isSigned := interpreterProxy booleanValueOf: (interpreterProxy stackValue: 0). byteSize := interpreterProxy stackIntegerValue: 1. valueOop := interpreterProxy stackValue: 2. byteOffset := interpreterProxy stackIntegerValue: 3. rcvr := interpreterProxy stackObjectValue: 4. interpreterProxy failed ifTrue:[^0]. (byteOffset > 0 and:[byteSize = 1 or:[byteSize = 2 or:[byteSize = 4]]]) ifFalse:[^interpreterProxy primitiveFail]. addr := self ffiAddressOf: rcvr startingAt: byteOffset size: byteSize. interpreterProxy failed ifTrue:[^0]. isSigned ifTrue:[value := interpreterProxy signed32BitValueOf: valueOop] ifFalse:[value := interpreterProxy positive32BitValueOf: valueOop]. interpreterProxy failed ifTrue:[^0]. byteSize < 4 ifTrue:[ isSigned ifTrue:[ max := 1 << (8 * byteSize - 1). value >= max ifTrue:[^interpreterProxy primitiveFail]. value < (0 - max) ifTrue:[^interpreterProxy primitiveFail]. ] ifFalse:[ value >= (1 << (8*byteSize)) ifTrue:[^interpreterProxy primitiveFail]. ]. "short/byte" byteSize = 1 ifTrue:[interpreterProxy byteAt: addr put: value] ifFalse:[ self cCode: '*((short int *) addr) = value' inSmalltalk: [interpreterProxy shortAt: addr put: value]]. ] ifFalse:[interpreterProxy longAt: addr put: value]. + ^interpreterProxy pop: 5 thenPush: valueOop! - interpreterProxy pop: 5 thenPush: valueOop!
Item was changed: ----- Method: ThreadedIA32FFIPlugin>>ffiCalloutTo:SpecOnStack:in: (in category 'callout support') ----- ffiCalloutTo: procAddr SpecOnStack: specOnStack in: calloutState <var: #procAddr type: #'void *'> <var: #calloutState type: #'CalloutState *'> "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 oop | <var: #floatRet type: #double> <var: #intRet type: #usqLong> <inline: true> self cppIf: COGMTVM ifTrue: [(calloutState callFlags anyMask: FFICallFlagThreaded) ifTrue: [myThreadIndex := interpreterProxy disownVM: 0]].
self registerArgsSlop + self cStackAlignment > 0 ifTrue: [self setsp: calloutState argVector].
atomicType := self atomicTypeOf: calloutState ffiRetHeader. (atomicType >> 1) = (FFITypeSingleFloat > 1) ifTrue: [floatRet := self dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'double (*)()')] ifFalse: [intRet := self dispatchFunctionPointer: (self cCoerceSimple: procAddr to: 'usqLong (*)()')]. "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) - ^(calloutState ffiRetHeader anyMask: FFIFlagPointer) ifTrue: + [oop := self ffiReturnPointer: intRet ofType: (self ffiReturnType: specOnStack) in: calloutState] - [self ffiReturnPointer: intRet ofType: (self ffiReturnType: specOnStack) in: calloutState] ifFalse: + [oop := self ffiReturnStruct: intRet ofType: (self ffiReturnType: specOnStack) in: calloutState]. + ^oop]. - [self ffiReturnStruct: intRet ofType: (self ffiReturnType: specOnStack) in: calloutState]]. (atomicType >> 1) = (FFITypeSingleFloat > 1) ifTrue: [oop := interpreterProxy floatObjectOf: floatRet] ifFalse: [oop := self ffiCreateIntegralResultOop: intRet ofAtomicType: atomicType in: calloutState]. ^interpreterProxy methodReturnValue: oop!
vm-dev@lists.squeakfoundation.org