Why "object becomeForward: 3" is not working?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

Why "object becomeForward: 3" is not working?

Denis Kudriashov
 
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?
Reply | Threaded
Open this post in threaded view
|

Re: Why "object becomeForward: 3" is not working?

Levente Uzonyi
 
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

Reply | Threaded
Open this post in threaded view
|

Re: Why "object becomeForward: 3" is not working?

David T. Lewis
In reply to this post by Denis Kudriashov
 
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

Reply | Threaded
Open this post in threaded view
|

Re: Why "object becomeForward: 3" is not working?

Denis Kudriashov
 
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 <[hidden email]>:

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


Reply | Threaded
Open this post in threaded view
|

Re: Why "object becomeForward: 3" is not working?

Bert Freudenberg
In reply to this post by David T. Lewis
 

> On 17.03.2016, at 13:52, David T. Lewis <[hidden email]> 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 <[hidden email]> 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 -


smime.p7s (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Why "object becomeForward: 3" is not working?

Mariano Martinez Peck
 


On Thu, Mar 17, 2016 at 11:42 AM, Bert Freudenberg <[hidden email]> wrote:
 

> On 17.03.2016, at 13:52, David T. Lewis <[hidden email]> 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 <[hidden email]> 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 -





--
Reply | Threaded
Open this post in threaded view
|

Re: Why "object becomeForward: 3" is not working?

Bert Freudenberg
 
On 17.03.2016, at 15:54, Mariano Martinez Peck <[hidden email]> wrote:

On Thu, Mar 17, 2016 at 11:42 AM, Bert Freudenberg <[hidden email]> 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 -


smime.p7s (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Why "object becomeForward: 3" is not working?

Mariano Martinez Peck
 
Ups...sorry..I didn't see that last part of the email.

On Thu, Mar 17, 2016 at 11:56 AM, Bert Freudenberg <[hidden email]> wrote:
 
On 17.03.2016, at 15:54, Mariano Martinez Peck <[hidden email]> wrote:

On Thu, Mar 17, 2016 at 11:42 AM, Bert Freudenberg <[hidden email]> 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 -





--
Reply | Threaded
Open this post in threaded view
|

Re: Why "object becomeForward: 3" is not working?

Eliot Miranda-2
In reply to this post by Denis Kudriashov
 
Hi Denis,

On Mar 17, 2016, at 1:57 AM, Denis Kudriashov <[hidden email]> 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)
Reply | Threaded
Open this post in threaded view
|

Re: Why "object becomeForward: 3" is not working?

Eliot Miranda-2
In reply to this post by Denis Kudriashov
 
Hi Denis,

On Mar 17, 2016, at 6:35 AM, Denis Kudriashov <[hidden email]> 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 <[hidden email]>:

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


Reply | Threaded
Open this post in threaded view
|

Re: Why "object becomeForward: 3" is not working?

Eliot Miranda-2
In reply to this post by Bert Freudenberg



> On Mar 17, 2016, at 7:42 AM, Bert Freudenberg <[hidden email]> wrote:
>
>
>> On 17.03.2016, at 13:52, David T. Lewis <[hidden email]> 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 <[hidden email]> 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 -
>
Reply | Threaded
Open this post in threaded view
|

Re: Why "object becomeForward: 3" is not working?

Denis Kudriashov
 

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?

Reply | Threaded
Open this post in threaded view
|

Re: Why "object becomeForward: 3" is not working?

Bert Freudenberg
 
On 21.03.2016, at 10:28, Denis Kudriashov <[hidden email]> 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 -




smime.p7s (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Why "object becomeForward: 3" is not working?

Denis Kudriashov
 

2016-03-21 16:14 GMT+01:00 Bert Freudenberg <[hidden email]>:
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