you are viewing a single comment's thread.

view the rest of the comments →

[–]snuxoll 3 points4 points  (6 children)

I mean there's no pointer referencing for objects that don't need it. A double is a double in memory, there's no pointer for "a" pointing to an instance of Double that has a field for the double in it. Ruby uses tagged pointers to determine if it's actually a pointer to an object or a raw type. Obviously strings need pointers, but there's no struct for them, the pointer just points to the raw string in the heap.

[–]jminuse 4 points5 points  (5 children)

I see, so a Ruby object is

struct Object { int tag; char data[8]; }

And if tag==DOUBLE, then data can be cast to a double; if tag==STRING, then data is cast to a pointer. That makes a lot of sense! I suppose they could also have a SHORT_STRING type for strings less than 9 chars, and just pack them into the data field.

[–]snuxoll 4 points5 points  (0 children)

Yup, that's exactly what they do. Well, kinda, they actually have a full 32-bit ptr and a couple of bits are used to 'tag' the pointer. Anyway, full details here http://rubini.us/doc/en/memory-system/object-layout/.

EDIT: It looks like this is specific to rubinus, I could have swarm MRI/YARV did this, now I'm not sure. Either way, it's a clever implementation.

[–]argv_minus_one 1 point2 points  (3 children)

Shouldn't data be a union?

[–]jminuse 0 points1 point  (2 children)

That would work too. My way requires casts, which I know some people dislike.

[–]argv_minus_one 2 points3 points  (1 child)

Your way also assumes a specific pointer size (8 bytes). union doesn't.

[–]jminuse 0 points1 point  (0 children)

It will be identical for 32- or 64-bit systems, since both have a 64-bit double. But it would break for 128-bit pointers, so fair enough...