Hi.
I investigate that #becomeForward: is not working for SmallInteger args. It is mentioned in method comment:
Fails if either argument is a SmallInteger.
I guess that it is not working for any immediate argument. For example it is failed for Character too.
So I am interesting why it is not supported?
On Thu, 17 Mar 2016, Denis Kudriashov wrote:
Because they are immediate objects, so they don't exist on their own, only in a slot of another object. Using #becomeForward: would be an overkill anyway, because you can use assignment or #at:put: to achieve the same thing.
Levente
On Thu, Mar 17, 2016 at 09:57:51AM +0100, Denis Kudriashov wrote:
Hi.
I investigate that #becomeForward: is not working for SmallInteger args. It is mentioned in method comment:
Fails if either argument is a SmallInteger.
I guess that it is not working for any immediate argument. For example it is failed for Character too.
So I am interesting why it is not supported?
The become mechanism is swapping references to objects, such that the object pointers that pointed to one object are all now pointing to another. An immediate object such as SmallInteger is hiding its value within the object pointer itself (so it not really a pointer when used in this way). The immediate object "pointer" is therefore not able to participate in reference swapping.
Dave
So to implement becomeForward: with integer argument it is needed to scan all references to receiver and change pointers body to hold integer value. Am I right?
2016-03-17 13:52 GMT+01:00 David T. Lewis lewis@mail.msen.com:
On Thu, Mar 17, 2016 at 09:57:51AM +0100, Denis Kudriashov wrote:
Hi.
I investigate that #becomeForward: is not working for SmallInteger args.
It
is mentioned in method comment:
Fails if either argument is a SmallInteger.
I guess that it is not working for any immediate argument. For example it is failed for Character too.
So I am interesting why it is not supported?
The become mechanism is swapping references to objects, such that the object pointers that pointed to one object are all now pointing to another. An immediate object such as SmallInteger is hiding its value within the object pointer itself (so it not really a pointer when used in this way). The immediate object "pointer" is therefore not able to participate in reference swapping.
Dave
Hi Denis,
On Mar 17, 2016, at 6:35 AM, Denis Kudriashov dionisiydk@gmail.com wrote:
So to implement becomeForward: with integer argument it is needed to scan all references to receiver and change pointers body to hold integer value. Am I right?
If you were to implement it at the image level, yes. But you don't want to do that right? Let's imagine you were asking the question about the VM. Then the answer is:
Half right :-). That's what happened before Spur. Now what happens is that the object gets modified into a forwarding pointer to the object it becomes. In a two-way become we create two copies of the objects and make the originals point to the other copy, unless they are the same size, in which case we exchange their contents. (remember that bug with zero-sized objects which was due to a C compiler aliasing bug?)
In any case, the becomeForward:copyHash: false case should not fail for immediate targets. I'll make it so soon. But you're welcome to try yourself ;-)
_,,,^..^,,,_ (phone)
2016-03-17 13:52 GMT+01:00 David T. Lewis lewis@mail.msen.com:
On Thu, Mar 17, 2016 at 09:57:51AM +0100, Denis Kudriashov wrote:
Hi.
I investigate that #becomeForward: is not working for SmallInteger args. It is mentioned in method comment:
Fails if either argument is a SmallInteger.
I guess that it is not working for any immediate argument. For example it is failed for Character too.
So I am interesting why it is not supported?
The become mechanism is swapping references to objects, such that the object pointers that pointed to one object are all now pointing to another. An immediate object such as SmallInteger is hiding its value within the object pointer itself (so it not really a pointer when used in this way). The immediate object "pointer" is therefore not able to participate in reference swapping.
Dave
On 17.03.2016, at 13:52, David T. Lewis lewis@mail.msen.com wrote:
On Thu, Mar 17, 2016 at 09:57:51AM +0100, Denis Kudriashov wrote:
Hi.
I investigate that #becomeForward: is not working for SmallInteger args. It is mentioned in method comment:
Fails if either argument is a SmallInteger.
I guess that it is not working for any immediate argument. For example it is failed for Character too.
So I am interesting why it is not supported?
The become mechanism is swapping references to objects, such that the object pointers that pointed to one object are all now pointing to another. An immediate object such as SmallInteger is hiding its value within the object pointer itself (so it not really a pointer when used in this way). The immediate object "pointer" is therefore not able to participate in reference swapping.
Well, that’s no reason we couldn’t just replace all references to the object with the immediate value.
There’s only one technical reason I am aware of, and that is that becomeForward actually does change the argument’s identityHash:
old := ‘old'. new := ’new'. idold := old identityHash. idnew := new identityHash. old becomeForward: new. {idold. idnew. new identityHash}
==> #(153 3753 153)
In this case, b’s identity hash changed from 3753 to 153.
This mechanism exists so that if ‘old’ was used as key in an IdentityDictionary before, then now ‘new’ can be found at the same position because it uses the same hash. And since there is no way to change the identity hash of an immediate value, this can not work.
On 17.03.2016, at 14:35, Denis Kudriashov dionisiydk@gmail.com wrote:
So to implement becomeForward: with integer argument it is needed to scan all references to receiver and change pointers body to hold integer value. Am I right?
What *does* work, however (at least in Cog and SqueakJS, although not in the interpreter) is to use 'becomeForward: new copyHash: false’:
old := 'hi'. old becomeForward: 3 copyHash: false. old ==> 3
... because in the “copyHash: false” case the argument object is not modified in any way.
- Bert -
On Thu, Mar 17, 2016 at 11:42 AM, Bert Freudenberg bert@freudenbergs.de wrote:
On 17.03.2016, at 13:52, David T. Lewis lewis@mail.msen.com wrote:
On Thu, Mar 17, 2016 at 09:57:51AM +0100, Denis Kudriashov wrote:
Hi.
I investigate that #becomeForward: is not working for SmallInteger
args. It
is mentioned in method comment:
Fails if either argument is a SmallInteger.
I guess that it is not working for any immediate argument. For example
it
is failed for Character too.
So I am interesting why it is not supported?
The become mechanism is swapping references to objects, such that the object pointers that pointed to one object are all now pointing to
another.
An immediate object such as SmallInteger is hiding its value within the object pointer itself (so it not really a pointer when used in this way). The immediate object "pointer" is therefore not able to participate in reference swapping.
Well, that’s no reason we couldn’t just replace all references to the object with the immediate value.
There’s only one technical reason I am aware of, and that is that becomeForward actually does change the argument’s identityHash:
Couldn't that be solved using the #becomeForward:copyHash: flavor (passing `false` to copyHas:) ?
old := ‘old'. new := ’new'. idold := old identityHash. idnew := new identityHash. old becomeForward: new. {idold. idnew. new identityHash}
==> #(153 3753 153)
In this case, b’s identity hash changed from 3753 to 153.
This mechanism exists so that if ‘old’ was used as key in an IdentityDictionary before, then now ‘new’ can be found at the same position because it uses the same hash. And since there is no way to change the identity hash of an immediate value, this can not work.
On 17.03.2016, at 14:35, Denis Kudriashov dionisiydk@gmail.com wrote:
So to implement becomeForward: with integer argument it is needed to
scan all references to receiver and change pointers body to hold integer value.
Am I right?
What *does* work, however (at least in Cog and SqueakJS, although not in the interpreter) is to use 'becomeForward: new copyHash: false’:
old := 'hi'. old becomeForward: 3 copyHash: false. old ==> 3
... because in the “copyHash: false” case the argument object is not modified in any way.
- Bert -
On 17.03.2016, at 15:54, Mariano Martinez Peck marianopeck@gmail.com wrote:
On Thu, Mar 17, 2016 at 11:42 AM, Bert Freudenberg <bert@freudenbergs.de mailto:bert@freudenbergs.de> wrote:
There’s only one technical reason I am aware of, and that is that becomeForward actually does change the argument’s identityHash:
Couldn't that be solved using the #becomeForward:copyHash: flavor (passing `false` to copyHas:) ?
Yes, as I wrote further down below ;)
What *does* work, however (at least in Cog and SqueakJS, although not in the interpreter) is to use 'becomeForward: new copyHash: false’:
old := 'hi'. old becomeForward: 3 copyHash: false. old ==> 3
... because in the “copyHash: false” case the argument object is not modified in any way.
- Bert -
Sorry for my poor quoting.
- Bert -
Ups...sorry..I didn't see that last part of the email.
On Thu, Mar 17, 2016 at 11:56 AM, Bert Freudenberg bert@freudenbergs.de wrote:
On 17.03.2016, at 15:54, Mariano Martinez Peck marianopeck@gmail.com wrote:
On Thu, Mar 17, 2016 at 11:42 AM, Bert Freudenberg bert@freudenbergs.de wrote:
There’s only one technical reason I am aware of, and that is that becomeForward actually does change the argument’s identityHash:
Couldn't that be solved using the #becomeForward:copyHash: flavor (passing `false` to copyHas:) ?
Yes, as I wrote further down below ;)
What *does* work, however (at least in Cog and SqueakJS, although not in
the interpreter) is to use 'becomeForward: new copyHash: false’:
old := 'hi'. old becomeForward: 3 copyHash: false. old ==> 3
... because in the “copyHash: false” case the argument object is not modified in any way.
- Bert -
Sorry for my poor quoting.
- Bert -
On Mar 17, 2016, at 7:42 AM, Bert Freudenberg bert@freudenbergs.de wrote:
On 17.03.2016, at 13:52, David T. Lewis lewis@mail.msen.com wrote:
On Thu, Mar 17, 2016 at 09:57:51AM +0100, Denis Kudriashov wrote:
Hi.
I investigate that #becomeForward: is not working for SmallInteger args. It is mentioned in method comment:
Fails if either argument is a SmallInteger.
I guess that it is not working for any immediate argument. For example it is failed for Character too.
So I am interesting why it is not supported?
The become mechanism is swapping references to objects, such that the object pointers that pointed to one object are all now pointing to another. An immediate object such as SmallInteger is hiding its value within the object pointer itself (so it not really a pointer when used in this way). The immediate object "pointer" is therefore not able to participate in reference swapping.
Well, that’s no reason we couldn’t just replace all references to the object with the immediate value.
There’s only one technical reason I am aware of, and that is that becomeForward actually does change the argument’s identityHash:
old := ‘old'. new := ’new'. idold := old identityHash. idnew := new identityHash. old becomeForward: new. {idold. idnew. new identityHash}
==> #(153 3753 153)
In this case, b’s identity hash changed from 3753 to 153.
This mechanism exists so that if ‘old’ was used as key in an IdentityDictionary before, then now ‘new’ can be found at the same position because it uses the same hash. And since there is no way to change the identity hash of an immediate value, this can not work.
On 17.03.2016, at 14:35, Denis Kudriashov dionisiydk@gmail.com wrote:
So to implement becomeForward: with integer argument it is needed to scan all references to receiver and change pointers body to hold integer value. Am I right?
What *does* work, however (at least in Cog and SqueakJS, although not in the interpreter) is to use 'becomeForward: new copyHash: false’:
old := 'hi'. old becomeForward: 3 copyHash: false. old ==> 3
... because in the “copyHash: false” case the argument object is not modified in any way.
+1. I'll make Spur support this too.
- Bert -
Thank you for responses.
old becomeForward: 3 copyHash: false.
This is exactly what I need.
About case when old object is dictionary item. Changing it hash (during become for example) should not break dictionary. It will only slowdown object lookup. Am I right?
On 21.03.2016, at 10:28, Denis Kudriashov dionisiydk@gmail.com wrote:
Thank you for responses.
old becomeForward: 3 copyHash: false.
This is exactly what I need.
About case when old object is dictionary item. Changing it hash (during become for example) should not break dictionary. It will only slowdown object lookup. Am I right?
No, it will break. If the hash changes, the lookup very likely fails because it is looking at the wrong index (even though the object is in the dictionary).
You need to send #rehash to the dictionary to fix this.
Of course this only applies if the object was used as key. Curious: what are you actually trying to do?
- Bert -
2016-03-21 16:14 GMT+01:00 Bert Freudenberg bert@freudenbergs.de:
No, it will break. If the hash changes, the lookup very likely fails because it is looking at the wrong index (even though the object is in the dictionary).
You need to send #rehash to the dictionary to fix this.
Of course this only applies if the object was used as key. Curious: what are you actually trying to do?
I implemented new version of Mocketry which will return new mocks for any unexpected message. And in the case when this resulted mock will be used in arithmetics I will substitute it with zero as default number value. Same logic I apply for boolean operations where returned mock is substituted by false when mustBeBoolean is detected.
It should be correct behaviour for usual mock scenarios
Hi Denis,
On Mar 17, 2016, at 1:57 AM, Denis Kudriashov dionisiydk@gmail.com wrote:
Hi.
I investigate that #becomeForward: is not working for SmallInteger args. It is mentioned in method comment:
Fails if either argument is a SmallInteger.
I guess that it is not working for any immediate argument. For example it is failed for Character too.
So I am interesting why it is not supported?
It's a lazy coding bug. Both arrays get checked for validity. The thing that gets becommed can never be an immediate (you can't do 3 becomeForward: nil etc), even though the other way round makes sense. So the same routine us used to check both arrays and that fails the primitive. I'll fix it soon.
_,,,^..^,,,_ (phone)
vm-dev@lists.squeakfoundation.org