Hi,
I feel like I did not explain my short term goals.
This lack of explanation may let my recent commit be viewed as gratuitous
breakage.
They are not. What I'm after is:
- reduce the number of C Undefined Behaviours that we depend upon
my own vm brand can be compiled without the -fwrapv workaround, it's
doable.
- eliminate ever more C compiler warnings
Eliot did really a great job these last two years
maybe we're not yet ready to compile with -Wall -Werror, but we are
approaching
- simplify the slang source when possible
- connect the 32 bits limbs trick for accelerating large integer arithmetic
About this last point, I'm now thinking about a different strategy for the
hypothetical BIG-ENDIAN machines: swap bytes while fetching/storing limbs
instead of using native order tricks.
It's more robust and not really expensive nowadays.
This way, the code that would fetch largeInteger bytes would still work
unchanged.
Also no need to hack ImageSegment and image version number.
I'm thinking of using the approach of this kind of references:
http://www.boost.org/doc/libs/1_60_0/boost/endian/detail/intrinsic.hpphttps://blogs.oracle.com/DanX/entry/optimizing_byte_swapping_for_funhttp://hardwarebug.org/2010/01/14/beware-the-builtinshttp://stackoverflow.com/questions/105252/how-do-i-convert-between-big-endi…
So, once again, apologies for the hiccups, there might be a few more, even
if I'll try my best to take it seriously and carefully, it's currently too
expensive to guaranty non regression. With a single dev branch, it's more
than expensive, it's impossible.
Until we come with a more modern architecture, please don't consider that
each and every monticello commit is OK to take as is.
Eliot has short release cycles, and he does generally commit on .SVN
repository when there is a MC version ready with enough added value and
enough stability. That's not at each and every MC version.
It's far from perfect, and maybe won't scale once a few more people add
noise.
But in the interim, my advice is to synch the production on .SVN release
and associated MC version, not on MC.
Running tests for the two are different jobs, that's a way to mitigate the
fact that we have a single branch.
cheers
Hi Nico,
somewhere between this and VMMaker.oscog-dtl.1730 all PharoVMs become unusable :(
are you aware of this?
maybe I’m forgetting something in my builds?
cheers,
Esteban
> On 17 Mar 2016, at 22:49, commits(a)source.squeak.org wrote:
>
>
> Nicolas Cellier uploaded a new version of VMMaker to project VM Maker:
> http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1733.mcz
>
> ==================== Summary ====================
>
> Name: VMMaker.oscog-nice.1733
> Author: nice
> Time: 17 March 2016, 11:45:52.436 pm
> UUID: cc4513ea-67e5-4b41-b7bd-2fc790ac0102
> Ancestors: VMMaker.oscog-nice.1732
>
> Oups (Oops) forgot the <doNotGenerate> for simulated #stSizeOf: version.
>
> =============== Diff against VMMaker.oscog-nice.1732 ===============
>
> Item was changed:
> ----- Method: SpurMemoryManager>>stSizeOf: (in category 'object access') -----
> stSizeOf: oop
> "Return the number of indexable fields in the receiver"
> + <doNotGenerate>
> ^oop basicSize!
>
Nicolas Cellier uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1736.mcz
==================== Summary ====================
Name: VMMaker.oscog-nice.1736
Author: nice
Time: 19 March 2016, 3:41:39.741 pm
UUID: 193c2046-4773-44ea-9455-a138be7b0992
Ancestors: VMMaker.oscog-nice.1735
Fix another bug of 1732.nice commit which broke primitiveBitAnd and primitiveBitOr
The symptom is this one at least in stack spur 64bits:
(-1 bitAnd: -1) -> -1 "correct"
(-1 perform: 1bitAnd: with: -1) -> 16r1FFFFFFF 'huh?"
it's -1 asUnsignedInteger >> 3...
The first one is working Ok because it's using bytecodePrimBitAnd which is very simple and correct.
here is the mistake I introduced a #usqInt type hint in slang.
At the time I did it, it was to reduce the number of signed mismatch warnings which are a plague. Yes but:
integerArgument := self positiveMachineIntegerValueOf: integerArgument.
Ouch, the return value is supposed to be unsigned.
While the parameter has to be signed in order to have the isIntegerObject: bit tricks working once inlined by slang...
So reusing the variable name for two different things was not a good idea finally (it rarely is).
This doesn't happen in my own branch because I've carefully rewritten the shift logic to use exclusively well defined unsigned behavior, but my changes are too aggressive, and I'd like to introduce them gradually to give a chance of reviewing them.
------------------
While at it, use cCorceSimple:to: 'unsigned int' when fetching integerValueOf rather than asUnsignedInteger.
The reason is that the first will never do sign extension, while the second would in 64bits.
OK, the 64bits spur cannot take this path, because a 32bit int would be a SmallInteger, but I prefer to throw good basis, this will avoid having to ask myelf about the same problem again in a couple of years...
I would much prefer to have a fetchUnsigned32/64, but we'll see that another time.
=============== Diff against VMMaker.oscog-nice.1735 ===============
Item was changed:
----- Method: InterpreterPrimitives>>positiveMachineIntegerValueOf: (in category 'primitive support') -----
positiveMachineIntegerValueOf: oop
"Answer a value of an integer in address range, i.e up to the size of a machine word.
The object may be either a positive SmallInteger or a LargePositiveInteger of size <= word size."
<returnTypeC: #'unsigned long'>
<inline: true> "only two callers & one is primitiveNewWithArg"
| value bs ok |
(objectMemory isIntegerObject: oop) ifTrue:
[value := objectMemory integerValueOf: oop.
value < 0 ifTrue: [^self primitiveFail].
^value].
(objectMemory isNonIntegerImmediate: oop) ifTrue:
[self primitiveFail.
^0].
ok := objectMemory
isClassOfNonImm: oop
equalTo: (objectMemory splObj: ClassLargePositiveInteger)
compactClassIndex: ClassLargePositiveIntegerCompactIndex.
ok ifFalse:
[self primitiveFail.
^0].
bs := objectMemory numBytesOfBytes: oop.
bs > (self sizeof: #'unsigned long') ifTrue:
[self primitiveFail.
^0].
((self sizeof: #'unsigned long') = 8
and: [bs > 4]) ifTrue:
[^self cppIf: VMBIGENDIAN
ifTrue:
[ (objectMemory fetchByte: 0 ofObject: oop)
+ ((objectMemory fetchByte: 1 ofObject: oop) << 8)
+ ((objectMemory fetchByte: 2 ofObject: oop) << 16)
+ ((objectMemory fetchByte: 3 ofObject: oop) << 24)
+ ((objectMemory fetchByte: 4 ofObject: oop) << 32)
+ ((objectMemory fetchByte: 5 ofObject: oop) << 40)
+ ((objectMemory fetchByte: 6 ofObject: oop) << 48)
+ ((objectMemory fetchByte: 7 ofObject: oop) << 56)]
ifFalse:
[objectMemory fetchLong64: 0 ofObject: oop]]
ifFalse:
[^self cppIf: VMBIGENDIAN
ifTrue:
[ (objectMemory fetchByte: 0 ofObject: oop)
+ ((objectMemory fetchByte: 1 ofObject: oop) << 8)
+ ((objectMemory fetchByte: 2 ofObject: oop) << 16)
+ ((objectMemory fetchByte: 3 ofObject: oop) << 24)]
ifFalse:
+ [self cCoerceSimple: (objectMemory fetchLong32: 0 ofObject: oop) to: #'unsigned int']]!
- [objectMemory fetchLong32: 0 ofObject: oop]]!
Item was changed:
----- Method: InterpreterPrimitives>>primitiveBitAnd (in category 'arithmetic integer primitives') -----
primitiveBitAnd
<inline: false>
+ <var: 'integerArgumentValue' type: #usqInt>
+ <var: 'intergerReceiverValue' type: #usqInt>
+ | integerReceiver integerArgument integerArgumentValue integerReceiverValue |
- <var: 'integerArgument' type: #usqInt>
- <var: 'intergerReceiver' type: #usqInt>
- | integerReceiver integerArgument |
integerArgument := self stackTop.
integerReceiver := self stackValue: 1.
"Comment out the short-cut. Either the inline interpreter bytecode or the JIT primitive will handle this case.
((objectMemory isIntegerObject: integerArgument)
and: [objectMemory isIntegerObject: integerReceiver])
ifTrue: [self pop: 2 thenPush: (integerArgument bitAnd: integerReceiver)]
ifFalse:
["
+ integerArgumentValue := self positiveMachineIntegerValueOf: integerArgument.
+ integerReceiverValue := self positiveMachineIntegerValueOf: integerReceiver.
- integerArgument := self positiveMachineIntegerValueOf: integerArgument.
- integerReceiver := self positiveMachineIntegerValueOf: integerReceiver.
self successful ifTrue:
+ [self pop: 2 thenPush: (self positiveMachineIntegerFor: (integerArgumentValue bitAnd: integerReceiverValue))]
- [self pop: 2 thenPush: (self positiveMachineIntegerFor: (integerArgument bitAnd: integerReceiver))]
ifFalse:
[]"]"!
Item was changed:
----- Method: InterpreterPrimitives>>primitiveBitOr (in category 'arithmetic integer primitives') -----
primitiveBitOr
<inline: false>
+ <var: 'integerArgumentValue' type: #usqInt>
+ <var: 'intergerReceiverValue' type: #usqInt>
+ | integerReceiver integerArgument integerArgumentValue integerReceiverValue |
- <var: 'integerArgument' type: #usqInt>
- <var: 'intergerReceiver' type: #usqInt>
- | integerReceiver integerArgument |
integerArgument := self stackTop.
integerReceiver := self stackValue: 1.
"Comment out the short-cut. Either the inline interpreter bytecode or the JIT primitive will handle this case.
((objectMemory isIntegerObject: integerArgument)
and: [objectMemory isIntegerObject: integerReceiver])
ifTrue: [self pop: 2 thenPush: (integerArgument bitOr: integerReceiver)]
ifFalse:
["
+ integerArgumentValue := self positiveMachineIntegerValueOf: integerArgument.
+ integerReceiverValue := self positiveMachineIntegerValueOf: integerReceiver.
- integerArgument := self positiveMachineIntegerValueOf: integerArgument.
- integerReceiver := self positiveMachineIntegerValueOf: integerReceiver.
self successful ifTrue:
+ [self pop: 2 thenPush: (self positiveMachineIntegerFor: (integerArgumentValue bitOr: integerReceiverValue))]
- [self pop: 2 thenPush: (self positiveMachineIntegerFor: (integerArgument bitOr: integerReceiver))]
ifFalse:
[]"]"!
Item was changed:
----- Method: InterpreterPrimitives>>primitiveBitXor (in category 'arithmetic integer primitives') -----
primitiveBitXor
<inline: false>
+ <var: 'integerArgumentValue' type: #usqInt>
+ <var: 'intergerReceiverValue' type: #usqInt>
+ | integerReceiver integerArgument integerArgumentValue integerReceiverValue |
- | integerReceiver integerArgument |
integerArgument := self stackTop.
integerReceiver := self stackValue: 1.
((objectMemory isIntegerObject: integerArgument)
and: [objectMemory isIntegerObject: integerReceiver])
ifTrue: "xoring will leave the tag bits zero, whether the tag is 1 or zero, so add it back in."
[self pop: 2 thenPush: (integerArgument bitXor: integerReceiver) + objectMemory smallIntegerTag]
ifFalse:
+ [integerArgumentValue := self positiveMachineIntegerValueOf: integerArgument.
+ integerReceiverValue := self positiveMachineIntegerValueOf: integerReceiver.
- [integerArgument := self positiveMachineIntegerValueOf: integerArgument.
- integerReceiver := self positiveMachineIntegerValueOf: integerReceiver.
self successful ifTrue:
+ [self pop: 2 thenPush: (self positiveMachineIntegerFor: (integerArgumentValue bitXor: integerReceiverValue))]]!
- [self pop: 2 thenPush: (self positiveMachineIntegerFor: (integerArgument bitXor: integerReceiver))]]!
Item was changed:
----- Method: InterpreterPrimitives>>signed64BitValueOf: (in category 'primitive support') -----
signed64BitValueOf: oop
"Convert the given object into an integer value.
The object may be either a positive SmallInteger or a eight-byte LargeInteger."
| sz value negative ok magnitude |
<inline: false>
<returnTypeC: #sqLong>
<var: #value type: #sqLong>
<var: #magnitude type: #usqLong>
(objectMemory isIntegerObject: oop) ifTrue:
[^self cCoerce: (objectMemory integerValueOf: oop) to: #sqLong].
(objectMemory isNonIntegerImmediate: oop) ifTrue:
[self primitiveFail.
^0].
ok := objectMemory isClassOfNonImm: oop
equalTo: (objectMemory splObj: ClassLargePositiveInteger)
compactClassIndex: ClassLargePositiveIntegerCompactIndex.
ok
ifTrue: [negative := false]
ifFalse:
[negative := true.
ok := objectMemory isClassOfNonImm: oop
equalTo: (objectMemory splObj: ClassLargeNegativeInteger)
compactClassIndex: ClassLargeNegativeIntegerCompactIndex.
ok ifFalse:
[self primitiveFail.
^0]].
sz := objectMemory numBytesOfBytes: oop.
sz > (self sizeof: #sqLong) ifTrue:
[self primitiveFail.
^0].
self cppIf: VMBIGENDIAN
ifTrue:
[magnitude := objectMemory fetchByte: sz - 1 ofObject: oop.
sz - 2 to: 0 by: -1 do: [:i |
magnitude := magnitude << 8 + (objectMemory fetchByte: i ofObject: oop)]]
ifFalse:
[magnitude := sz > 4
ifTrue: [objectMemory fetchLong64: 0 ofObject: oop]
+ ifFalse: [self cCoerceSimple: (objectMemory fetchLong32: 0 ofObject: oop) to: #'unsigned int']].
- ifFalse: [(objectMemory fetchLong32: 0 ofObject: oop) asUnsignedInteger]].
(negative
ifTrue: [magnitude > 16r8000000000000000]
ifFalse: [magnitude >= 16r8000000000000000])
ifTrue: [self primitiveFail.
^0].
negative
ifTrue: [value := 0 - magnitude]
ifFalse: [value := magnitude].
^value!
Nicolas Cellier uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1735.mcz
==================== Summary ====================
Name: VMMaker.oscog-nice.1735
Author: nice
Time: 18 March 2016, 11:56:29.175 pm
UUID: 498f1478-029f-42dc-8290-20203333af22
Ancestors: VMMaker.oscog-nice.1733
Workaround spurious breakage caused by nice.1732
Slang inliner does inline this call:
sqInt shifted = 0xFFFFFFFFU;
shifted = positive32BitIntegerFor(shifted);
into:
sqInt shifted = 0xFFFFFFFFU;
if( shifted <= MaxSmallInteger)
{
shifted = (shifted << 1) | 1;
...snip...
shifted interpreted as signed integer is negative.
MaxSmallInteger is a signed integer constant, so the if test is TRUE.
and a negative SmallInteger is created (with value -1) instead of a LargePositiveInteger as it should have been.
The intention is to interpret shifted as an unsigned integer, but since we did not help SLANG with a hint, slang did produce a signed (sqInt) by default.
=============== Diff against VMMaker.oscog-nice.1733 ===============
Item was changed:
----- Method: StackInterpreter>>maybeInlinePositive32BitIntegerFor: (in category 'primitive support') -----
maybeInlinePositive32BitIntegerFor: integerValue
"N.B. will *not* cause a GC.
integerValue is interpreted as POSITIVE, e.g. as the result of Bitmap>at:."
<notOption: #Spur64BitMemoryManager>
<var: 'integerValue' type: #'unsigned int'>
| newLargeInteger |
self deny: objectMemory hasSixtyFourBitImmediates.
+ "force coercion because slang inliner sometimes incorrectly pass a signed int without converting to unsigned"
+ (self cCoerceSimple: integerValue to: #'unsigned int') <= objectMemory maxSmallInteger
- integerValue <= objectMemory maxSmallInteger
ifTrue: [^ objectMemory integerObjectOf: integerValue].
newLargeInteger := objectMemory
eeInstantiateSmallClassIndex: ClassLargePositiveIntegerCompactIndex
format: (objectMemory byteFormatForNumBytes: 4)
numSlots: 1.
self cppIf: VMBIGENDIAN
ifTrue:
[objectMemory
storeByte: 3 ofObject: newLargeInteger withValue: (integerValue >> 24 bitAnd: 16rFF);
storeByte: 2 ofObject: newLargeInteger withValue: (integerValue >> 16 bitAnd: 16rFF);
storeByte: 1 ofObject: newLargeInteger withValue: (integerValue >> 8 bitAnd: 16rFF);
storeByte: 0 ofObject: newLargeInteger withValue: (integerValue ">> 0" bitAnd: 16rFF)]
ifFalse:
[objectMemory storeLong32: 0 ofObject: newLargeInteger withValue: integerValue].
^newLargeInteger!
Hi David,
On Wed, Mar 16, 2016 at 6:07 PM, <commits(a)source.squeak.org> wrote:
>
> David T. Lewis uploaded a new version of VMMaker to project VM Maker:
> http://source.squeak.org/VMMaker/VMMaker.oscog-dtl.1730.mcz
>
> ==================== Summary ====================
>
> Name: VMMaker.oscog-dtl.1730
> Author: dtl
> Time: 16 March 2016, 9:06:26.74934 pm
> UUID: ad4e53e1-bdbc-4cb9-b5fb-f1229ca4e19f
> Ancestors: VMMaker.oscog-nice.1729
>
> Allow primitiveUtcWithOffset to accept an optional parameter with an array
> or object with two or more slots to store UTC posix microseconds and time
> zone offset in seconds. Compatibility with VMM trunk. Note, consider
> incorporating ioUtcWithOffset from SVN trunk to provide true atomic
> primitive.
>
Feel free to move the code over.
>
> =============== Diff against VMMaker.oscog-nice.1729 ===============
>
> Item was changed:
> ----- Method: InterpreterPrimitives>>primitiveUtcWithOffset (in category
> 'system control primitives') -----
> primitiveUtcWithOffset
> + "Answer an array with UTC microseconds since the Posix epoch and
> the
> + current seconds offset from GMT in the local time zone. An empty
> two
> + element array (or any object with two or more slots) may be
> supplied
> + as a parameter.
> - "Answer an array with UTC microseconds since the Posix epoch and
> - the current seconds offset from GMT in the local time zone.
> This is a named (not numbered) primitive in the null module (ie
> the VM)"
> | epochDelta offset resultArray utcMicroseconds |
>
> <export: true>
> <var: #epochDelta declareC: 'static usqLong epochDelta=
> 2177452800000000ULL'>
> <var: #utcMicroseconds type: #usqLong>
> <var: #offset type: #sqLong>
> + argumentCount > 1 ifTrue: [^self primitiveFailFor:
> PrimErrBadNumArgs].
> self cCode: '' inSmalltalk: [epochDelta := 2177452800000000].
> utcMicroseconds := self ioUTCMicroseconds.
> offset := self ioLocalMicroseconds - utcMicroseconds.
> offset := offset / 1000000.
> objectMemory pushRemappableOop: (self positive64BitIntegerFor:
> utcMicroseconds - epochDelta).
> + argumentCount > 0
> + ifTrue: [resultArray := self popStack.
> + ((objectMemory isPointers: resultArray)
> + and: [(objectMemory lengthOf: resultArray)
> >= 2])
> + ifFalse: [^self primitiveFailFor:
> PrimErrBadArgument]]
> + ifFalse: [resultArray := objectMemory instantiateClass:
> objectMemory classArray indexableSize: 2].
> - resultArray := objectMemory instantiateClass: objectMemory
> classArray indexableSize: 2.
> objectMemory storePointer: 0 ofObject: resultArray withValue:
> objectMemory popRemappableOop.
> objectMemory storePointerUnchecked: 1 ofObject: resultArray
> withValue: (objectMemory integerObjectOf: offset).
> self pop: 1 thenPush: resultArray
> !
>
>
--
_,,,^..^,,,_
best, Eliot
Nicolas Cellier uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1733.mcz
==================== Summary ====================
Name: VMMaker.oscog-nice.1733
Author: nice
Time: 17 March 2016, 11:45:52.436 pm
UUID: cc4513ea-67e5-4b41-b7bd-2fc790ac0102
Ancestors: VMMaker.oscog-nice.1732
Oups (Oops) forgot the <doNotGenerate> for simulated #stSizeOf: version.
=============== Diff against VMMaker.oscog-nice.1732 ===============
Item was changed:
----- Method: SpurMemoryManager>>stSizeOf: (in category 'object access') -----
stSizeOf: oop
"Return the number of indexable fields in the receiver"
+ <doNotGenerate>
^oop basicSize!