Ruby Object Encoding

CSC 252 Lecture on Tuesday January 29, 2013 by Chen Ding.  Notes taken by Jacob Brock.

RUBY NOTES

 

* Architects don't give full precision.  Why?

** Speed!

** How does Intel sell so much?

*** Improvements. Improvements. Improvements.

*** ~2,000 R&D employees in Hillsborough, OR.

*** Faster, stronger processor every 1-2 years.

 

* Ruby can give "infinite" (up to machine limits) precision.

** Example: Factorial

  >> def fac(n)

  >>   return 1 if n == 0

  >>   return n * fac(n-1)

  >> end

** Everything in Ruby is an object.

  >> 100.class

  => Fixnum

  >> (100**10).class

  => Bignum

*** Under the hood, automatic type conversion from Fixnum to Bignum.

*** So what do we need inside the object?

*** From rhg.rubyforge.org/chapter02.html

**** In ruby, the contents of an object is expressed by a C structure, always handled via a pointer. A different kind of structure is used for each class, but the pointer type will always be VALUE (figure 1).

**** Exercise: Complete the Code for on/off/flip/check

  unsigned long mark (unsigned long flags) {

    return ______________

  }

**** Look at T_MASK below, last 6 bits will remain after applying mask.

 

**** From ruby.h

  #define T_NONE   0x00

 

  #define T_NIL    0x01

  #define T_OBJECT 0x02

  #define T_CLASS  0x03

  #define T_ICLASS 0x04

  #define T_MODULE 0x05

  #define T_FLOAT  0x06

  #define T_STRING 0x07

  #define T_REGEXP 0x08

  #define T_ARRAY  0x09

  #define T_FIXNUM 0x0a

  #define T_HASH   0x0b

  #define T_STRUCT 0x0c

  #define T_BIGNUM 0x0d

  #define T_FILE   0x0e

 

  #define T_TRUE   0x20

  #define T_FALSE  0x21

  #define T_DATA   0x22

  #define T_MATCH  0x23

  #define T_SYMBOL 0x24

 

  #define T_BLKTAG 0x3b

  #define T_UNDEF  0x3c

  #define T_VARMAP 0x3d

  #define T_SCOPE  0x3e

  #define T_NODE   0x3f

 

  #define T_MASK   0x3f

 

** Pointer has 8 bytes.  Ruby embeds a Fixnum into 8 bytes!

*** Does this create a conflict?  Given 8 bytes, how do we tell if it's a pointer or a number?

*** When we reference a memory address, we can refer to it only at word granularity (for 64 bit machine, this is 8 bytes, for 32 bit, 4 bytes).  For the pointer, the address has to be multiples of word size.  This means the last 2 or 3 bits have to be zero.  These are then free to indicate if it's a pointer or something else!

**** 6 cases:

  1. small integers

  2. symbols

  3. true

  4. false

  5. nil

  6. Qundef

 

** Bignum (see bignum.c in rubycore)

*** Buf is array of long integers.

*** Buf is ordered from least significant to most significant word

*** buf[0] is the least significant word

*** buf[num_longs-1] is the most significant word

*** This means the array "buf" is little endian.

*** However, each word in buf is native endian.