RHGの逆襲第2回に参加します

ちょっと、予習が不十分ですが、参加してきます。

いかに、予習した分の簡単なまとめをさらしておきます。

st_tableのメンバが変化している

- ruby 1.8
struct st_table {
    struct st_hash_type *type;
    int num_bins;
    int num_entries;
    struct st_table_entry **bins;
};
- ruby 1.9
struct st_table {
     const struct st_hash_type *type;
     st_index_t num_bins;
     unsigned int entries_packed : 1;
     st_index_t num_entries : ST_INDEX_BITS - 1;
     struct st_table_entry **bins;
     struct st_table_entry *head;
 };

変更があったのは、num_bins,num_entriesがst_index_t の変数になり(num_entriesはLONGLONG
のサイズ*8(char のbitサイズから1を引いたビット数のサイズ IA-32なら511)、int entries_packed :1 と
st_table_entry *headが追加されている。
st_hash_typeには変更無し。

st_lookup 引数である、keyとvalがchar*からst_data_t(long)に変更されている
tableのentries_packedが1のとき、0<=i FIND_ENTRYの流れ。

st_add_directの引数も、st_lookupと同様に変更されている。
流れも、table->entries_packedにbitがたっていないと1.8のころと同様の処理。
bitが立っている場合は、
tableに登録されている要素数(table->num_entries)+1*2がtableのサイズ(table->num_bins)を超えておらず、
かつ、table->num_entries+1が<=MAX_PACKED_NUMHASH(5)のときは、
table->num_entriesをインクリメントし、table->num_entries*2の位置にkeyをkey+1の位置にvalを登録する。
そうでない場合は、unpack_entries()を呼ぶ。
unpack_entriesでは、MAX_PACKED_NUMHASH*2のサイズのst_table_entryの配列を用意し、
table->binesをコピー。table->entries_packed,table->num_entries,table->binsを0に初期化。
そして、コピーしておいたst_table_entryの配列を使い、st_insert呼び、
tableに今までのkeyとvalを登録していく。
ADD_DIRECTマクロが1.8から変更されている。
hashが登録順を保持するようになったためだと思われる。 (参考:http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/43887)
st_table_entryはlinked_listからdouble_link_list構造になった。
tableが空でない場合には、headの直後に追加をする。
空の場合は、先頭に追加。
st_insert()も同様に、table->entries_packedで分岐する。
処理内容は、どちらも登録されているか確認->されていれば書き換え1を、されていなければ挿入し0を返す。

rb_intern() は、rb_intern()->rb_intern2()->rb_intern3の流れになる。
rb_intern2を呼ぶ際に、rb_internの引数のstrlenを渡す。rb_intern3のときは、さらにrb_enc_from_indexを引数0で
呼んでいる。返り値は0になるのだがenc_tableが初期化されていない場合に初期化する副作用を狙っていると思われる
rb_intern3()では、引数よりRStringのオブジェクトを作り、rb_enc_associate(str,enc)でエンコードを設定する。
作成したオブジェクトがglobal_symbols.sym_idに登録されていた場合、そのidを返す。