<div dir="ltr">Thanks Nicolas! And great that you found slips. The more eyes the merrier.</div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Mar 4, 2016 at 5:24 PM, <span dir="ltr"><<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
Nicolas Cellier uploaded a new version of VMMaker to project VM Maker:<br>
<a href="http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1711.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1711.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: VMMaker.oscog-nice.1711<br>
Author: nice<br>
Time: 5 March 2016, 2:14:57.11 am<br>
UUID: 9e7ba417-b6ed-4263-82f2-27ec641d8f30<br>
Ancestors: VMMaker.oscog-eem.1709<br>
<br>
3 minor fixes for type inference:<br>
1) remove unecessary block argument assignment<br>
2) infer type of allMask:<br>
3) infer type of rem: instead of mod: (mod: does not exist)<br>
<br>
Don't use cCode: pointer aliasing for storing/fetching float/double in FFI primitives.<br>
Replace with a call to mem:cp:y:<br>
- the first one is dangerous with modern C compilers<br>
- while the second is optimized away (no call to memcpy)<br>
<br>
=============== Diff against VMMaker.oscog-eem.1709 ===============<br>
<br>
Item was changed:<br>
----- Method: FFIPlugin>>primitiveFFIDoubleAt (in category 'primitives') -----<br>
primitiveFFIDoubleAt<br>
"Return a (signed or unsigned) n byte integer from the given byte offset."<br>
| byteOffset rcvr addr floatValue |<br>
<export: true><br>
<inline: false><br>
+ <var: #floatValue type: #double><br>
- <var: #floatValue type:'double '><br>
byteOffset := interpreterProxy stackIntegerValue: 0.<br>
rcvr := interpreterProxy stackObjectValue: 1.<br>
interpreterProxy failed ifTrue:[^0].<br>
addr := self ffiAddressOf: rcvr startingAt: byteOffset size: 8.<br>
interpreterProxy failed ifTrue:[^0].<br>
+ self mem: (self addressOf: floatValue) cp: addr y: (self sizeof: floatValue).<br>
- self cCode:'((int*)(&floatValue))[0] = ((int*)addr)[0]'.<br>
- self cCode:'((int*)(&floatValue))[1] = ((int*)addr)[1]'.<br>
interpreterProxy pop: 2.<br>
^interpreterProxy pushFloat: floatValue<br>
!<br>
<br>
Item was changed:<br>
----- Method: FFIPlugin>>primitiveFFIDoubleAtPut (in category 'primitives') -----<br>
primitiveFFIDoubleAtPut<br>
"Return a (signed or unsigned) n byte integer from the given byte offset."<br>
| byteOffset rcvr addr floatValue floatOop |<br>
<export: true><br>
<inline: false><br>
+ <var: #floatValue type: #double><br>
- <var: #floatValue type:'double '><br>
floatOop := interpreterProxy stackValue: 0.<br>
(interpreterProxy isIntegerObject: floatOop)<br>
ifTrue:[floatValue := self cCoerce: (interpreterProxy integerValueOf: floatOop) to:'double']<br>
ifFalse:[floatValue := self cCoerce: (interpreterProxy floatValueOf: floatOop) to:'double'].<br>
byteOffset := interpreterProxy stackIntegerValue: 1.<br>
rcvr := interpreterProxy stackObjectValue: 2.<br>
interpreterProxy failed ifTrue:[^0].<br>
addr := self ffiAddressOf: rcvr startingAt: byteOffset size: 8.<br>
interpreterProxy failed ifTrue:[^0].<br>
+ self mem: addr cp: (self addressOf: floatValue) y: (self sizeof: floatValue).<br>
- self cCode:'((int*)addr)[0] = ((int*)(&floatValue))[0]'.<br>
- self cCode:'((int*)addr)[1] = ((int*)(&floatValue))[1]'.<br>
interpreterProxy pop: 3.<br>
^interpreterProxy push: floatOop!<br>
<br>
Item was changed:<br>
----- Method: FFIPlugin>>primitiveFFIFloatAt (in category 'primitives') -----<br>
primitiveFFIFloatAt<br>
"Return a (signed or unsigned) n byte integer from the given byte offset."<br>
| byteOffset rcvr addr floatValue |<br>
<export: true><br>
<inline: false><br>
+ <var: #floatValue type: #float><br>
- <var: #floatValue type:'float '><br>
byteOffset := interpreterProxy stackIntegerValue: 0.<br>
rcvr := interpreterProxy stackObjectValue: 1.<br>
interpreterProxy failed ifTrue:[^0].<br>
addr := self ffiAddressOf: rcvr startingAt: byteOffset size: 4.<br>
interpreterProxy failed ifTrue:[^0].<br>
+ self mem: (self addressOf: floatValue) cp: addr y: (self sizeof: floatValue).<br>
- self cCode:'((int*)(&floatValue))[0] = ((int*)addr)[0]'.<br>
interpreterProxy pop: 2.<br>
^interpreterProxy pushFloat: floatValue!<br>
<br>
Item was changed:<br>
----- Method: FFIPlugin>>primitiveFFIFloatAtPut (in category 'primitives') -----<br>
primitiveFFIFloatAtPut<br>
"Return a (signed or unsigned) n byte integer from the given byte offset."<br>
| byteOffset rcvr addr floatValue floatOop |<br>
<export: true><br>
<inline: false><br>
+ <var: #floatValue type: #float><br>
- <var: #floatValue type:'float '><br>
floatOop := interpreterProxy stackValue: 0.<br>
(interpreterProxy isIntegerObject: floatOop)<br>
ifTrue:[floatValue := self cCoerce: (interpreterProxy integerValueOf: floatOop) to:'float']<br>
ifFalse:[floatValue := self cCoerce: (interpreterProxy floatValueOf: floatOop) to:'float'].<br>
byteOffset := interpreterProxy stackIntegerValue: 1.<br>
rcvr := interpreterProxy stackObjectValue: 2.<br>
interpreterProxy failed ifTrue:[^0].<br>
addr := self ffiAddressOf: rcvr startingAt: byteOffset size: 4.<br>
interpreterProxy failed ifTrue:[^0].<br>
+ self mem: addr cp: (self addressOf: floatValue) y: (self sizeof: floatValue).<br>
- self cCode:'((int*)addr)[0] = ((int*)(&floatValue))[0]'.<br>
interpreterProxy pop: 3.<br>
^interpreterProxy push: floatOop!<br>
<br>
Item was changed:<br>
----- Method: IA32ABIPlugin>>primDoubleAt (in category 'primitives-accessing') -----<br>
primDoubleAt<br>
"Answer the 64-bit double starting at the given byte offset (little endian)."<br>
"<Alien> doubleAt: index <Integer> ^<Float><br>
<primitive: 'primDoubleAt' error: errorCode module: 'IA32ABI'>"<br>
| byteOffset rcvr startAddr addr floatValue |<br>
<export: true><br>
+ <var: #floatValue type: #double><br>
- <var: #floatValue type:'double '><br>
<br>
byteOffset := (interpreterProxy stackPositiveMachineIntegerValue: 0) - 1.<br>
rcvr := interpreterProxy stackObjectValue: 1.<br>
interpreterProxy failed ifTrue:<br>
[^interpreterProxy primitiveFailFor: PrimErrBadArgument].<br>
(self index: byteOffset length: 8 inRange: rcvr) ifFalse:<br>
[^interpreterProxy primitiveFailFor: PrimErrBadIndex].<br>
(startAddr := self startOfData: rcvr) = 0 ifTrue:<br>
[^interpreterProxy primitiveFailFor: PrimErrBadReceiver].<br>
addr := startAddr + byteOffset.<br>
+ self mem: (self addressOf: floatValue) cp: addr y: (self sizeof: floatValue).<br>
- self cCode:'((long *)(&floatValue))[0] = ((long *)addr)[0]; ((long *)(&floatValue))[1] = ((long *)addr)[1]'<br>
- inSmalltalk: [floatValue := rcvr doubleAt: byteOffset].<br>
interpreterProxy pop: 2.<br>
^interpreterProxy pushFloat: floatValue!<br>
<br>
Item was changed:<br>
----- Method: IA32ABIPlugin>>primDoubleAtPut (in category 'primitives-accessing') -----<br>
primDoubleAtPut<br>
"Store a double into 64 bits starting at the given byte offset (little endian)."<br>
"<Alien> doubleAt: index <Integer> put: value <Float | Integer> ^<Float | Integer><br>
<primitive: 'primDoubleAtPut' error: errorCode module: 'IA32ABI'>"<br>
| byteOffset rcvr startAddr addr valueOop floatValue |<br>
<export: true><br>
<var: #floatValue type: #double><br>
<br>
valueOop := interpreterProxy stackValue: 0.<br>
(interpreterProxy isIntegerObject: valueOop)<br>
ifTrue:[floatValue := self cCoerce: (interpreterProxy integerValueOf: valueOop) to: #double]<br>
ifFalse:[floatValue := self cCoerce: (interpreterProxy floatValueOf: valueOop) to: #double].<br>
byteOffset := (interpreterProxy stackPositiveMachineIntegerValue: 1) - 1.<br>
rcvr := interpreterProxy stackObjectValue: 2.<br>
interpreterProxy failed ifTrue:<br>
[^interpreterProxy primitiveFailFor: PrimErrBadArgument].<br>
(self index: byteOffset length: 8 inRange: rcvr) ifFalse:<br>
[^interpreterProxy primitiveFailFor: PrimErrBadIndex].<br>
(interpreterProxy isOopImmutable: rcvr) ifTrue:<br>
[^interpreterProxy primitiveFailFor: PrimErrNoModification].<br>
(startAddr := self startOfData: rcvr) = 0 ifTrue:<br>
[^interpreterProxy primitiveFailFor: PrimErrBadReceiver].<br>
addr := startAddr + byteOffset.<br>
+ self mem: addr cp: (self addressOf: floatValue) y: (self sizeof: floatValue).<br>
- self cCode:'((int*)addr)[0] = ((int*)(&floatValue))[0]'.<br>
- self cCode:'((int*)addr)[1] = ((int*)(&floatValue))[1]'.<br>
interpreterProxy methodReturnValue: valueOop!<br>
<br>
Item was changed:<br>
----- Method: IA32ABIPlugin>>primFloatAt (in category 'primitives-accessing') -----<br>
primFloatAt<br>
"Answer the 32-bit float starting at the given byte offset (little endian)."<br>
"<Alien> floatAt: index <Integer> ^<Float><br>
<primitive: 'primFloatAt' error: errorCode module: 'IA32ABI'>"<br>
| byteOffset rcvr startAddr addr floatValue |<br>
<export: true><br>
+ <var: #floatValue type: #float><br>
- <var: #floatValue type: 'float '><br>
<br>
byteOffset := (interpreterProxy stackPositiveMachineIntegerValue: 0) - 1.<br>
rcvr := interpreterProxy stackObjectValue: 1.<br>
interpreterProxy failed ifTrue:<br>
[^interpreterProxy primitiveFailFor: PrimErrBadArgument].<br>
(self index: byteOffset length: 4 inRange: rcvr) ifFalse:<br>
[^interpreterProxy primitiveFailFor: PrimErrBadIndex].<br>
(startAddr := self startOfData: rcvr) = 0 ifTrue:<br>
[^interpreterProxy primitiveFailFor: PrimErrBadReceiver].<br>
addr := startAddr + byteOffset.<br>
+ self mem: (self addressOf: floatValue) cp: addr y: (self sizeof: floatValue).<br>
- self cCode:'((long *)(&floatValue))[0] = ((long *)addr)[0]'<br>
- inSmalltalk: [floatValue := rcvr floatAt: byteOffset].<br>
interpreterProxy pop: 2.<br>
^interpreterProxy pushFloat: floatValue!<br>
<br>
Item was changed:<br>
----- Method: IA32ABIPlugin>>primFloatAtPut (in category 'primitives-accessing') -----<br>
primFloatAtPut<br>
"Store a float into 32 bits starting at the given byte offset (little endian)."<br>
"<Alien> floatAt: index <Integer> put: value <Float | Integer> ^<Float | Integer><br>
<primitive: 'primFloatAtPut' error: errorCode module: 'IA32ABI'>"<br>
| byteOffset rcvr startAddr addr valueOop floatValue |<br>
<export: true><br>
<var: #floatValue type: #float><br>
<br>
valueOop := interpreterProxy stackValue: 0.<br>
(interpreterProxy isIntegerObject: valueOop)<br>
ifTrue:[floatValue := self cCoerce: (interpreterProxy integerValueOf: valueOop) to: #double]<br>
ifFalse:[floatValue := self cCoerce: (interpreterProxy floatValueOf: valueOop) to: #double].<br>
byteOffset := (interpreterProxy stackPositiveMachineIntegerValue: 1) - 1.<br>
rcvr := interpreterProxy stackObjectValue: 2.<br>
interpreterProxy failed ifTrue:<br>
[^interpreterProxy primitiveFailFor: PrimErrBadArgument].<br>
(self index: byteOffset length: 4 inRange: rcvr) ifFalse:<br>
[^interpreterProxy primitiveFailFor: PrimErrBadIndex].<br>
(interpreterProxy isOopImmutable: rcvr) ifTrue:<br>
[^interpreterProxy primitiveFailFor: PrimErrNoModification].<br>
(startAddr := self startOfData: rcvr) = 0 ifTrue:<br>
[^interpreterProxy primitiveFailFor: PrimErrBadReceiver].<br>
addr := startAddr + byteOffset.<br>
+ self mem: addr cp: (self addressOf: floatValue) y: (self sizeof: floatValue).<br>
- self cCode:'((long *)addr)[0] = ((long *)(&floatValue))[0]'.<br>
interpreterProxy methodReturnValue: valueOop!<br>
<br>
Item was changed:<br>
----- Method: TMethod>>addTypesFor:to:in: (in category 'type inference') -----<br>
addTypesFor: node to: typeSet in: aCodeGen<br>
"Add the value tupes for the node to typeSet.<br>
Answer if any type was derived from an as-yet-untyped method, which allows us to abort<br>
inferReturnTypeFromReturnsIn: if the return type depends on a yet-to-be-typed method."<br>
| expr |<br>
expr := node.<br>
[expr isAssignment or: [expr isStmtList]] whileTrue:<br>
[expr isAssignment ifTrue:<br>
[expr := expr variable].<br>
expr isStmtList ifTrue:<br>
[expr := expr statements last]].<br>
expr isSend ifTrue:<br>
[(#(ifTrue: ifFalse: ifTrue:ifFalse: ifFalse:ifTrue:) includes: expr selector) ifTrue:<br>
[^expr args<br>
inject: false<br>
into: [:asYetUntyped :block|<br>
+ asYetUntyped | (self addTypesFor: block to: typeSet in: aCodeGen)]].<br>
+ (#(= ~= == ~~ < > <= >= anyMask: allMask: noMask:) includes: expr selector) ifTrue:<br>
- asYetUntyped := asYetUntyped | (self addTypesFor: block to: typeSet in: aCodeGen)]].<br>
- (#(= ~= == ~~ < > <= >= anyMask: noMask:) includes: expr selector) ifTrue:<br>
[typeSet add: #sqInt. ^false].<br>
+ (#(+ - * / // \\ rem: quo: bitAnd: bitClear: bitOr: bitXor: bitShift:) includes: expr selector) ifTrue:<br>
- (#(+ - * / // \\ mod: quo: bitAnd: bitClear: bitOr: bitXor: bitShift:) includes: expr selector) ifTrue:<br>
[| types |<br>
types := Set new.<br>
self addTypesFor: expr receiver to: types in: aCodeGen.<br>
(types size = 1 and: [types anyOne last = $*]) ifTrue: "pointer arithmetic"<br>
[typeSet add: types anyOne. ^false].<br>
self addTypesFor: expr args first to: types in: aCodeGen.<br>
types := aCodeGen harmonizeReturnTypesIn: types.<br>
types size = 2 ifTrue:<br>
[(types includes: #double) ifTrue:<br>
[typeSet add: #double. ^false].<br>
(types includes: #float) ifTrue:<br>
[typeSet add: #float. ^false].<br>
^false]. "don't know; leave unspecified."<br>
types notEmpty ifTrue:<br>
[typeSet add: types anyOne].<br>
^false].<br>
"Abort only for untyped methods that will be typed, but don't be phased by recursion."<br>
^(aCodeGen returnTypeForSend: expr in: self)<br>
ifNotNil: [:type| typeSet add: type. false]<br>
ifNil: [(aCodeGen methodNamed: expr selector) notNil and: [expr selector ~~ selector]]].<br>
expr isVariable ifTrue:<br>
[(aCodeGen typeOfVariable: expr name)<br>
ifNotNil: [:type| typeSet add: type]<br>
ifNil: [typeSet add: (expr name = 'self'<br>
ifTrue: [#void]<br>
ifFalse: [#sqInt])]].<br>
expr isConstant ifTrue:<br>
[| val |<br>
val := expr value.<br>
val isInteger ifTrue:<br>
[typeSet add: ((val >= 0 ifTrue: [val] ifFalse: [-1 - val]) highBit <= 32<br>
ifTrue: [#sqInt]<br>
ifFalse: [#sqLong])].<br>
(#(nil true false) includes: val) ifTrue:<br>
[typeSet add: #sqInt].<br>
val isFloat ifTrue:<br>
[typeSet add: #float]].<br>
^false!<br>
<br>
Item was changed:<br>
----- Method: ThreadedFFIPlugin>>primitiveFFIDoubleAt (in category 'primitives') -----<br>
primitiveFFIDoubleAt<br>
"Return a (signed or unsigned) n byte integer from the given byte offset."<br>
| byteOffset rcvr addr floatValue |<br>
<export: true><br>
<inline: false><br>
+ <var: #floatValue type: #double><br>
- <var: #floatValue type:'double '><br>
byteOffset := interpreterProxy stackIntegerValue: 0.<br>
rcvr := interpreterProxy stackObjectValue: 1.<br>
interpreterProxy failed ifTrue:[^0].<br>
addr := self ffiAddressOf: rcvr startingAt: byteOffset size: 8.<br>
interpreterProxy failed ifTrue:[^0].<br>
+ self mem: (self addressOf: floatValue) cp: addr y: (self sizeof: floatValue).<br>
- self cCode:'((int*)(&floatValue))[0] = ((int*)addr)[0]'.<br>
- self cCode:'((int*)(&floatValue))[1] = ((int*)addr)[1]'.<br>
interpreterProxy pop: 2.<br>
^interpreterProxy pushFloat: floatValue<br>
!<br>
<br>
Item was changed:<br>
----- Method: ThreadedFFIPlugin>>primitiveFFIDoubleAtPut (in category 'primitives') -----<br>
primitiveFFIDoubleAtPut<br>
"Return a (signed or unsigned) n byte integer from the given byte offset."<br>
| byteOffset rcvr addr floatValue floatOop |<br>
<export: true><br>
<inline: false><br>
+ <var: #floatValue type: #double><br>
- <var: #floatValue type:'double '><br>
floatOop := interpreterProxy stackValue: 0.<br>
(interpreterProxy isIntegerObject: floatOop)<br>
ifTrue:[floatValue := self cCoerce: (interpreterProxy integerValueOf: floatOop) to:'double']<br>
ifFalse:[floatValue := self cCoerce: (interpreterProxy floatValueOf: floatOop) to:'double'].<br>
byteOffset := interpreterProxy stackIntegerValue: 1.<br>
rcvr := interpreterProxy stackObjectValue: 2.<br>
interpreterProxy failed ifTrue:[^0].<br>
addr := self ffiAddressOf: rcvr startingAt: byteOffset size: 8.<br>
interpreterProxy failed ifTrue:[^0].<br>
+ self mem: addr cp: (self addressOf: floatValue) y: (self sizeof: floatValue).<br>
- self cCode:'((int*)addr)[0] = ((int*)(&floatValue))[0]'.<br>
- self cCode:'((int*)addr)[1] = ((int*)(&floatValue))[1]'.<br>
^interpreterProxy pop: 3 thenPush: floatOop!<br>
<br>
Item was changed:<br>
----- Method: ThreadedFFIPlugin>>primitiveFFIFloatAt (in category 'primitives') -----<br>
primitiveFFIFloatAt<br>
"Return a (signed or unsigned) n byte integer from the given byte offset."<br>
| byteOffset rcvr addr floatValue |<br>
<export: true><br>
<inline: false><br>
+ <var: #floatValue type: #float><br>
- <var: #floatValue type:'float '><br>
byteOffset := interpreterProxy stackIntegerValue: 0.<br>
rcvr := interpreterProxy stackObjectValue: 1.<br>
interpreterProxy failed ifTrue:[^0].<br>
addr := self ffiAddressOf: rcvr startingAt: byteOffset size: 4.<br>
interpreterProxy failed ifTrue:[^0].<br>
+ self mem: (self addressOf: floatValue) cp: addr y: (self sizeof: floatValue).<br>
- self cCode:'((int*)(&floatValue))[0] = ((int*)addr)[0]'.<br>
interpreterProxy pop: 2.<br>
^interpreterProxy pushFloat: floatValue!<br>
<br>
Item was changed:<br>
----- Method: ThreadedFFIPlugin>>primitiveFFIFloatAtPut (in category 'primitives') -----<br>
primitiveFFIFloatAtPut<br>
"Return a (signed or unsigned) n byte integer from the given byte offset."<br>
| byteOffset rcvr addr floatValue floatOop |<br>
<export: true><br>
<inline: false><br>
+ <var: #floatValue type: #float><br>
- <var: #floatValue type:'float '><br>
floatOop := interpreterProxy stackValue: 0.<br>
(interpreterProxy isIntegerObject: floatOop)<br>
ifTrue:[floatValue := self cCoerce: (interpreterProxy integerValueOf: floatOop) to:'float']<br>
ifFalse:[floatValue := self cCoerce: (interpreterProxy floatValueOf: floatOop) to:'float'].<br>
byteOffset := interpreterProxy stackIntegerValue: 1.<br>
rcvr := interpreterProxy stackObjectValue: 2.<br>
interpreterProxy failed ifTrue:[^0].<br>
addr := self ffiAddressOf: rcvr startingAt: byteOffset size: 4.<br>
interpreterProxy failed ifTrue:[^0].<br>
+ self mem: addr cp: (self addressOf: floatValue) y: (self sizeof: floatValue).<br>
- self cCode:'((int*)addr)[0] = ((int*)(&floatValue))[0]'.<br>
^interpreterProxy pop: 3 thenPush: floatOop!<br>
<br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div>
</div>