Open-Source Wikis

/

Ruby

/

Reference

/

Data models

ruby/ruby

Data models

Memory layouts of the core CRuby types. Most live in include/ruby/internal/core/ (public-API view) or in the *.c files (internal view).

VALUE

A VALUE is a uintptr_t-sized tagged integer (include/ruby/internal/value.h):

64-bit layout:

| 63                                                       1 | 0 |
+------------------------------------------------------------+---+
| heap-pointer (aligned, low 3 bits zero)                    | 0 |
| Fixnum integer payload                                     | 1 |
| Flonum float payload                                  | 1 0 | 0 |
| Symbol id                                          | 1 1 0 0 | (0?) |
| Qfalse  = 0x0                                              |
| Qnil    = 0x8                                              |
| Qtrue   = 0x14                                             |
| Qundef  = 0x24 (sentinel; never visible to Ruby code)      |

Helpers:

Macro Test
RB_FIXNUM_P(v) low bit is 1
RB_FLONUM_P(v) (v & 3) == 2 (Flonum-enabled platforms)
RB_STATIC_SYM_P(v) low byte matches RUBY_SYMBOL_FLAG
RB_NIL_P(v) v == Qnil
RB_SPECIAL_CONST_P(v) not a heap pointer
RB_TYPE_P(v, T_X) heap-object type check

Conversions:

Macro Action
INT2FIX(n) Embed C int as Fixnum
LONG2NUM(n) Fixnum if it fits, otherwise allocate Bignum
FIX2LONG(v) Unwrap Fixnum
RFLOAT_VALUE(v) Get C double from a Float (or Flonum)
RB_SYM2ID(v) Symbol → ID
RB_ID2SYM(id) ID → Symbol

Heap object header (RBasic)

Every heap object starts with struct RBasic:

struct RBasic {
    VALUE flags;        /* type, frozen?, embedded?, encoding, shape, ... */
    const VALUE klass;  /* class pointer */
};

The flags field encodes:

  • The type tag (T_OBJECT, T_ARRAY, T_STRING, T_HASH, T_REGEXP, T_FLOAT, T_BIGNUM, etc.).
  • The frozen bit.
  • The embed flag (for String/Array embedded variants).
  • The encoding index (for String, Symbol, Regexp).
  • The shape id (for T_OBJECT).
  • GC bits (write-barrier-protected, marked, old, age).

Type tags are listed in include/ruby/internal/value_type.h:

enum ruby_value_type {
    RUBY_T_NONE   = 0x00,
    RUBY_T_OBJECT = 0x01,    /* user-defined class instance */
    RUBY_T_CLASS  = 0x02,
    RUBY_T_MODULE = 0x03,
    RUBY_T_FLOAT  = 0x04,
    RUBY_T_STRING = 0x05,
    RUBY_T_REGEXP = 0x06,
    RUBY_T_ARRAY  = 0x07,
    RUBY_T_HASH   = 0x08,
    RUBY_T_STRUCT = 0x09,
    RUBY_T_BIGNUM = 0x0a,
    RUBY_T_FILE   = 0x0b,
    RUBY_T_DATA   = 0x0c,    /* TypedData wrapper for C extensions */
    RUBY_T_MATCH  = 0x0d,
    RUBY_T_COMPLEX = 0x0e,
    RUBY_T_RATIONAL = 0x0f,
    RUBY_T_NIL    = 0x11,
    RUBY_T_TRUE   = 0x12,
    RUBY_T_FALSE  = 0x13,
    RUBY_T_SYMBOL = 0x14,
    RUBY_T_FIXNUM = 0x15,
    RUBY_T_UNDEF  = 0x16,
    RUBY_T_IMEMO  = 0x1a,    /* internal-memo type */
    RUBY_T_NODE   = 0x1b,    /* AST node */
    RUBY_T_ICLASS = 0x1c,    /* internal class for Module#include */
    RUBY_T_ZOMBIE = 0x1d,    /* dead object pending finalizer */
    RUBY_T_MOVED  = 0x1e,    /* compaction forwarded */
    RUBY_T_MASK   = 0x1f,
};

RObject

The default user-class instance:

struct RObject {
    struct RBasic basic;
    union {
        struct {
            uint32_t numiv;          /* number of inline IVs in use */
            VALUE *ivptr;            /* IV array (heap-allocated for non-embedded) */
            void *iv_index_tbl;      /* legacy ivar lookup table */
        } heap;
        VALUE ary[ROBJECT_EMBED_LEN_MAX];   /* embedded inline IVs */
    } as;
};

Modern Ruby uses shapes (shape.c/shape.h) for IV layout. The shape ID in flags indexes into a transition table that maps (shape, name) pairs to slot indices.

RArray

struct RArray {
    struct RBasic basic;
    union {
        struct {
            long len;
            VALUE *ptr;
            union { long capa; VALUE shared_root; } aux;
        } heap;
        const VALUE ary[RARRAY_EMBED_LEN_MAX];
    } as;
};

Three flavors via flags: embedded, heap, shared.

RHash

struct RHash {
    struct RBasic basic;
    union {
        struct st_table *st;          /* general-purpose */
        struct ar_table_struct *ar;   /* small open-addressed */
    } as;
    const VALUE ifnone;
};

ar_table for ≤ 8 entries; st_table for larger.

RString

struct RString {
    struct RBasic basic;
    union {
        struct {
            long len;
            char *ptr;
            union { long capa; VALUE shared; } aux;
        } heap;
        struct { char ary[RSTRING_EMBED_LEN_MAX + 1]; } embed;
    } as;
};

Three flavors. Encoding index in flags.

RBignum

struct RBignum {
    struct RBasic basic;
    long len;
    BDIGIT *digits;       /* sign + magnitude in base 2^BITSPERDIG */
};

BDIGIT is uint32_t on most platforms. BITSPERDIG = 32.

RRational and RComplex

struct RRational {
    struct RBasic basic;
    VALUE num;
    VALUE den;
};

struct RComplex {
    struct RBasic basic;
    VALUE real;
    VALUE imag;
};

RData / RTypedData

struct RTypedData {
    struct RBasic basic;
    VALUE typed_flag;                  /* always 1 */
    const rb_data_type_t *type;        /* mark/free/size/compact callbacks */
    void *data;                        /* user pointer */
};

TypedData_Make_Struct allocates one of these around a C struct. type provides:

struct rb_data_type_struct {
    const char *wrap_struct_name;
    struct {
        void (*dmark)(void *);
        void (*dfree)(void *);
        size_t (*dsize)(const void *);
        void (*dcompact)(void *);
    } function;
    const struct rb_data_type_struct *parent;
    void *data;
    VALUE flags;
};

rb_iseq_t

typedef struct rb_iseq_struct rb_iseq_t;

struct rb_iseq_struct {
    VALUE flags;
    VALUE wrapper;
    struct rb_iseq_constant_body *body;
};

struct rb_iseq_constant_body {
    enum rb_iseq_type type;            /* :method, :block, :class, :top, ... */
    unsigned int iseq_size;
    VALUE *iseq_encoded;               /* the bytecode */
    rb_iseq_param_struct param;
    rb_id_table_t *local_table;
    int local_table_size;
    rb_iseq_call_data_struct call_data;
    rb_iseq_constant_body::iseq_insn_info insn_info;
    /* + many more fields */
};

Defined in iseq.h. Each method, block, class body, lambda, top-level program is an rb_iseq_t.

rb_callinfo and rb_callcache

struct rb_callinfo {
    VALUE flag;        /* call kind: simple, with-block, kwargs, ... */
    int argc;
    VALUE kwarg;
    VALUE mid;
};

struct rb_callcache {
    VALUE flags;
    VALUE klass;       /* class at last hit */
    const struct rb_callable_method_entry_struct *cme;
    union {
        struct { uintptr_t method_serial; uintptr_t aux1; } v;
        struct { VALUE call; uintptr_t aux2; } jit;
    } aux_;
};

Defined in vm_callinfo.h. One callinfo per call site (immutable). One callcache per call site (mutable, updated on misses).

rb_method_entry_t

struct rb_method_entry {
    VALUE flags;
    const struct rb_method_definition_struct *def;
    ID called_id;
    VALUE owner;       /* defining class or module */
};

The method definition can be:

  • VM_METHOD_TYPE_ISEQ — Ruby method (carries an iseq).
  • VM_METHOD_TYPE_CFUNC — C method (carries a function pointer).
  • VM_METHOD_TYPE_ATTRSET, VM_METHOD_TYPE_IVAR — accessors generated by attr_*.
  • VM_METHOD_TYPE_BMETHODdefine_method-defined.
  • VM_METHOD_TYPE_ZSUPERprivate re-definition that just chains to super.
  • VM_METHOD_TYPE_REFINED — refinement entry.
  • VM_METHOD_TYPE_NOTIMPLEMENTEDrb_f_notimplement.
  • VM_METHOD_TYPE_ALIAS — alias.
  • VM_METHOD_TYPE_OPTIMIZED — built-in fast paths.

Stored in classes' method tables (rb_id_table_t keyed by method ID).

rb_control_frame_t

struct rb_control_frame_struct {
    const VALUE *pc;                   /* program counter */
    VALUE *sp;                         /* stack pointer */
    const rb_iseq_t *iseq;
    VALUE self;
    const VALUE *ep;                   /* environment pointer */
    void *block_handler;
};

One per active method/block call. Lives on the per-thread VM stack.

rb_execution_context_t

struct rb_execution_context_struct {
    VALUE *vm_stack;
    size_t vm_stack_size;
    rb_control_frame_t *cfp;
    /* + interrupt mask, raised flags, errinfo, machine state */
};

Per-thread state. GET_EC() returns the running thread's EC.

rb_thread_t and rb_ractor_t

struct rb_thread_struct {
    rb_execution_context_t *ec;
    rb_ractor_t *ractor;
    /* native thread handle, status, priority */
};

struct rb_ractor_struct {
    rb_global_vm_lock_t *gvl;
    struct list_head threads;
    /* per-ractor caches */
};

See systems/threading.md and systems/ractor.md.

RClass / RModule

struct RClass {
    struct RBasic basic;
    VALUE super;                       /* parent class */
    rb_classext_t *ptr;                /* method table, IV table, constant table */
};

rb_classext_t holds:

  • The method table (rb_id_table_t).
  • The constant table.
  • The IV index table for instances.
  • The class IV table.
  • Subclass list (for inheritance invalidation).
  • Refinement metadata.

Special constants

Constant Meaning Encoding
Qnil nil 0x08
Qfalse false 0x00
Qtrue true 0x14
Qundef sentinel ("undefined") 0x24 (not exposed to Ruby)

Qfalse == 0 is intentional — if (v) in C is true iff the VALUE is "Ruby-truthy" plus Qnil-checking, except Qnil != 0. RTEST(v) does the right check (!RB_NIL_P(v) && v != Qfalse).

See also

  • include/ruby/internal/value.h, value_type.h — the public-API view.
  • include/ruby/internal/core/RObject, RArray, RHash, RString, RClass, etc.
  • vm_core.hrb_vm_t, rb_thread_t, rb_iseq_t, rb_control_frame_t.
  • vm_callinfo.h — call site structures.
  • iseq.h — iseq layout.
  • shape.h — object shape transitions.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Data models – Ruby wiki | Factory