On Thu, Sep 3, 2009 at 11:54 AM, Charles Oliver
Nutter<headius / headius.com> wrote:
> On Wed, Aug 26, 2009 at 5:21 PM, Shot (Piotr Szotkowski)<shot / hot.pl> wro=
te:
>> EbFFA:
>>
>>> I was playing with Ruby and wrote an interesting method:
>>
>>> =A0 =A0 def double n
>>> =A0 =A0 =A0 n.object_id - 1
>>> =A0 =A0 end
>>
>>> Anyone know why this works? Why Ruby was implemented this way?
>>
>> Note that other Ruby implementations (JRuby, Rubinius, IronRuby=85) do
>> not have to keep this contract; it=92s best considered as MRI peculiarit=
y.
>> But yes, I do find this design beautiful =96 as well as Ruby=92s method
>> lookup: http://www.viddler.com/explore/CobyR/videos/1/
>
> I don't know that it's particularly beautiful; it's just a side effect
> of Fixnums not having any internal state and not actually being
> objects in MRI. Because they are "immediates" they don't actually have
> an object_id. As a result, their object_id is just based on their
> actual value, 2n+1. All other objects then get stuffed into the
> remaining even object_ids, and fixnum.object_id - 1 =3D=3D fixnum * 2.

And its not that particularly unique to MRI.  I know lots of VM
implementations for various languages (Ruby, Smalltalk, JavaScript
...) which use different variations of representing an integer n
smaller than 2**b for some b less than the word length as:

      n * 2**flag_shift + int_flag

where flag_shift is some small integer (usually but not always 1) and
int_flag is usually 1 or at least odd, since on most machines a
pointer to an object will be aligned on some even address boundary.

For some reason, Googles V8 JavaScript VM uses an int_flag of 1 and
SETs the low order bit of references which are pointers, at least
according to a video I watched about the implementation.


--=20
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale