【日々更新中です】RubyのRObjectの構造体について深めてみる（2016/06/03更新）

最近ひたすらRubyの元コードを読んで、う〜んと頭をもたげています。
頑張って、早くRubyに対してCommit出来るくらいの知識を身につけたいと思います。（そして、いつの日かコミッターとやらになるぞー！おー！）

### 今回の趣旨

今回の趣旨は、書きながら説明しながらだと適当に読み飛ばすこともないので、勉強にはもってこいだなって感じで、書いてます。だから、自分の理解用のものなのでわかりにくいところや、これは理解が違うってところがあるかもしれませんが、そしたら叱ってやってください。

ちなみにC言語の知識もそこまでないので、勉強しながら調べながら進んでいきます。
寄り道もたくさんします。

**rubyのVersionは2.3.1**です。

## 今回のコードはこちら

```c:ruby-2.3.1/include/ruby/ruby.h
struct RObject {
    struct RBasic basic;
    union {
	struct {
	    long numiv; /* only uses 32-bits */
	    VALUE *ivptr;
            void *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */
	} heap;
	VALUE ary[ROBJECT_EMBED_LEN_MAX];
    } as;
};
```

これは、RObjectの構造体を定義している部分です。
RObjectのメンバ変数は

- RBasic basic
- union(struct{long numiv, VALUE *ivptr, void *iv_index_tbl})
- VALUE ary[ROBJECT_EMBED_LEN_MAX];

の三つです。
まだまだ全然意味がわかりません笑
勉強していきます

## RBasic

まず、RBasicを見てみます。もうどの構造体もメンバに持っていないので
どうやら、RBasicがrubyが持つ構造体の元になっているようです。

```c:ruby-2.3.1/include/ruby/ruby.h
struct RBasic {
    VALUE flags;
    const VALUE klass;
}
```

RBasicは、VALUE flagsとconst VALUE klassをメンバに持つ構造体でした。

### VALUE型

まず、VALUE型は、再定義された型なので調べると

`typedef unsigned long VALUE;`

と出てきます。
つまり、VALUE型は、32bitで、符号なし（倍長）整数型で、範囲を0～4294967295これだけ持つ型です。
Rubyだとなんかめっちゃ出てきます。

### flagsの持つ意味

さて、ではflagsが持つ意味について深めていきます。
flagsは、

> flagsは多目的のフラグだが、最も重要な用途は構造体の型 （struct RObjectだとか）を記憶しておくことである。型を示すフラグは T_xxxxという名前で定義されていて、VALUEからはマクロTYPE()で 得ることができる。

> Rubyソースコード完全解説
http://i.loveruby.net/ja/rhg/book/

とのことです。
flagsは構造体の型を記憶して、引っ張り出してくるためのものみたいですね。
確かに、RBasicという元祖の構造体に定義してあるので、RBasicをメンバに持つ構造体は、RBasicのflagsにアクセスすれば、何の型なのかというのが一瞬でわかって便利ですね。

せっかくなので、マクロTYPEもちゃんと調べておきます。

### マクロTYPE

マクロTYPEはここに定義してありました。

```c:ruby-2.3.1/include/ruby/ruby.h-line_538
static inline int rb_type(VALUE obj);
#define TYPE(x) rb_type((VALUE)(x))
```
上のrb_typeの関数宣言文にある、`static inline`は、インライン関数というものらしいです。（初めて聞いた）

> 先頭に inline という言葉を付けて関数を宣言すると，コンパイラーはそれをヒントにコードをインライン化――関数のコードを呼出し元に展開する。これにより，関数呼び出しのオーバーヘッドが取り除かれ実行が早くなる。

> こちらに記載してありました。
http://d.hatena.ne.jp/wocota/20090219/1235058524

つまり、コンパイルするときに呼び出しに行くんじゃなくて、処理部分をここに書いちゃうよ！ってことみたいです。なるほど！

はい！じゃあ、処理部分を見に行きましょう。

```c:ruby-2.3.1/include/ruby/ruby.h--line_1952
static inline int
rb_type(VALUE obj)
{
    if (RB_IMMEDIATE_P(obj)) {
        if (RB_FIXNUM_P(obj)) return RUBY_T_FIXNUM;
        if (RB_FLONUM_P(obj)) return RUBY_T_FLOAT;
        if (obj == RUBY_Qtrue)  return RUBY_T_TRUE;
        if (RB_STATIC_SYM_P(obj)) return RUBY_T_SYMBOL;
        if (obj == RUBY_Qundef) return RUBY_T_UNDEF;
    }
    else if (!RTEST(obj)) {
        if (obj == RUBY_Qnil)   return RUBY_T_NIL;
        if (obj == RUBY_Qfalse) return RUBY_T_FALSE;
    }
    return RB_BUILTIN_TYPE(obj);
}
```

VALUE型のオブジェクトを渡すと、何やらT_〇〇というTYPEが返ってきそうな感じです。

### RB_IMMEDIATE_P(obj)

上から読んで行きましょう。まずは、`RB_IMMEDIATE_P(obj)`の条件分岐です。
こいつも、マクロみたいです。
ここにありました。

```c:ruby-2.3.1/include/ruby/ruby.h--line_393
#define RB_IMMEDIATE_P(x) ((VALUE)(x) & RUBY_IMMEDIATE_MASK)
```

ぐぬぬ、、、どういうことや

&ってアドレス演算子じゃないんか！って思って調べたら、ビット演算子っていうのが、あった。
まだまだ知らないことがいっぱいですね笑

&はビットANDっていう演算子らしく、左辺と右辺の同じ位置にあるビットだけ1に残す演算子みたい。if文の条件分岐なのに、true, falseとかじゃないんだね。

具体的には

```
0000000000000111  = 7
0000000000001110  = 14
----------------
0000000000000110  = 6
```

みたいな感じらしい。うおお。なんかPCっぽいと感動してます笑

### RUBY_IMMEDIATE_MASK

ほいでは、比較する左辺である`RUBY_IMMEDIATE_MASK`の調査を開始したいと思います。

これはすぐ近くにありました。

```c:ruby-2.3.1/include/ruby/ruby.h--line_427

/* special constants - i.e. non-zero and non-fixnum constants */
enum ruby_special_consts {
#if USE_FLONUM
    RUBY_Qfalse = 0x00,		/* ...0000 0000 */
    RUBY_Qtrue  = 0x14,		/* ...0001 0100 */
    RUBY_Qnil   = 0x08,		/* ...0000 1000 */
    RUBY_Qundef = 0x34,		/* ...0011 0100 */

    RUBY_IMMEDIATE_MASK = 0x07,
    RUBY_FIXNUM_FLAG    = 0x01,	/* ...xxxx xxx1 */
    RUBY_FLONUM_MASK    = 0x03,
    RUBY_FLONUM_FLAG    = 0x02,	/* ...xxxx xx10 */
    RUBY_SYMBOL_FLAG    = 0x0c,	/* ...0000 1100 */
#else
    RUBY_Qfalse = 0,		/* ...0000 0000 */
    RUBY_Qtrue  = 2,		/* ...0000 0010 */
    RUBY_Qnil   = 4,		/* ...0000 0100 */
    RUBY_Qundef = 6,		/* ...0000 0110 */

    RUBY_IMMEDIATE_MASK = 0x03,
    RUBY_FIXNUM_FLAG    = 0x01,	/* ...xxxx xxx1 */
    RUBY_FLONUM_MASK    = 0x00,	/* any values ANDed with FLONUM_MASK cannot be FLONUM_FLAG */
    RUBY_FLONUM_FLAG    = 0x02,
    RUBY_SYMBOL_FLAG    = 0x0e,	/* ...0000 1110 */
#endif
    RUBY_SPECIAL_SHIFT  = 8
};

```

ruby_special_constsと書かれるとちょっとテンションが上がりますね笑
rubyのスペシャルな定数とは一体！！！？

って、書いてありますよね。笑

non-zero and non-fixnum constants

0じゃなくて、fixnumじゃない定数のことみたいです。

さてさて、関係あるところだけを切り取って考えましょう。

```c:ruby-2.3.1/include/ruby/ruby.h--line_427
/* special constants - i.e. non-zero and non-fixnum constants */
enum ruby_special_consts {
#if USE_FLONUM
    RUBY_IMMEDIATE_MASK = 0x07,
#else
    RUBY_IMMEDIATE_MASK = 0x03,
#endif
    RUBY_SPECIAL_SHIFT  = 8
};

```

### USE_FLONUM

いちいちつまづく。本題には一体いつたどり着くのだろうか。。
でも、面白いからよしとします笑
`#if USE_FLONUM`について調べます。

```c:ruby-2.3.1/include/ruby/ruby.h--line_409
#ifndef USE_FLONUM
#if SIZEOF_VALUE >= SIZEOF_DOUBLE
#define USE_FLONUM 1
#else
#define USE_FLONUM 0
#endif
#endif
```

>  #ifndef は #ifdef の逆です。つまり #ifndef MACRONAME ～～ #endif とあったら、 MACRONAME が #define されてない時にかぎり、～～の部分をコンパイルするという事です。 
参考サイトhttp://www.geocities.co.jp/SiliconValley/6071/technic/16.html

とりあえず、USE_FLONUMが定義されてないとして、次に進みます。

次はここみたいです。深いなーw

```c:ruby-2.3.1/include/ruby/ruby.h--line_103
#if defined HAVE_UINTPTR_T && 0
typedef uintptr_t VALUE;
typedef uintptr_t ID;
# define SIGNED_VALUE intptr_t
# define SIZEOF_VALUE SIZEOF_UINTPTR_T
# undef PRI_VALUE_PREFIX
#elif SIZEOF_LONG == SIZEOF_VOIDP
typedef unsigned long VALUE;
typedef unsigned long ID;
# define SIGNED_VALUE long
# define SIZEOF_VALUE SIZEOF_LONG
# define PRI_VALUE_PREFIX "l"
#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
typedef unsigned LONG_LONG VALUE;
typedef unsigned LONG_LONG ID;
# define SIGNED_VALUE LONG_LONG
# define LONG_LONG_VALUE 1
# define SIZEOF_VALUE SIZEOF_LONG_LONG
# define PRI_VALUE_PREFIX PRI_LL_PREFIX
#else
# error ---->> ruby requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<----
#endif
```
さっきみたいに関係あるところだけ抜き出します。

```c:ruby-2.3.1/include/ruby/ruby.h--line_103
#if defined HAVE_UINTPTR_T && 0
    # define SIZEOF_VALUE SIZEOF_UINTPTR_T

#elif SIZEOF_LONG == SIZEOF_VOIDP
    # define SIZEOF_VALUE SIZEOF_LONG

#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
    # define SIZEOF_VALUE SIZEOF_LONG_LONG

#else
    # error ---->> ruby requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<----
#endif
```
まず最初の条件分岐は、HAVE_UINTPTR_Tが定義されていて、かつ、０だった時ということです。
grepして、HAVE_UINTPTR_Tを探してみると、

```
include/ruby/ruby.h:#if defined HAVE_UINTPTR_T && 0
win32/Makefile.sub:#define HAVE_UINTPTR_T 1
```
しか出てきませんでした。
つまり、windows32では1と定義されるので、とりあえずここは関係ないのかな？

>  #If 0ってC,C++では、#endifまで問答無用でコメントにします
http://blog.seasons.cc/entry/20090504/1241390314

って書いてありました。今回は、elifがあるので、そこまではコメントになっているということみたいです。
つまり、今は使われてない的なやつなのかなと推測しておきます。

次は、`if SIZEOF_LONG == SIZEOF_VOIDP`の部分です。

**SIZEOF_LONG**は結構遠いところにありました。

```c:ruby-2.3.1/fiddle/fiddle.c--line_377
rb_define_const(mFiddle, "SIZEOF_LONG",  INT2NUM(sizeof(long)));
```
ちなみに、fiddleはヴァイオリンとか詐欺とかいう意味です。なぜなんだろう…。。

rb_define_constは名前の通り、定数を定義するものっぽいですよね。

正解っぽいです

> void rb_define_const(VALUE klass, const char *name, VALUE val)
クラス klass の定数 name を初期値 val で 定義します。既に同名の定数が定義されていたら警告します。
http://docs.ruby-lang.org/ja/2.3.0/function/rb_define_const.html

つまり今回の場合、SIZEOF_LONGを呼び出すと、INT2NUM(sizeof(long))が呼び出されます。
sizeof(long)は、longのsizeを求める関数です。
INT2NUMは、INT型から、NUM型にキャストする関数です。

longは4byteのはずです。

### 一回復習

なので、SIZEOF_VOIDPがlongのサイズと同じであれば、SIZEOF_VALUEはlongのサイズとなります。
そして、SIZEOF_VALUEがlongのサイズとすると、SIZEOF_DOUBLEと比較できて、
SIZEOF_DOUBLEの方が小さければ、USE_FLONUMが1となり、
RUBY_IMMEDIATE_MASKは0x07となる。
で、0x07とobjとをビットANDして、
その解が真であれば、if文の中に入っていきます！

**では、SIZEOF_VOIDPを調べていきます。**

```c:ruby-2.3.1/fiddle/fiddle.c--line_353
rb_define_const(mFiddle, "SIZEOF_VOIDP", INT2NUM(sizeof(void*)));
```
さっきと同じで、void*のサイズをはかる関数のようです。
何やら、mFiddleは、サイズを測ったりするクラスのようです。また、SIZEOF_〇〇とは、〇〇のサイズを測ってINTからNUMに変換する関数のようです。なんとなくわかってきました。

ポインタは、型によらず4byteのようです。
http://rainbow.pc.uec.ac.jp/edu/program/b1/Ex4-1.htm

**よしきました！**

`# define SIZEOF_VALUE SIZEOF_LONG`が実行されます。
SIZEOF_VALUEは4byteになります。

### じゃあ、帰ってきてUSE_FLONUMの部分いきましょう

```c:ruby-2.3.1/include/ruby/ruby.h--line_409
#ifndef USE_FLONUM
#if SIZEOF_VALUE >= SIZEOF_DOUBLE
#define USE_FLONUM 1
#else
#define USE_FLONUM 0
#endif
#endif
```
4byteより、SIZEOF_DOUBLEが大きければ、USE_FLONUMが1となります。

SIZEOF_〇〇は、サイズをはかるやつです。

```c:ruby-2.3.1/fiddle/fiddle.c--line_397
rb_define_const(mFiddle, "SIZEOF_DOUBLE",INT2NUM(sizeof(double)));
```

doubleは8byteです。ですので、**USE_FLONUMは、0**となります。

### さっきのSIZEOF_VALUEの定義が間違ってました

 **やばい。SIZEOF_VALUE**の定義が間違っていることにここで気づきました。
doubleは8byteで固定なため、SIZEOF_VALUEが可変でないとおかしいはずです。

どこで間違ったのか

# 6月2日

jkr_2255さんのコメントで判明しました！（ありがとうございました！）

> 可搬性
Rubyはいろいろな環境でコンパイルできるように、型のサイズを決め打ちにしないようにしてあります。
Windows/Linux x86…ポインタもlongも32ビット
Windows x64…ポインタは64ビット、longは32ビット
Linux x64…ポインタもlongも64ビット
SIZEOF_XXXマクロは、これと似たような仕組みでソースコードの外から供給されますが、基本的には「sizeof(xxx)」の結果と同じ、と考えて問題ありません。
USE_FLONUMも、環境によって0か1かが決まってくるものなので、VALUEが32ビット、doubleが64ビットの環境では0になります。

ということだったので、longが4byte、ポインタも、型によらず4byteって決めつけていたのが間違いでした。

Windows/Linux x86の時は、longもポインタも32bitと同じなので、SIZEOF_VALUEはSIZEOF_LONGと同じと定義され、4byteです。x86のdoubleは8byteでした。（参考：http://d.hatena.ne.jp/bellbind/20081118/1227032924）
なので、`#if SIZEOF_VALUE >= SIZEOF_DOUBLE`は、falseが買えるので、USE_FLONUMは0になって、`RUBY_IMMEDIATE_MASK = 0x03`になります。
0x03は16進数で、10進数に直すと、3です。3は2進数に直すと`0011`です。

この`0011`とobjのVALUEをビットANDして、この先どおしたらええんや笑

`#define RB_IMMEDIATE_P(x) ((VALUE)(x) & RUBY_IMMEDIATE_MASK)`

IMMEDIATEは、”直接の、じかの、即座の、即時の、早速の、すぐ隣の、隣接した、当面の、目下の、ごく近い”って意味みたいです。
_Pは、

> ～pという名前はLisp由来の記法で、真偽値を返す手続きであること を示している。
http://i.loveruby.net/ja/rhg/book/object.html

ということです。

つまり、RB_IMMEDIATE_P(x)は、xが直に何かしてるかどうか？みたいなニュアンス？のようです。
惜しい感じ。

と、思って調べまくってたら、おおおおお！って感じで発見しました。

> 例えば、第 1 ビットに 1 が入っているとすると、第 1 ビットが立っているという言い方をします。ある数の第 1 ビットが立っているかどうかを調べる時、論理積 ( & ) 演算子を使います。
a = ある数 & 0X02;
上記の演算を行って a が 0 なら、第 1 ビットは立っていません。0 以外なら、第 1 ビットは立っています。
http://www1.cts.ne.jp/~clab/hsample/Bit/Bit2.html

つまり、`0011`の部分がかぶっていたらtrue！、
どこも被らずに0になったら、false!ということみたいです。

ここで、jkr_2255さんのコメントに書いてあった、

> ポインタの下位数ビットが0となるように配置されます。
Rubyではこれを利用して、最下位ビットが立っているものはFixnumとして扱います（参考）。また、4バイトアラインだと「4で割って2余る数」も有効なポインタとして使われないことになるので、ビット数が十分ある状況ならdoubleをシフトして、下位ビットを調整した上でVALUEに突っ込んでしまいます。

が活きてくるような気がします。
まず、Fixnumだったら、最下位ビットが必ず1が立つので、trueです。
中を見てましょう。

```c
if (RB_IMMEDIATE_P(obj)) {
  if (RB_FIXNUM_P(obj)) return RUBY_T_FIXNUM;
  if (RB_FLONUM_P(obj)) return RUBY_T_FLOAT;
  if (obj == RUBY_Qtrue)  return RUBY_T_TRUE;
  if (RB_STATIC_SYM_P(obj)) return RUBY_T_SYMBOL;
  if (obj == RUBY_Qundef) return RUBY_T_UNDEF;
}
```

どうやら正解みたいです！
`if (RB_FIXNUM_P(obj)) return RUBY_T_FIXNUM;`があるので、objがFIXNUMの場合、RUBY_T_FIXNUMが返るみたいです。

やりました！

一応、RB_FIXNUM_P(obj)と、RUBY_T_FIXNUMについても勉強しておきます。

### RB_FIXNUM_P

```c:ruby-2.3.1/include/ruby/ruby.h--line_382
#define RB_FIXNUM_P(f) (((int)(SIGNED_VALUE)(f))&RUBY_FIXNUM_FLAG)
```
RUBY_FIXNUM_FLAGは実は、ruby_special_constsの部分で定義していました。
`RUBY_FIXNUM_FLAG    = 0x01`です。２進数だと、`0001`なので
最下位ビットのみが立っていれば、FIXNUMということになります。

### RUBY_T_FIXNUM

```c:ruby-2.3.1/include/ruby/ruby.h--line_472
enum ruby_value_type {
    RUBY_T_NONE   = 0x00,

    RUBY_T_OBJECT = 0x01,
    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,
    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,
    RUBY_T_NODE   = 0x1b,
    RUBY_T_ICLASS = 0x1c,
    RUBY_T_ZOMBIE = 0x1d,

    RUBY_T_MASK   = 0x1f
};

```
TYPEは472行めでたくさん定義してありました。
RUBY_T_FIXNUM = 0x15です。

いやあ、長かったですね。一応、TYPEのゴールに行き着きました。
ついでに、`0011`でビットANDで真になる他のものを調べてみましょう。

```
0001(FIXNUM)
0010
0101
0110
0111
1001
1010
1011
1101
1110
1111
```
が、真になるものとなる気がします。

```c
if (RB_IMMEDIATE_P(obj)) {
  if (RB_FIXNUM_P(obj)) return RUBY_T_FIXNUM;
  if (RB_FLONUM_P(obj)) return RUBY_T_FLOAT;
  if (obj == RUBY_Qtrue)  return RUBY_T_TRUE;
  if (RB_STATIC_SYM_P(obj)) return RUBY_T_SYMBOL;
  if (obj == RUBY_Qundef) return RUBY_T_UNDEF;
}
```

で、おそらく、このCodeのFIXNUMの下にあるものが、上記の形で表現されているはずです。
調べてあっていたら、理解が正しいということになります。

じゃあ、調べます。

### FLONUM

FLONUMどこかで見たぞと思ったけど、USE_FLONUMをさっき定義したところでした。
先ほどは、USE_FLONUMが0になりましたので、今回は使用しないのでスルーします。

### RUBY_Qtrue

RUBY_Qtrueも実は、先ほどのruby_special_constsで定義してあります。
`RUBY_Qtrue  = 2,        /* ...0000 0010 */`
こう定義されていました。

狙いどうりでしたね！

```
0001(FIXNUM)
0010（Qtrue）
0101
0110
0111
1001
1010
1011
1101
1110
1111
```

### RUBY_T_SYMBOL

これも、おそらく`RUBY_SYMBOL_FLAG    = 0x0e, /* ...0000 1110 */`の部分と思います。
これも正解みたいです。

```
0001(FIXNUM)
0010（Qtrue）
0101
0110
0111
1001
1010
1011
1101
1110(SYMBOL_FLAG)
1111
```

### RUBY_Qundef

ラストー！！！
RUBY_Qundef

`RUBY_Qundef = 6,        /* ...0000 0110 */`

これもこのように定義されていました。
これもビンゴです！

```
0001(FIXNUM)
0010（Qtrue）
0101
0110(Qundef)
0111
1001
1010
1011
1101
1110(SYMBOL_FLAG)
1111
```

ちなみにQundefはこんな感じのものです

> st_delete と似ているが、その場ですぐに削除するのではなく never を
書きこんでおく。st_cleanup_safe() で本当に削除できる。
Ruby では never には Qundef を使う。
http://docs.ruby-lang.org/ja/search/query:st_delete/version:1.8.7/

論理削除に使う型なのかなと推測しておきます。

###  #define RB_IMMEDIATE_P(x) ((VALUE)(x) & RUBY_IMMEDIATE_MASK)

つまり、RB_IMMEDIATE_P(x) は

- FIXNUM
- Qtrue
- SYMBOL_FLAG
- Qundef（never）

の時のみtrueになる関数みたいです。 


今日も少しですが進みました。
また明日これたらいいなー笑

2016/06/02/03:12

-------------------------

# 6月3日

今日は始めるのが遅かったので、ちょっとだけ進めます。
昨日のことで間違ってることが少しありました。

```
0001(FIXNUM)
0010
0101
0110
0111
1001
1010
1011
1101
1110
1111
```
が、真になるものとなる気がします。

と、このように記述したのですが、冷静に最下位ビットが1のものはFIXNUMとなるので、正しくは

```
0001(FIXNUM)
0010
0110
1010
1110
```

となるはずでした。
これに、他の調査した型を当てはめると

```
0001(FIXNUM)
0010（Qtrue）
0110(Qundef)
1010
1110(SYMBOL_FLAG)
```

と、このようにピッタリ当てはまります。今日の朝ハッ！っと気づいて、少し嬉しかったです。笑
1010は一体何なのかもきになるところですね。気になって、grepをかけてみたのですが、1010ではhitしませんでした。
1010は、16進数だと0x10なのでこちらで検索してみたら
`dir.c:#define FNM_EXTGLOB       0x10`
とかが出てきました、、が、あっているかどうかはイマイチわかりません。またわかったら記述します。

ではでは、次に進みます。

```c:ruby-2.3.1/include/ruby/ruby.h--line_1952
static inline int
rb_type(VALUE obj)
{
    if (RB_IMMEDIATE_P(obj)) {
        if (RB_FIXNUM_P(obj)) return RUBY_T_FIXNUM;
        if (RB_FLONUM_P(obj)) return RUBY_T_FLOAT;
        if (obj == RUBY_Qtrue)  return RUBY_T_TRUE;
        if (RB_STATIC_SYM_P(obj)) return RUBY_T_SYMBOL;
        if (obj == RUBY_Qundef) return RUBY_T_UNDEF;
    }

↑ここまでは理解
------------------------------------

    else if (!RTEST(obj)) {
        if (obj == RUBY_Qnil)   return RUBY_T_NIL;
        if (obj == RUBY_Qfalse) return RUBY_T_FALSE;
    }
    return RB_BUILTIN_TYPE(obj);
}
```

### if (!RTEST(obj))

というわけで、次は`if (!RTEST(obj))`の部分ですね。
こちらは、ruby.hの467行めにありました。

```c:ruby-2.3.1/include/ruby/ruby.h--line_467
#define RTEST(v) !(((VALUE)(v) & ~Qnil) == 0)
```
vと~QnilのビットANDが0でない時、真って感じですね。
今回の、条件分岐には、!が付いているので、逆でvと~QnilのビットANDが0の時、中に入っていくことになります。

では、~Qnilがどういう意味なのか確認しましょう。
まず、~が何を意味しているのかがわかりません。

> C言語やC++言語では、NOT演算子は "~" （チルダ）である。
https://ja.wikipedia.org/wiki/%E3%83%93%E3%83%83%E3%83%88%E6%BC%94%E7%AE%97

なるほど、Qnilのbitが反転するわけですね。
Qnilのbitが反転して、ビットANDして、0になるということは、Qnilのbitと一致しているということになるので
処理部分に入って行って、return Nilされるということですね。なるほど。

では、実際にQnilのbitを確認してみます。

`RUBY_Qnil   = 4,		/* ...0000 0100 */`

つまり、NOT演算子（チルダ）で反転すると

`1111 1011`となるわけです。これとビットANDして0ということは
`0000 0100`であるわけですから、Qnilで問題ありません。

ここで、問題になるのは、`RUBY_Qfalse`ですよね。
こちらについても調べてみましょう。

`RUBY_Qfalse = 0,		/* ...0000 0000 */`

こう書いてありました。これは盲点でした。
全部、0だったらビットANDシテモ、絶対0になりますよね。

これで、長かったTYPE()関数ともお別れです。

### 最後は　RB_BUILTIN_TYPE(obj);

`return RB_BUILTIN_TYPE(obj);`

とりあえず、いつも通り調べてみましょう。
ruby.hの534行めにありました。

```c:ruby-2.3.1/include/ruby/ruby.h--line_534
#define RB_BUILTIN_TYPE(x) (int)(((struct RBasic*)(x))->flags & RUBY_T_MASK)
```
きたー！RBasicのflagsの勉強とビットANDが繋がりました。
今までの努力が身を結びました。

すべてのオブジェクトが持つ構造体である、RBasicのflagsにアクセスして、RUBY_T_MASKとビットANDするわけです。
それで、TYPEがわかるIntを返すと。

ちなみに、RUBY_T_MASKは
`RUBY_T_MASK   = 0x1f`と先ほど定義されていました。

0x1fとは31のことで2進数で表すと
`0001 1111`のことです。

戻り値であるIntからTYPEを判明するのは、ruby_value_typeを調べればいけそうな予感です。

長かった、、、、笑
これでようやっと、flagsの使い方と必要性が理解できました。

今日はこれくらいにしておきます笑
明日は、flagsの代入部分と、klassについての勉強をしていこうと思いやす。

2016/06/03/03:57

-------------------------

# 6月4日

さて、今日はflagsの代入部分とklassについて勉強していきます。
とりあえず、flagsの代入部分を探しましょう。

### flagsの代入部分

おそらく、何かのインスタンスを作成するときにflagsが設定されるはずなので、
今回は、この関数について追っていこうと思います。

`rb_str_new(); `

これはstring.cにありました。やっと、headerファイルから抜けました笑

```c:ruby-2.3.1/string.c--line_640
static VALUE
str_new0(VALUE klass, const char *ptr, long len, int termlen)
{
    VALUE str;

    if (len < 0) {
	rb_raise(rb_eArgError, "negative string size (or size too big)");
    }

    RUBY_DTRACE_CREATE_HOOK(STRING, len);

    str = str_alloc(klass);
    if (len > RSTRING_EMBED_LEN_MAX) {
	RSTRING(str)->as.heap.aux.capa = len;
	RSTRING(str)->as.heap.ptr = ALLOC_N(char, len + termlen);
	STR_SET_NOEMBED(str);
    }
    else if (len == 0) {
	ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT);
    }
    if (ptr) {
	memcpy(RSTRING_PTR(str), ptr, len);
    }
    STR_SET_LEN(str, len);
    TERM_FILL(RSTRING_PTR(str) + len, termlen);
    return str;
}

static VALUE
str_new(VALUE klass, const char *ptr, long len)
{
    return str_new0(klass, ptr, len, 1);
}

VALUE
rb_str_new(const char *ptr, long len)
{
    return str_new(rb_cString, ptr, len);
}
```
rb_cString以外のklassが入ることもあるみたいね。
ちなみに、rb_cStringはここで定義されています。

```c:ruby-2.3.1/string.c--line_９３８７
rb_cString  = rb_define_class("String", rb_cObject);
```

せっかくなので、rb_define_classもみておきましょう。
と、思ったのですが、また長くなりそうな雰囲気のあるコードが出てきたので
なので、一旦flagsの代入部分を済ませてから帰ってこようと思います。

とりあえず、コードの流れ的には、
rb_str_new → str_new → str_new0の順番で呼ばれます。
rb_str_newから、rb_cStringをstr_newに渡します。で、そのままstr_new0に渡します。

**str_newがある意味ってなんなんだろうか**ともちょっと思いました笑

では、str_new0のメソッドを見ていきます。
まず最初に文字列の長さチェックがあるみたいです。

```c
if (len < 0) {
	rb_raise(rb_eArgError, "negative string size (or size too big)");
    }
```

lenが0以下であれば、rb_raise、rb_eArgErrorの例外処理が発生します。
後で、rb_raiseの方も見ていきましょう！
でも、とりあえず今は本筋を進めていきます。

例外処理を超えると、`RUBY_DTRACE_CREATE_HOOK(STRING, len);`が表れます。
なんだこれはということで調べます。


```c:ruby-2.3.1/include/ruby/ruby.h
#define RUBY_DTRACE_CREATE_HOOK(name, arg) \
    RUBY_DTRACE_HOOK(name##_CREATE, arg)
#define RUBY_DTRACE_HOOK(name, arg) \
do { \
    if (UNLIKELY(RUBY_DTRACE_##name##_ENABLED())) { \
	int dtrace_line; \
	const char *dtrace_file = rb_source_loc(&dtrace_line); \
	if (!dtrace_file) dtrace_file = ""; \
	RUBY_DTRACE_##name(arg, dtrace_file, dtrace_line); \
    } \
} while (0)
```

コード中に出てくるバックスラッシュはなんだ、一行のコードを改行するやつかな？




### rb_raise



### rb_define_class

```c:ruby-2.3.1/class.c--line_642
VALUE
rb_define_class(const char *name, VALUE super)
{
    VALUE klass;
    ID id;

    id = rb_intern(name);
    if (rb_const_defined(rb_cObject, id)) {
	klass = rb_const_get(rb_cObject, id);
	if (!RB_TYPE_P(klass, T_CLASS)) {
	    rb_raise(rb_eTypeError, "%s is not a class (%"PRIsVALUE")",
		     name, rb_obj_class(klass));
	}
	if (rb_class_real(RCLASS_SUPER(klass)) != super) {
	    rb_raise(rb_eTypeError, "superclass mismatch for class %s", name);
	}
	return klass;
    }
    if (!super) {
	rb_warn("no super class for `%s', Object assumed", name);
    }
    klass = rb_define_class_id(id, super);
    rb_vm_add_root_module(id, klass);
    rb_name_class(klass, id);
    rb_const_set(rb_cObject, id, klass);
    rb_class_inherited(super, klass);

    return klass;
}

```



-------------------------

ちなみに、macがどんなbitかわからなかったので、調べてみたら

```c
#include<stdio.h>
int main() {
  printf("long_size is %lu byte\npointer_size is %lu byte\n", sizeof(long), sizeof(void*));
  return 0;
}
```
long_size is 8 byte
pointer_size is 8 byte

とのように出たので、longもpointerも64bitなので、Linux x64と同じ状態です。


----------------------------

## union(struct{long numiv, VALUE *ivptr, void *iv_index_tbl})

## VALUE ary[ROBJECT_EMBED_LEN_MAX];

## いつもお世話になっています

Rubyソースコード完全解説
http://i.loveruby.net/ja/rhg/book/


```c:ruby-2.3.1/include/ruby/ruby.h
```