I found that #testBecomeIdentityHash sometimes failing, sometimes not.
It seems like VM 'forgets' to produce different identityHash bits for two consequently allocated objects, while test assumes that they are always different.
If i insert a statement (see the code), test no longer fails.
testBecomeIdentityHash "Note. The identity hash of both objects seems to change after the become:"
| a b c d |
a := 'ab' copy. b := 'cd' copy.
[ b identityHash = a identityHash ] whileTrue: [ b := b copy ].
c := a. d := b.
a become: b.
self assert: a identityHash = c identityHash; assert: b identityHash = d identityHash; deny: a identityHash = b identityHash.
A simple piece of code reveals the problem:
(1 to: 20) collect: [:i | 'ab' copy basicIdentityHash ] #(954 954 955 955 956 956 957 957 958 958 959 959 960 960 961 961 962 962 963 963)
Hi Igor. Does the same test work correctlly in a interpreter VM? because I can see:
ObjectMemory >> newObjectHash "Answer a new 16-bit pseudo-random number for use as an identity hash."
lastHash := 13849 + (27181 * lastHash) bitAnd: 65535. ^ lastHash
In which case, it seems that every new hash will be different than the previous one.
But NewObjectMemory >> newObjectHash "Derive the new object hash from the allocation pointer. This is less costly than using lastHash because it avoids the read-modify-write cycle to update lastHash. Since the size of eden is a power of two and larger than the hash range this provides a well-distributed and fairly random set of values." <inline: true> ^freeStart >> BytesPerWord
so...I have no idea, but maybe for two consequently allocated objects, the instVar freeStart can remain with the same value ?
On Mon, Aug 1, 2011 at 8:43 AM, Igor Stasenko siguctua@gmail.com wrote:
I found that #testBecomeIdentityHash sometimes failing, sometimes not.
It seems like VM 'forgets' to produce different identityHash bits for two consequently allocated objects, while test assumes that they are always different.
If i insert a statement (see the code), test no longer fails.
testBecomeIdentityHash "Note. The identity hash of both objects seems to change after the become:"
| a b c d | a := 'ab' copy. b := 'cd' copy.
[ b identityHash = a identityHash ] whileTrue: [ b := b copy ].
c := a. d := b. a become: b. self assert: a identityHash = c identityHash; assert: b identityHash = d identityHash; deny: a identityHash = b identityHash.
A simple piece of code reveals the problem:
(1 to: 20) collect: [:i | 'ab' copy basicIdentityHash ] #(954 954 955 955 956 956 957 957 958 958 959 959 960 960 961 961 962 962 963 963)
-- Best regards, Igor Stasenko AKA sig.
On 1 August 2011 09:47, Mariano Martinez Peck marianopeck@gmail.com wrote:
Hi Igor. Does the same test work correctlly in a interpreter VM? because I can see:
ObjectMemory >> newObjectHash "Answer a new 16-bit pseudo-random number for use as an identity hash."
lastHash := 13849 + (27181 * lastHash) bitAnd: 65535. ^ lastHash
In which case, it seems that every new hash will be different than the previous one.
But NewObjectMemory >> newObjectHash "Derive the new object hash from the allocation pointer. This is less costly than using lastHash because it avoids the read-modify-write cycle to update lastHash. Since the size of eden is a power of two and larger than the hash range this provides a well-distributed and fairly random set of values." <inline: true> ^freeStart >> BytesPerWord
aha.. so this is the reason why hash is not incrementing! Since BytesPerWord == 4 it means that hash will change only if old freeStart - new freeStart value >= 16
and since two short strings 'ab' fit in 16 bytes, they receive same hash value.
So, instead it should be:
^freeStart // BytesPerWord
since freeStart is aligned on BytesPerWord, but not (2^BytesPerWord)
so...I have no idea, but maybe for two consequently allocated objects, the instVar freeStart can remain with the same value ?
On Mon, Aug 1, 2011 at 8:43 AM, Igor Stasenko siguctua@gmail.com wrote:
I found that #testBecomeIdentityHash sometimes failing, sometimes not.
It seems like VM 'forgets' to produce different identityHash bits for two consequently allocated objects, while test assumes that they are always different.
If i insert a statement (see the code), test no longer fails.
testBecomeIdentityHash "Note. The identity hash of both objects seems to change after the become:"
| a b c d |
a := 'ab' copy. b := 'cd' copy.
[ b identityHash = a identityHash ] whileTrue: [ b := b copy ].
c := a. d := b.
a become: b.
self assert: a identityHash = c identityHash; assert: b identityHash = d identityHash; deny: a identityHash = b identityHash.
A simple piece of code reveals the problem:
(1 to: 20) collect: [:i | 'ab' copy basicIdentityHash ] #(954 954 955 955 956 956 957 957 958 958 959 959 960 960 961 961 962 962 963 963)
-- Best regards, Igor Stasenko AKA sig.
-- Mariano http://marianopeck.wordpress.com
On Mon, Aug 01, 2011 at 10:03:04AM +0200, Igor Stasenko wrote:
On 1 August 2011 09:47, Mariano Martinez Peck marianopeck@gmail.com wrote:
Hi Igor. Does the same test work correctlly in a interpreter VM??? because I can see:
ObjectMemory >> newObjectHash ?????? "Answer a new 16-bit pseudo-random number for use as an identity hash."
?????? lastHash := 13849 + (27181 * lastHash) bitAnd: 65535. ?????? ^ lastHash
In which case, it seems that every new hash will be different than the previous one.
But NewObjectMemory >> newObjectHash ?????? "Derive the new object hash from the allocation pointer.?? This is less costly than ?????? ??using lastHash because it avoids the read-modify-write cycle to update lastHash. ?????? ??Since the size of eden is a power of two and larger than the hash range this provides ?????? ??a well-distributed and fairly random set of values." ?????? <inline: true> ?????? ^freeStart >> BytesPerWord
aha.. so this is the reason why hash is not incrementing! Since BytesPerWord == 4 it means that hash will change only if old freeStart - new freeStart value >= 16
and since two short strings 'ab' fit in 16 bytes, they receive same hash value.
So, instead it should be:
^freeStart // BytesPerWord
since freeStart is aligned on BytesPerWord, but not (2^BytesPerWord)
Nice catch Igor!
I think the intented implementation was probably this:
^freeStart >> ShiftForWord
Nasty sort of bug, it's the sort of typo that looks fine until you stop to think about it ;)
Dave
Well distributed ? In examples like Igor's one you'll likely get consecutive hashes...
Nicolas
2011/8/1 David T. Lewis lewis@mail.msen.com:
On Mon, Aug 01, 2011 at 10:03:04AM +0200, Igor Stasenko wrote:
On 1 August 2011 09:47, Mariano Martinez Peck marianopeck@gmail.com wrote:
Hi Igor. Does the same test work correctlly in a interpreter VM??? because I can see:
ObjectMemory >> newObjectHash ?????? "Answer a new 16-bit pseudo-random number for use as an identity hash."
?????? lastHash := 13849 + (27181 * lastHash) bitAnd: 65535. ?????? ^ lastHash
In which case, it seems that every new hash will be different than the previous one.
But NewObjectMemory >> newObjectHash ?????? "Derive the new object hash from the allocation pointer.?? This is less costly than ?????? ??using lastHash because it avoids the read-modify-write cycle to update lastHash. ?????? ??Since the size of eden is a power of two and larger than the hash range this provides ?????? ??a well-distributed and fairly random set of values." ?????? <inline: true> ?????? ^freeStart >> BytesPerWord
aha.. so this is the reason why hash is not incrementing! Since BytesPerWord == 4 it means that hash will change only if old freeStart - new freeStart value >= 16
and since two short strings 'ab' fit in 16 bytes, they receive same hash value.
So, instead it should be:
^freeStart // BytesPerWord
since freeStart is aligned on BytesPerWord, but not (2^BytesPerWord)
Nice catch Igor!
I think the intented implementation was probably this:
^freeStart >> ShiftForWord
Nasty sort of bug, it's the sort of typo that looks fine until you stop to think about it ;)
Dave
On Mon, Aug 01, 2011 at 01:55:16PM +0200, Nicolas Cellier wrote:
Well distributed ? In examples like Igor's one you'll likely get consecutive hashes...
Nicolas
I don't know, but I would say that if you have a suitable hash test, please try comparing the results of that test on Cog versus a interpreter VM (and check it again after Igor's patch becomes available) to see if it makes a significant difference.
Dave
2011/8/1 David T. Lewis lewis@mail.msen.com:
On Mon, Aug 01, 2011 at 10:03:04AM +0200, Igor Stasenko wrote:
On 1 August 2011 09:47, Mariano Martinez Peck marianopeck@gmail.com wrote:
Hi Igor. Does the same test work correctlly in a interpreter VM??? because I can see:
ObjectMemory >> newObjectHash ?????? "Answer a new 16-bit pseudo-random number for use as an identity hash."
?????? lastHash := 13849 + (27181 * lastHash) bitAnd: 65535. ?????? ^ lastHash
In which case, it seems that every new hash will be different than the previous one.
But NewObjectMemory >> newObjectHash ?????? "Derive the new object hash from the allocation pointer.?? This is less costly than ?????? ??using lastHash because it avoids the read-modify-write cycle to update lastHash. ?????? ??Since the size of eden is a power of two and larger than the hash range this provides ?????? ??a well-distributed and fairly random set of values." ?????? <inline: true> ?????? ^freeStart >> BytesPerWord
aha.. so this is the reason why hash is not incrementing! Since BytesPerWord == 4 it means that hash will change only if old freeStart - new freeStart value >= 16
and since two short strings 'ab' fit in 16 bytes, they receive same hash value.
So, instead it should be:
? ? ^freeStart // BytesPerWord
since freeStart is aligned on BytesPerWord, but not (2^BytesPerWord)
Nice catch Igor!
I think the intented implementation was probably this:
? ? ? ?^freeStart >> ShiftForWord
Nasty sort of bug, it's the sort of typo that looks fine until you stop to think about it ;)
Dave
vm-dev@lists.squeakfoundation.org