iv の格納ら辺まとめ
インスタンス変数は,先頭に"@"(アットマーク)が付いている
インスタンススコープの変数.
例えば,こんな感じ.
irb(main):001:0> a = 1 => 1 irb(main):002:0> class Fixnum irb(main):003:1> def hoge; @hoge; end irb(main):004:1> def hoge=(hoge); @hoge = hoge; end irb(main):005:1> end => nil irb(main):006:0> a.hoge => nil irb(main):007:0> a.hoge = "fuga" => "fuga" irb(main):008:0> a.hoge => "fuga"
準備
関数 | rb_obj_class(obj) | ROBJECT(obj)->basic->klass |
マクロ | ROBJECT_IV_INDEX_TBL(obj) | ROBJECT(obj)->iv_index_tbl EMBED の場合は,RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) |
マクロ | RCLASS_IV_INDEX_TBL(klass) | RCLASS(klass)->iv_index_tbl |
関数 | st_lookup(st_table, key, *value) | key のindex をiv_index_tbl から探す |
マクロ | ROJBECT_NUMIV(obj) | ROBJECT(obj)->as.heap.numiv 今入るIV の最大値を返す |
マクロ | ROBJECT_IVPTR(obj) | ROBJECT(obj)->as.heap.ivptr IV のテーブル |
値 | ROBJECT_EMBED | RObject.ary に埋め込むというフラグ |
値 | ROBJECT_EMBED_LEN_MAX | RObject.ary に入れる最大値 |
変数 | generic_iv_tbl | obj -> tbl(symbol と値のテーブル)を保持するテーブル |
マクロ | RCLASS_IV_TBL | RCLASS(c)->ptr->iv_tbl |
variable.c:1005:rb_ivar_set() を見るとわかるらしい.
最初のif は例外処理なので飛ばして,
switch で,TYPE(obj) にて分岐してる.
- 1016:T_OBJECT
- 1066-1067:T_CLASS or T_MODULE
- 1071:default
(VALUE埋め込みオブジェクトでない)オブジェクトの場合
- iv_index_tbl (iv のsymbol と位置を関係付けるテーブル)を取得する
- 無かったらclass 上に作る
- iv_index_tbl の中に今回のid がsymbol としてあるかどうか探す
- 無かったら追加
- index(保持する値の位置) が決定する
- ivar_extended(新しいsymbol) かどうかのフラグ
- len(今保持しているIV の最大値)を取得
- 保持する位置がlen 以上ならば
- ptr (値を保持する配列) を取得
- len <= index < ROBJECT_EMBED_LEN_MAX ならば埋め込みにする*1
- new_size((index+1)*1.25) と num_entries(現在のサイズ) からptr を決定する
- 値を保持する
クラス(モジュール)の場合
- RCLASS_IV_TBL(obj) を見て,値を保持する
その他
- generic_ivar_set(obj, id, val) する
もうちょっと言うと,
- *iv_tbl は,key(symbol), value で値を保持する(RClass とか その他の場合)
- RObject は,RObject.as.ary or RObject.as.heap の形態がある(union)
- RBASIC(o)->flags & ROBJECT_EMBD の場合
- 値は ROBJECT(o)->as.ary
- key(symbol) => index のテーブルは,RCLASS_IV_INDEX_TBL(rb_obj_class(o)) -> これは,大体 RBASIC(o)->klass->iv_index_tbl
- そうでなければ
- 値は,ROBJECT(o)->as.heap.ivptr
- key(symbol) => index のテーブルは,ROBJECT(o)->as.heap.iv_index_tbl
- RBASIC(o)->flags & ROBJECT_EMBD の場合
- ROBJECT_EMBD になる境目は,ROBJECT_EMBED_LEN_MAX 個(=3)
egrep -n -B1 -A71 \^rb_ivar_set *.c variable.c-1004-VALUE variable.c:1005:rb_ivar_set(VALUE obj, ID id, VALUE val) variable.c-1006-{ variable.c-1007- struct st_table *iv_index_tbl; variable.c-1008- st_data_t index; variable.c-1009- long i, len; variable.c-1010- int ivar_extended; variable.c-1011- variable.c-1012- if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4) variable.c-1013- rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable"); variable.c-1014- if (OBJ_FROZEN(obj)) rb_error_frozen("object"); variable.c-1015- switch (TYPE(obj)) { variable.c-1016- case T_OBJECT: variable.c-1017- iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); variable.c-1018- if (!iv_index_tbl) { variable.c-1019- VALUE klass = rb_obj_class(obj); variable.c-1020- iv_index_tbl = RCLASS_IV_INDEX_TBL(klass); variable.c-1021- if (!iv_index_tbl) { variable.c-1022- iv_index_tbl = RCLASS_IV_INDEX_TBL(klass) = st_init_numtable(); variable.c-1023- } variable.c-1024- } variable.c-1025- ivar_extended = 0; variable.c-1026- if (!st_lookup(iv_index_tbl, id, &index)) { variable.c-1027- index = iv_index_tbl->num_entries; variable.c-1028- st_add_direct(iv_index_tbl, id, index); variable.c-1029- ivar_extended = 1; variable.c-1030- } variable.c-1031- len = ROBJECT_NUMIV(obj); variable.c-1032- if (len <= index) { variable.c-1033- VALUE *ptr = ROBJECT_IVPTR(obj); variable.c-1034- if (index < ROBJECT_EMBED_LEN_MAX) { variable.c-1035- RBASIC(obj)->flags |= ROBJECT_EMBED; variable.c-1036- ptr = ROBJECT(obj)->as.ary; variable.c-1037- for (i = 0; i < ROBJECT_EMBED_LEN_MAX; i++) { variable.c-1038- ptr[i] = Qundef; variable.c-1039- } variable.c-1040- } variable.c-1041- else { variable.c-1042- VALUE *newptr; variable.c-1043- long newsize = (index+1) + (index+1)/4; /* (index+1)*1.25 */ variable.c-1044- if (!ivar_extended && variable.c-1045- iv_index_tbl->num_entries < newsize) { variable.c-1046- newsize = iv_index_tbl->num_entries; variable.c-1047- } variable.c-1048- if (RBASIC(obj)->flags & ROBJECT_EMBED) { variable.c-1049- newptr = ALLOC_N(VALUE, newsize); variable.c-1050- MEMCPY(newptr, ptr, VALUE, len); variable.c-1051- RBASIC(obj)->flags &= ~ROBJECT_EMBED; variable.c-1052- ROBJECT(obj)->as.heap.ivptr = newptr; variable.c-1053- } variable.c-1054- else { variable.c-1055- REALLOC_N(ROBJECT(obj)->as.heap.ivptr, VALUE, newsize); variable.c-1056- newptr = ROBJECT(obj)->as.heap.ivptr; variable.c-1057- } variable.c-1058- for (; len < newsize; len++) variable.c-1059- newptr[len] = Qundef; variable.c-1060- ROBJECT(obj)->as.heap.numiv = newsize; variable.c-1061- ROBJECT(obj)->as.heap.iv_index_tbl = iv_index_tbl; variable.c-1062- } variable.c-1063- } variable.c-1064- ROBJECT_IVPTR(obj)[index] = val; variable.c-1065- break; variable.c-1066- case T_CLASS: variable.c-1067- case T_MODULE: variable.c-1068- if (!RCLASS_IV_TBL(obj)) RCLASS_IV_TBL(obj) = st_init_numtable(); variable.c-1069- st_insert(RCLASS_IV_TBL(obj), id, val); variable.c-1070- break; variable.c-1071- default: variable.c-1072- generic_ivar_set(obj, id, val); variable.c-1073- break; variable.c-1074- } variable.c-1075- return val; variable.c-1076-}
*1:これは,埋め込みでなくなるときにしか起きない