Object_id 1, 2, 3

Fixnum object_id
0 1
1 3
2 5

-1 -1
-2 -3

so the question is… which objects have the object_id 2, 4, 6, and -2,
-4, etc?

irb(main):041:0> a = 0
=> 0
irb(main):042:0> a.object_id
=> 1

irb(main):043:0> a = 1
=> 1
irb(main):044:0> a.object_id
=> 3

irb(main):045:0> a = 2
=> 2
irb(main):046:0> a.object_id
=> 5

irb(main):047:0> a = -1
=> -1
irb(main):048:0> a.object_id
=> -1

irb(main):049:0> a = -2
=> -2
irb(main):050:0> a.object_id
=> -3

$ irb
irb(main):001:0> true.object_id
=> 2
irb(main):002:0> nil.object_id
=> 4
irb(main):003:0> false.object_id
=> 0

I saw a flowchart somewhere (online?) that showed how the least-
significant bits were used by the interpreter in the implementation
of some “objects” which were both common and immutable (TrueClass,
FalseClass, NilClass, Fixnum).

The LSB=1 is Fixnum (hence the object_id of n would be (n<<1)|0x01 in
the underlying C code).

-Rob

On Sep 24, 2007, at 8:14 PM, SpringFlowers AutumnMoon wrote:

and -2,
irb(main):043:0> a = 1
=> -1
irb(main):048:0> a.object_id
=> -1

irb(main):049:0> a = -2
=> -2
irb(main):050:0> a.object_id
=> -3

Rob B. http://agileconsultingllc.com
[email protected]

Rob B. wrote:

$ irb
irb(main):001:0> true.object_id
=> 2
irb(main):002:0> nil.object_id
=> 4
irb(main):003:0> false.object_id
=> 0

irb(main):063:0> 1000.object_id
=> 2001

irb(main):064:0> 1001.object_id
=> 2003

wonder where the 2002, 2004, etc go…

SpringFlowers AutumnMoon wrote:

-4, etc?

ex$ irb
irb(main):001:0> x = true
=> true
irb(main):002:0> x.object_id
=> 2
irb(main):003:0> x = false
=> false
irb(main):004:0> x.object_id
=> 0
irb(main):005:0> x = nil
=> nil
irb(main):006:0> x.object_id
=> 4

In other words, very small even values of object_id are reserved for
special values.

Rob B. wrote:

I saw a flowchart somewhere (online?) that showed how the least-
significant bits were used by the interpreter in the implementation
of some “objects” which were both common and immutable (TrueClass,
FalseClass, NilClass, Fixnum).

The LSB=1 is Fixnum (hence the object_id of n would be (n<<1)|0x01 in
the underlying C code).

you mean the 2002, 2004, 20002, 20004, etc are all for other immutable
objects? what are they i wonder… the negative numbers have their own
negative object_id’s.

One should keep in mind that these are interesting implementation
artifacts. I don’t believe that there’s any guarantee that such ids
would be the same in an arbitrary ruby implementation or even between
versions of the same implementation.

No – nor should they be expected to be, under any circumstance.

At best, they’re used for comparing objects (Object#==), and should
never be explicitly stored or used for comparisons or hash lookups in
their own right
. Even two similar strings can have different
object_ids.

irb(main):001:0> “a”.object_id
=> 23739988544880
irb(main):002:0> “a”.object_id
=> 23739988519760
irb(main):003:0>

Be careful, and remember that you should anticipate them to never remain
constant between executions of even the same interpreter. (though they
will for your numbers, but beware… :))

Arlen

Rick Denatale wrote:

On 9/24/07, Tim H. [email protected] wrote:

so the question is… which objects have the object_id 2, 4, 6, and -2,
irb(main):004:0> x.object_id
=> 0
irb(main):005:0> x = nil
=> nil
irb(main):006:0> x.object_id
=> 4

One should keep in mind that these are interesting implementation
artifacts. I don’t believe that there’s any guarantee that such ids
would be the same in an arbitrary ruby implementation or even between
versions of the same implementation.

right, it is just from the curiosity standpoint. that where did those
even number object id’s go? (the 10002, 10004, etc)

On 9/24/07, Tim H. [email protected] wrote:

so the question is… which objects have the object_id 2, 4, 6, and -2,
irb(main):004:0> x.object_id
=> 0
irb(main):005:0> x = nil
=> nil
irb(main):006:0> x.object_id
=> 4

In other words, very small even values of object_id are reserved for
special values.

One should keep in mind that these are interesting implementation
artifacts. I don’t believe that there’s any guarantee that such ids
would be the same in an arbitrary ruby implementation or even between
versions of the same implementation.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On Sep 24, 2007, at 17:14 , SpringFlowers AutumnMoon wrote:

and -2,
-4, etc?

ri ObjectSpace._id2ref

(0…5).map { |n| ObjectSpace._id2ref(n) }
=> [false, 0, true, 1, nil, 2]

On Sep 26, 2007, at 14:00 , Tim H. wrote:

Also, because of the way operating systems dole out memory to C
programs, the memory addresses are usually going to be very large
numbers.

Of course at this point somebody will pipe up and say that what I just
wrote is untrue on such-and-such an obscure computer, and they’d be
right.

You don’t need to go quite so far. OS X starts its heap at a low
memory address:

$ ruby -ve “p ‘’.object_id”
ruby 1.8.6 (2007-09-23 patchlevel 5000) [powerpc-darwin8.10.0]
1002180

$ ruby -ve “p ‘’.object_id”
ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-freebsd6]
67351450

Also, the way ruby’s heap is constructed, addresses will count down
then jump up to the next chunk of ruby heap slots (provided that no
GC is done):

$ ruby -e “p %w[a b].map { |o| o.object_id }”
[1002060, 1002050]

Also, on 64 bit platforms ruby objects are twice as big due to bigger
pointers and whatnot:

$ ruby -ve “p %w[a b].map { |o| o.object_id }”
ruby 1.8.5 (2006-08-25) [amd64-freebsd6]
[2789280, 2789260]

SpringFlowers AutumnMoon wrote:

Rick Denatale wrote:

On 9/24/07, Tim H. [email protected] wrote:

so the question is… which objects have the object_id 2, 4, 6, and -2,
irb(main):004:0> x.object_id
=> 0
irb(main):005:0> x = nil
=> nil
irb(main):006:0> x.object_id
=> 4

One should keep in mind that these are interesting implementation
artifacts. I don’t believe that there’s any guarantee that such ids
would be the same in an arbitrary ruby implementation or even between
versions of the same implementation.

right, it is just from the curiosity standpoint. that where did those
even number object id’s go? (the 10002, 10004, etc)

Object ids are memory addresses. Due to the way C programs (remember
Ruby is a C program) allocate memory, the object ids that are not
Fixnums and not very small even numbers are (at least in common systems)
always multiples of 8, so 10002 isn’t going to be a real object id.
Also, because of the way operating systems dole out memory to C
programs, the memory addresses are usually going to be very large
numbers. (Mostly because operating systems like to reserve low memory
addresses for themselves.) Memory addresses are of course always
positive numbers, but Ruby displays object ids as signed numbers. If the
memory address is sufficiently large (such that the sign bit is set)
Ruby displays it as a negative number.

Of course at this point somebody will pipe up and say that what I just
wrote is untrue on such-and-such an obscure computer, and they’d be
right. I’m just talking about the kind of computers (PCs) and operating
systems (Win, Linux, etc.) that Ruby commonly runs on. Personally I’d be
interested in hearing about computers that Ruby runs on that don’t act
this way.

Eric H. wrote:

You don’t need to go quite so far. OS X starts its heap at a low
memory address:

$ ruby -ve “p ‘’.object_id”
ruby 1.8.6 (2007-09-23 patchlevel 5000) [powerpc-darwin8.10.0]
1002180

$ ruby -ve “p ‘’.object_id”
ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-freebsd6]
67351450

Also, the way ruby’s heap is constructed, addresses will count down
then jump up to the next chunk of ruby heap slots (provided that no
GC is done):

$ ruby -e “p %w[a b].map { |o| o.object_id }”
[1002060, 1002050]

so the object_id can be just the memory location of the object? does
Ruby keep a table to tell whether it is a memory location as opposed to

irb(main):003:0> 1000000.object_id
=> 2000001

which is not a memory location… in other words, when Ruby tries to
fetch the object, sometimes it will dereference 1002060 (fetch the
content there) but sometimes it won’t, but just pretend that it is an
actual object?

I just realize that what if we extend the class Fixnum to have an extra
instance variable

class Fixnum
attr_accessor :foo
end

p 1.foo # nil

1.foo = 123
p 1.foo # 123
p 1.object_id # 3

so in this case, the object_id is not the memory location… and where
is the memory location? (for storing the instance variable)

I also found that you cannot do a

a = Fixnum.new

On Sep 27, 2007, at 10:11 , SpringFlowers AutumnMoon wrote:

ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-freebsd6]
Ruby keep a table to tell whether it is a memory location as
opposed to

irb(main):003:0> 1000000.object_id
=> 2000001

For non-symbols and non-fixnums, it is the memory location of the
Object.

The table is:

static struct heaps_slot { /* … */ } *heaps;

in gc.c.

which is not a memory location… in other words, when Ruby tries to
fetch the object, sometimes it will dereference 1002060 (fetch the
content there) but sometimes it won’t, but just pretend that it is an
actual object?

See _id2ref in gc.c for how an id is turned into an Object.

I just realize that what if we extend the class Fixnum to have an
extra
instance variable

Instance variables are stored in a Hash that hangs off of the Object
for struct RObject-backed objects. There is a global hash for
everything else.

On 9/27/07, SpringFlowers AutumnMoon [email protected] wrote:

ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-freebsd6]
Ruby keep a table to tell whether it is a memory location as opposed to
instance variable
p 1.object_id # 3

so in this case, the object_id is not the memory location… and where
is the memory location? (for storing the instance variable)

For objects with immediate values, there is a global hash table which
maps the object_id to the location of the instance variables.

Note that “extend(ing) a class to have an extra instance variable” is
a bit misleading for Ruby.

Unlike many other OO languages instance variables in Ruby aren’t
really associated with a class.
An instance acquires an instance variable not because it’s a member of
a class, but because a method with that object as self was executed
which initialized it.

irb(main):001:0> class Fixnum
irb(main):002:1> attr_accessor :foo
irb(main):003:1> def foo_defined?
irb(main):004:2> defined? @foo
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> 1.foo_defined?
=> nil
irb(main):008:0> 1.foo = 123
=> 123
irb(main):009:0> 1.foo_defined?
=> “instance-variable”
irb(main):010:0> 2.foo_defined?
=> nil

This is true of all objects, not just immediates.

irb(main):011:0> class Glorp
irb(main):012:1> attr_accessor :bar
irb(main):013:1> def bar_defined?
irb(main):014:2> defined? @bar
irb(main):015:2> end
irb(main):016:1> end
=> nil
irb(main):017:0> g = Glorp.new
=> #Glorp:0x5ba68
irb(main):018:0> g.bar_defined?
=> nil
irb(main):019:0> g.bar = :fred
=> :fred
irb(main):020:0> g.bar_defined?
=> “instance-variable”


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/