[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

How and where Fixnum are created

Eustaquio Rangel de Oliveira Jr.

7/1/2005 8:50:00 PM

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi.

I'm wondering here how and where Fixnum are created.
I saw that ObjectSpace does not returns immediate values, ok, I was curious
about why having

n1, n2, n3, n4 = 1, 2, 3, 1

was returning nothing there on ObjectSpace.each_object(Fixnum).
I know that Fixnum are immediate values, and "they are assigned or passed
as parameters, the actual object is passed, rather than a reference to that
object.".

But reading about "There is effectively only one Fixnum object instance
for any given integer value, so, for example, you cannot add a singleton
method to a Fixnum.", my doubt is if "the actual object" and "only one
Fixnum object instance" referenced above is:

1 - A object created for each Fixnum (like o1 for n1 AND n4, o2 for n2 and
o3 for n3). But if so, they does not appears on ObjectSpace listing, and
what is the behaviour on gc?

n1(1) -------------+---> "hidden" fixnum object (object id 3)
n4(1) -------------+
n2(2) -----------------> another "hidden" fixnum object (object id 5)
n3(3) -----------------> another "hidden" fixnum object (object id 7)

2 - Or a single "internal" Fixnum object which is created ONCE and where is
the VMT, who is asked for it's method everytime it's needed. So on this
case n1, n2, n3 and n4 just stores the -(2**30) till (2**30)-1 number and
asks the "internal" Fixnum object for methods to use with the value.

n1(1) -------------+----> "internal" fixnum (check vmt)
n2(1) -------------+
n3(1) -------------+
n4(1) -------------+

Or any (or some kind of mix of) the two options above?

Thanks.

- ----------------------------
Eustáquio "TaQ" Rangel
eustaquiorangel@yahoo.com
http://b...
Usuário GNU/Linux no. 224050
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.7 (GNU/Linux)

iD8DBQFCxaxib6UiZnhJiLsRAnOFAKCoLs97HNPnwH6BT1yMTmRrF718PwCfbRyo
NoInDSM789ihxj6o3aM08+g=
=zY9W
-----END PGP SIGNATURE-----


9 Answers

Robert Klemme

7/1/2005 9:08:00 PM

0

Eustaquio Rangel de Oliveira Jr. <eustaquiorangel@yahoo.com> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Hi.
>
> I'm wondering here how and where Fixnum are created.
> I saw that ObjectSpace does not returns immediate values, ok, I was
> curious about why having
>
> n1, n2, n3, n4 = 1, 2, 3, 1
>
> was returning nothing there on ObjectSpace.each_object(Fixnum).
> I know that Fixnum are immediate values, and "they are assigned or
> passed as parameters, the actual object is passed, rather than a
> reference to that object.".
>
> But reading about "There is effectively only one Fixnum object
> instance for any given integer value, so, for example, you cannot add
> a singleton method to a Fixnum.", my doubt is if "the actual object"
> and "only one Fixnum object instance" referenced above is:
>
> 1 - A object created for each Fixnum (like o1 for n1 AND n4, o2 for
> n2 and o3 for n3). But if so, they does not appears on ObjectSpace
> listing, and what is the behaviour on gc?
>
> n1(1) -------------+---> "hidden" fixnum object (object id 3)
> n4(1) -------------+
> n2(2) -----------------> another "hidden" fixnum object (object id 5)
> n3(3) -----------------> another "hidden" fixnum object (object id 7)
>
> 2 - Or a single "internal" Fixnum object which is created ONCE and
> where is the VMT, who is asked for it's method everytime it's needed.
> So on this case n1, n2, n3 and n4 just stores the -(2**30) till
> (2**30)-1 number and asks the "internal" Fixnum object for methods to
> use with the value.
> n1(1) -------------+----> "internal" fixnum (check vmt)
> n2(1) -------------+
> n3(1) -------------+
> n4(1) -------------+
>
> Or any (or some kind of mix of) the two options above?

No, it's a third option: Fixnums are not really objects like others. With
Fixnum the object reference is the object itself. But you don't see that
directly because they are made to mostly work like other objects. You can
only observe it indirectly (like you did) in some places, namely

- absence from ObjectSpace
- prohibition of singleton methods

and maybe some more I don't recall because of my sleepyness. From a
pragmatic perspective this all doesn't really matter: since Fixnums are
immutable (no state changes, no singleton methods) anyway it doesn't matter
whether you have one instance representing a certain numeric value or
multiple. What in fact does matter in practice is that the implementation
of Fixnums in Ruby provides better performance than Fixnums that are
ordinary objects; in that case all numeric calculations would suffer because
they would incur the additional overhead of object creation and destruction.
HTH

Kind regards

robert

Eustaquio Rangel de Oliveira Jr.

7/1/2005 9:27:00 PM

0

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hey Robert!

|> Or any (or some kind of mix of) the two options above?

| No, it's a third option: Fixnums are not really objects like others.
| With Fixnum the object reference is the object itself.

I was checking numeric.c and found

rb_cFixnum = rb_define_class("Fixnum", rb_cInteger);

and method stuff like

rb_define_method(rb_cFixnum, "to_s", fix_to_s, -1);

and others. So, there is some method definition there, but so the object
itself handle the methods and it's value?

| But you don't
| see that directly because they are made to mostly work like other
| objects. You can only observe it indirectly (like you did) in some
| places, namely
|
| - absence from ObjectSpace

Yeah, I needed to open gc. and find

"Immediate objects (Fixnums, Symbols, true, false, and nil) are never
returned."

That gaves me a kind of relief because I was not understanding what was
happening. :-)

| and maybe some more I don't recall because of my sleepyness.

Is sleep a rare thing for developers? I'm on that kind of situation also.
Specially because I have a little baby girl who likes to go to sleep late
ehehe. :-)

| From a
| pragmatic perspective this all doesn't really matter: since Fixnums are
| immutable (no state changes, no singleton methods) anyway it doesn't
| matter whether you have one instance representing a certain numeric
| value or multiple.

Sure, but is there just one or multiples? :-)
Multiples instances will "eat" more memory, on this case?

| What in fact does matter in practice is that the
| implementation of Fixnums in Ruby provides better performance than
| Fixnums that are ordinary objects; in that case all numeric calculations
| would suffer because they would incur the additional overhead of object
| creation and destruction. HTH

Yes, that is really a good thing for sure, the implementation is very good.
I'm wondering about that because I'll need to explain that kind of thing to
some developers that does not know Ruby and I'm sure they will ask me
something about this case (specially the python ones). So I need to try to
resume the behaviour for them.

What is still confusing me is, as you said, is that there is no additional
overhead of object creating and destruction, so I can presume that we deal
directly with their values, but where are their methods?

Sorry to bore you, but I need a "light" about that (or more sleep and rest
to think better). :-)

Thanks!

- ----------------------------
Eustáquio "TaQ" Rangel
eustaquiorangel@yahoo.com
http://b...
Usuário GNU/Linux no. 224050
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.7 (GNU/Linux)

iD8DBQFCxbURb6UiZnhJiLsRAjECAJ0VhJxTzg6iPJEo6/dJ1qQ2vVbX4QCgvZHv
ARvvf3e0C3xHZdi27VjoAd0=
=Sccr
-----END PGP SIGNATURE-----


Daniel Brockman

7/2/2005 12:33:00 AM

0

Dominik Bathon

7/2/2005 1:28:00 AM

0

On Sat, 02 Jul 2005 02:32:38 +0200, Daniel Brockman <daniel@brockman.se>
wrote:

> Okay, I realize that this explanation turned out pretty confusing.
> For more information, you might search for ``ruby immediate values.''
>
> I hope this helps at least a bit,

If you look at ruby.h, you will find the following defines:

#define FIXNUM_MAX (LONG_MAX>>1)
#define FIXNUM_MIN RSHIFT((long)LONG_MIN,1)

#define FIXNUM_FLAG 0x01
#define INT2FIX(i) ((VALUE)(((long)(i))<<1 | FIXNUM_FLAG))
#define LONG2FIX(i) INT2FIX(i)

...

#define FIX2LONG(x) RSHIFT((long)x,1)
#define FIX2ULONG(x) (((unsigned long)(x))>>1)
#define FIXNUM_P(f) (((long)(f))&FIXNUM_FLAG)
#define POSFIXABLE(f) ((f) <= FIXNUM_MAX)
#define NEGFIXABLE(f) ((f) >= FIXNUM_MIN)
#define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f))


They should be self-explanatory after Daniel's nice explanation, and
should clear it up further.

You can also see how it works if you look at the object_id of Fixnums:

>> 1.object_id
=> 3
>> 42.object_id
=> 85
>> ObjectSpace._id2ref(87)
=> 43
>> ObjectSpace._id2ref(-87)
=> -44
>> ObjectSpace._id2ref(-86)
RangeError: 0xffffffaa is not id value
from (irb):5:in `_id2ref'
from (irb):5


Dominik


Eustaquio Rangel de Oliveira Jr.

7/2/2005 1:42:00 AM

0

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

| Eustaquio,

Hey Daniel. :-)

| Later, when you say this,
| foo.moomin
| Ruby sees that `foo' is divisible by four and so must be a pointer to
| an object, and a regular method call is made. But when you say this,

A regular method is called on the object at a memory location allocated
for the object value OR for value and a representation of the object
class, with methods and so on?

What is pointed by, let's say, a variable who stores a reference to a
String like "this is a long string where I can write a lot of things" is
just the string value or a complete package with it's value and methods?

What will be released by the garbage collector is the answer of the
question above (memory allocated for values OR for values and methods),
when is not needed anymore, right?

For example on

s1, s2, s3, s4 = "this","is","a","test"

s1, s2, s3, s4 shares the String methods and their references points to
memory locations only with "this" "is" "a" "test", querying the String
methods on a String representation

OR

the reference to "this" & object methods, "is" & object methods, "a" &
object methods and "test" & object methods?

So it's like

~ +-------- gc works here ------------+
~ | |
~ +--------+---------+ +---------+ +---------+--------+
~ | memory allocated | | String | | memory allocated |
~ +------------------+ +---------+ +------------------+
~ | value | | methods | | value |
~ +------------------+ +---------+ +------------------+
s1 = | "this" +--+ upcase +--+ "is" | = s2
~ +------------------+ +---------+ +------------------+

or like

~ +-------- gc works here -------+
~ | |
~ +---------+---------+ +--------+---------+
~ | memory allocated | | memory allocated |
~ +---------+---------+ +--------+---------+
~ | value | methods | | value | methods |
~ +---------+---------+ +--------+---------+
s1 = | "this" | upcase | s2 = | "is" | upcase |
~ +---------+---------+ +--------+---------+

I think it should be first one, specially when we change the String
class at runtime and it changes all the String references, but I'm
asking just to be sure. :-)

| bar.snufkin
| it sees that `bar' contains 85, which is an odd integer --- not
| divisible by four. The oddness means that `bar' is an immediate
| Fixnum, so Ruby converts the value to its real meaning by subtracting
| one and halving it, giving 42. Then the method `snufkin' is looked up
| in the Fixnum class and invoked with `self' bound to 42.

That give us the value of the Fixnum, where we can find it's real value,
as you explained, and on this case the method (snufkin) is looked up on
a generic (or "internal") Fixnum class, like I supposed String above,
not on the reference (the reference is the own object) as above right?
Kind of

n1, n2 = 1, 2

~ +-------+ +---------+ +-------+
~ | value | | methods | | value |
~ +-------+ +---------+ +-------+
n1 = | 1 +---| succ +---+ 2 | = n2
~ +-------+ +---------+ +-------+

So we can make math right with it's value, as Robert said, not needing
to make an overhead with methods and so on, right?
Robert answered me about this but his email is on my mailbox on my job. :-(

| Okay, I realize that this explanation turned out pretty confusing.
| For more information, you might search for ``ruby immediate values.''

No, I really appreciated it. Thank you very much. Sorry for bore you
guys with this kind of thing but I'm really curious. :-)

I searched for that on the web, but I really needed some more "deeper"
info, because there's a lot of places with just replicate the pickaxe
contents. :-)

Best regards,

- ----------------------------
Eustáquio "TaQ" Rangel
eustaquiorangel@yahoo.com
http://b...
Usuário GNU/Linux no. 224050
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (GNU/Linux)

iD8DBQFCxfEtb6UiZnhJiLsRApkXAJ0a1xSF7bmj19Athamio4BO0W69CgCeLsHN
BHaE1nxEz5IpquPKw2cRiVA=
=o8UT
-----END PGP SIGNATURE-----


Daniel Brockman

7/2/2005 2:41:00 AM

0

Eustaquio Rangel de Oliveira Jr.

7/2/2005 9:52:00 AM

0

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hey Daniel.

| Basically just the string data and a pointer to the String class.

Fine!

| Just the memory for the data. The methods are still needed because
| there are other strings around.

Ok!

| No, this is not how it works. That would be terribly inefficient.

Yes, I know, just asked to be sure ehehe. :-)

|>I think it should be first one, specially when we change the String
|>class at runtime and it changes all the String references, but I'm
|>asking just to be sure. :-)
| You are correct. :-)

Cool! :-)

| No, what happens is more like this:
| n1 = 0x00000003 | Fixnum |
| n2 = 0x00000005 | succ |
| +---------+
| The `n1' and `n2' variables don't reference any _actual_ objects.
| Ruby pretends the objects are there so we can feel warm and fuzzy.
| It would be too inefficient to allocate a separate memory block for
| each and every small integer out there.

Perfect!

| The truth is
| that I needed to freshen up a bit on this myself. :-)

It's what is happening to me trying to understand it more deeper. I
talked with some guys about Fixnum and they asked (and will ask more)
how it works internally, so it's curious how we learn (and remember, on
your case) about things talking about them. :-)

| Ah, yes, that's annoying. Man pages, in particular, tend to be
| replicated across so many pages that they pollute search results.
| One copy is quite enough please.

I have a 150 pages Ruby tutorial here and will write about what we
talked here. At least it can be a little different from the rest.

Thanks Daniel, Dominik and Robert for your explanation about that. I
think I got the idea of how it works. :-)

Best regards,

- ----------------------------
Eustáquio "TaQ" Rangel
eustaquiorangel@yahoo.com
http://b...
Usuário GNU/Linux no. 224050
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (GNU/Linux)

iD8DBQFCxmQFb6UiZnhJiLsRAiy7AJ9jkz0L1eFqdMVz10bh6XZKSoILtwCfaryj
cBmMrMflZRarSQoruxtpKgw=
=pX4c
-----END PGP SIGNATURE-----


Daniel Brockman

7/2/2005 2:00:00 PM

0

Daniel Brockman

7/2/2005 2:09:00 PM

0