Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rubyのobject_id

 Rubyのobject_id

Rubyのobject_idを入口にして、Rubyの実装詳細について学びます。

Masaki Hara

August 28, 2024
Tweet

More Decks by Masaki Hara

Other Decks in Programming

Transcript

  1. © 2024 Wantedly, Inc. Quiz 1 p 1.object_id == 1.object_id

    p "foo".object_id == "foo".object_id p [].object_id == [].object_id
  2. © 2024 Wantedly, Inc. Quiz 1 p 1.object_id == 1.object_id

    # => true p "foo".object_id == "foo".object_id # => frozen_string_literal に依存 p [].object_id == [].object_id # => false とは断言できない
  3. © 2024 Wantedly, Inc. object_id • オブジェクトの同一性をあらわす整数 ◦ Kernel#object_id または

    BasicObject#__id__ • #equal? と同等 ◦ a.equal?(b) ⇔ a.__id__ == b.__id__
  4. © 2024 Wantedly, Inc. object_idの永続性 [1, :RUBY_EVENT_LINE, [:newarray, 0], [:opt_send_without_block,

    {:mid=>:object_id, :flag=>16, :orig_argc=>0}], [:newarray, 0], [:opt_send_without_block, {:mid=>:object_id, :flag=>16, :orig_argc=>0}], [:opt_eq, {:mid=>:==, :flag=>16, :orig_argc=>1}], [:leave]]
  5. © 2024 Wantedly, Inc. object_idの永続性 [1, :RUBY_EVENT_LINE, [:newarray, 0], [:opt_send_without_block,

    {:mid=>:object_id, :flag=>16, :orig_argc=>0}], [:newarray, 0], [:opt_send_without_block, {:mid=>:object_id, :flag=>16, :orig_argc=>0}], [:opt_eq, {:mid=>:==, :flag=>16, :orig_argc=>1}], [:leave]] stack = [] stack = [[]] stack = [oid1] stack = [oid1, []] stack = [oid1, oid2] stack = [false]
  6. © 2024 Wantedly, Inc. Quiz 2 p false.object_id p 100.object_id

    p 10000000000.object_id ※CRubyの場合
  7. © 2024 Wantedly, Inc. Quiz 2 p false.object_id # =>

    0 p 100.object_id # => 201 p 10000000000.object_id # => 32bit環境と64bit環境で異なる ※CRubyの場合
  8. © 2024 Wantedly, Inc. 特別な値 • false, true, nil, および小さい整数値は特別なobject_id値

    をもつ (即値) ◦ 短い整数値はFixnumとも呼ばれる • 小さい整数値の上限は32bit環境と64bit環境で異なる ◦ 32bitなら −230 ≤ n < 230, 64bitなら −262 ≤ n < 262
  9. © 2024 Wantedly, Inc. Quiz 3 p [].object_id - [].object_id

    # => -8 (Ruby >= 3.4.0) # => -20 (Ruby >= 2.7.0) # => 20 (Ruby < 2.7.0) # ※GCの挙動に依存、64bit環境の例 ※CRubyの一般的な結果
  10. © 2024 Wantedly, Inc. 人工的なオブジェクトID • Ruby 2.7より前: オブジェクトID =

    アドレス÷2 ◦ GCの挙動に依存するが、降順に割り当てられるため正の値が出ることが多い ◦ 20 は64bit環境における sizeof(RVALUE) / 2 • Ruby 2.7以降: オブジェクトID = カウンタの値 ◦ コンパクションが実装されたため、アドレスが安定的に使えない ◦ かわりにカウンタの値を払い出して使っている ◦ sizeof(RVALUE) の倍数になるよう工夫されている (3.3以前はその半分) ◦ そのため、object_id を呼んだ順に依存して安定的に 8ずつ増える (3.3以前は20ずつ)
  11. © 2024 Wantedly, Inc. Quiz 4 p :foo.object_id # =>

    12280076 (一例) p "bar".to_sym.object_id # => 8 (一例) ※CRubyの一般的な結果
  12. © 2024 Wantedly, Inc. シンボルGC • 静的シンボル: GCされない。IDは 256n +

    12 ◦ :foo など静的な構文によって生成されるとこの形になる ◦ Ruby 3.3 以前は別仕様 • 動的シンボル: GCされる。IDは 40n ◦ 一般のオブジェクトと同じ扱い ◦ 40 は 64bit環境における sizeof(RVALUE) ◦ String#to_sym など動的な処理で生成されるとこの形になる ◦ すでに静的シンボルが生成されていればそちらが使われる (逆も然り)
  13. © 2024 Wantedly, Inc. ID • ID: Symbolの内部表現 ◦ rb_sym2id,

    rb_id2sym ◦ sym.object_id / 256 (Ruby 3.4〜, 静的シンボルの場合) ◦ sym.object_id / 20 (Ruby 〜3.3) • VALUE表現ともobject_idとも異なる
  14. © 2024 Wantedly, Inc. ID IDのフラグ 形式 ID (動的) ID

    (静的) 例 ローカル 16n + 0 16n + 1 :foo インスタンス 16n + 2 16n + 3 :@foo – 16n + 4 16n + 5 – グローバル 16n + 6 16n + 7 :$foo 形式 ID (動的) ID (静的) 例 セッター 16n + 8 16n + 9 :foo= 定数 16n + 10 16n + 11 :Foo クラス変数 16n + 12 16n + 13 :@@foo その他 16n + 14 16n + 15 :")(" ※演算子類は上の形式によらず、 ASCII符号値または128〜150の値が割り当てられる
  15. © 2024 Wantedly, Inc. Quiz 5 p 0.0.object_id # =>

    -9223372036854775806 p (-0.0).object_id # => 8 (一例) ※CRubyの場合
  16. © 2024 Wantedly, Inc. Flonum • Ruby 2.0以降では、64bit環境でFlonumが有効 • Flonum:

    特定範囲の浮動小数点数を即値で表現 ◦ 10-77 〜 1077 に限定すれば62bitで済む ◦ 使う機会の多い +0 は例外的に追加の即値として表現
  17. © 2024 Wantedly, Inc. Flonum 0000 0001 0010 0011 0100

    0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 オブジェクト 1…010 0…010 オブジェクト 1…110 0…110 オブジェクト +0 1.73 × 10-77 2.32 × 1077 +∞, NaN -0 -1.73 × 10-77 -2.32 × 1077 -∞, NaN 0
  18. © 2024 Wantedly, Inc. 64bit (Ruby 3.4-nightly-20240718) *1 *10 Fixnum

    (63bit) VALUE = 2n + 1 object_id = 2n + 1 Flonum (62bit) VALUE = 4n + 2 object_id = 4n + 2 *100 *000 Static Symbol 4 20 nil true 36 undef General Object 0 false
  19. © 2024 Wantedly, Inc. 64bit (Ruby 3.4-nightly-20240718) *1 *10 Fixnum

    (63bit) VALUE = 2n + 1 object_id = 2n + 1 Flonum (62bit) VALUE = 4n + 2 object_id = 4n + 2 *100 *000 Static Symbol 4 20 nil true 36 undef General Object 0 false VALUE = 256n + 12 object_id = 256n + 12 (nは奇数) VALUE = 8n object_id = 8k
  20. © 2024 Wantedly, Inc. 32bit (Ruby 3.4-nightly-20240718) *1 *10 Fixnum

    (31bit) VALUE = 2n + 1 object_id = 2n + 1 2 6 nil true 10 undef General Object 0 false *00 Static Symbol VALUE = 4n object_id = 4k VALUE = 256n + 14 object_id = 256n + 14 (nは奇数)
  21. © 2024 Wantedly, Inc. まとめ • #object_id は内部表現 (VALUE) をそのまま返しているわ

    けではない • とはいえ、Ruby 3.4では即値はそのまま返される • 小さいInteger, 妥当な範囲のFloat, 静的なSymbolは即値 で表現される • Ruby 2.7以降ではobject_idは再利用されない
  22. © 2024 Wantedly, Inc. JRuby JRubyにおける VALUE • Ruby ObjectをJavaのObjectとして表現

    ◦ Rubyの整数なども内部的にはJavaのObjectになる • JRubyからはJavaのObject IDは見えない ◦ System.identityHashCode がそれに近いが、32bitしかないので厳密な一意性は望 めない • したがって、VALUE相当の表現はないと言える
  23. © 2024 Wantedly, Inc. JRuby JRubyにおける object_id (v9.4.8.0 時点) •

    即値の処理は64bit環境のRuby 3.1.0を再現 ◦ Ruby 3.2での変更にはまだ追従していない • ObjectとSymbolにはカウンタを4倍した値を使用 ◦ Symbol専用の即値形式はなく、単なる interned Objectとして扱われる 関連するソース: • RubyKernel.object_id • IRubyObject.id ◦ RubyBasicObject.id, RubyBasicObject.getObjectId ◦ RubyBoolean.id ◦ RubyFixnum.id ◦ RubyFloat.id ◦ RubyNil.id
  24. © 2024 Wantedly, Inc. mruby • mrubyは多様な環境で動くことを想定しているため、各環境 に適した動作ができるようになっている ◦ ポインタサイズ、整数サイズ

    ◦ boxing mode (後述) ◦ Floatの有無 • 環境によっては整数のビット数不足により object_id のユ ニーク性を担保できない ◦ 整数のビット数が十分な場合でも、 object_idのユニーク性については現時点であまり 考慮されていない
  25. © 2024 Wantedly, Inc. boxing mode mrubyは3つのうちのいずれかのモードで動作する: • Unboxed (No

    Boxing) ◦ 2ワード利用するシンプルな表現 • Word Boxing ◦ CRubyと似たアプローチ • NaN Boxing ◦ JavaScript処理系でよく使われるアプローチ rake MRUBY_CONFIG=build_config/boxing.rb でビルドしてテストできる
  26. © 2024 Wantedly, Inc. Unboxed • UnboxedのVALUE表現 ◦ 型タグ +

    整数 または ◦ 型タグ + ポインタ ◦ nilはfalseと同じ型タグを持ち、整数部分で区別 • Unboxedのobject_id (3.3.0時点) ◦ 型タグと値(整数またはポインタ)のXOR ◦ 容易にコンフリクトする (たとえば nil.object_id == 2.object_id)
  27. © 2024 Wantedly, Inc. Word Boxing • Word BoxingのVALUE表現 (3.3.0時点)

    ◦ nil = 0, false = 4, true = 12, undef = 20 (nilが0になる点が特徴的!) ◦ Fixnum = 2n + 1 ◦ Float = 4n + 2 (Floatの切り捨て許可の場合) ▪ CRubyのFlonumとは異なる表現である点に注意 ◦ Symbol = 4n + 2 (Floatの切り捨て禁止の場合), 232n + 28 (64bitの場合), 32n + 28 (32bitの場合) ◦ その他 = struct RBasic* のポインタ値
  28. © 2024 Wantedly, Inc. Word Boxing • Word Boxingのobject_id (3.3.0時点)

    ◦ 原則としてVALUEをそのまま返す ◦ 整数サイズに収まるBignumは、その整数値を返す ▪ たとえば ポインタサイズ = 整数サイズ = 64 のとき、 262 はFixnumには入らないが、64bit符 号つき整数では表現できる。 結果として、 ((1 << 62) + 1).object_id == (1 << 61).object_id となってしまう ◦ Floatは、ビット表現のハッシュ値を計算して返す。ただし、 -0.0 はあらかじめ 0.0 に正 規化する。
  29. © 2024 Wantedly, Inc. NaN Boxing • NaN BoxingのVALUE表現 (3.3.0時点)

    ◦ Floatは必ず64bitで、ビット表現に 0x8004000000000000 を足して保管する ▪ 言い換えると、ビット表現から 0x7ffc000000000000 を引く。この値は正規 NaNのビット表現 よりちょっと大きい ◦ ただしNaNは正規化する ▪ ここでの正規NaNとは、符号が正で仮数部の最上位ビットが 1、残りが0のもの、つまり 0x7ff8000000000000 とする (正式ではないがよく使われる正規化形式 ) ◦ Float以外のデータは約53bitある非正規NaNの空間に押しこめる ▪ 負数と仮数部空間下半分は使わないので、 51bit分から正規NaNを除いて48bit空間7本分を 確保できる
  30. © 2024 Wantedly, Inc. NaN Boxing • NaN BoxingのVALUE表現 (3.3.0時点)

    ◦ Fixnumは -231 〜 231 - 1 の範囲で固定、空間1を利用 ◦ Symbolとfalse, true, undef は空間6を利用 ◦ Objectとnilは空間4を利用 ▪ Floatのシフト値 0x8004000000000000 は、空間4がちょうど0になるように選ばれている ▪ よく知られている64bitアーキテクチャでは (ユーザーランドの)ポインタサイズが48bitに抑えら れているので、これで問題なく表現できる ◦ 生ポインタのVALUE表現 (cptr) が欲しいときは空間7を利用
  31. © 2024 Wantedly, Inc. NaN Boxing • NaN Boxingのobject_id (3.3.0時点)

    ◦ VALUE表現をそのまま返す ◦ ただし、整数サイズが32bitの場合は上位32bitと下位32bitのXORに圧縮する (当然、 重複は発生する)
  32. © 2024 Wantedly, Inc. Ruby 0.49 Ruby 0.49 • 現存する最古のバージョン

    • true/falseは無い (1/nilで代用) • Symbolも無い (String, Integerで代用) ◦ IDはあった • Kernel#id はあった ◦ 現在の #object_id に相当 ◦ n|1 を返す処理のため、重複が発生しうる
  33. © 2024 Wantedly, Inc. Ruby 0.49 • VALUE object_id nil

    0 0 Fixnum 2n + 1 n Object 4n 2n ※ alignof(RBasic) = 4
  34. © 2024 Wantedly, Inc. Ruby 0.49 • 形式 ID 例

    演算子 < LAST_ID :+ ローカル 8n + 0 :foo インスタンス 8n + 2 :@foo グローバル 8n + 3 :$foo セッター 8n + 4 :foo= 定数 8n + 6 :%foo Ruby 0.66で :Foo に変更
  35. © 2024 Wantedly, Inc. Ruby 0.69 Ruby 0.69 • $1,

    $2, … が登場 ◦ これにあわせて、IDのフラグ割り当てが変更
  36. © 2024 Wantedly, Inc. Ruby 0.69 • 形式 ID 例

    演算子 < LAST_ID :+ ローカル 8n + 0 :foo インスタンス 8n + 1 :@foo 形式 ID 例 グローバル 8n + 2 :$foo セッター 8n + 3 :foo= 定数 8n + 4 :Foo グループ参照 8n + 5 :$1
  37. © 2024 Wantedly, Inc. Ruby 0.77 〜 0.95 Ruby 0.77

    〜 0.95 のどこか • $1, $2, … のID は $foo と区別されなくなった ◦ 具体的なバージョンは不明
  38. © 2024 Wantedly, Inc. Ruby 0.77 〜 0.95 • 形式

    ID 例 演算子 < LAST_ID :+ ローカル 8n + 0 :foo インスタンス 8n + 1 :@foo 形式 ID 例 グローバル 8n + 2 :$foo セッター 8n + 3 :foo= 定数 8n + 4 :Foo グループ参照 8n + 5 :$1
  39. © 2024 Wantedly, Inc. Ruby 0.96 • VALUE object_id nil

    4 2 false 0 0 true 2 1 Fixnum 2n + 1 n Object 4n 2n
  40. © 2024 Wantedly, Inc. Ruby 0.96 〜 0.99 Ruby 0.96

    〜 0.99 のどこか • IDの割り当て変更 ◦ 具体的なバージョンは不明
  41. © 2024 Wantedly, Inc. Ruby 0.96 〜 0.99 • 形式

    ID 例 演算子 < LAST_ID :+ ローカル 8n + 1 :foo インスタンス 8n + 2 :@foo 形式 ID 例 グローバル 8n + 3 :$foo セッター 8n + 4 :foo= 定数 8n + 5 :Foo
  42. © 2024 Wantedly, Inc. Ruby 1.1 Ruby 1.1 • Kernel#id

    が INT2NUM を使うようになった ◦ 1/2ではなく、そのままの値が見えるようになる
  43. © 2024 Wantedly, Inc. Ruby 1.1 • VALUE object_id nil

    4 4 false 0 0 true 2 2 Fixnum 2n + 1 2n + 1 Object 4n 4n
  44. © 2024 Wantedly, Inc. Ruby 1.2 Ruby 1.2 • 64bitアーキテクチャへの対応開始

    ◦ 64bitアーキテクチャではVALUEが64bitになり、sizeof(RVALUE), alignof(RVALUE) が大きくなる
  45. © 2024 Wantedly, Inc. Ruby 1.3 • VALUE object_id nil

    4 4 false 0 0 true 2 2 Fixnum 2n + 1 2n + 1 Object 4n 2n
  46. © 2024 Wantedly, Inc. Ruby 1.6 Ruby 1.6 • undef

    (Qundef) 導入 de71615 ◦ Cコード用であり、Rubyの世界に出現することはない • クラス変数が登場 3d6fde3 ◦ 旧名: 共有変数。 Ruby 1.5で導入しようとしたものの再挑戦。 • Symbolが登場 4d215cd ◦ Internされた状態の文字列をRuby側から保持できるようになった。
  47. © 2024 Wantedly, Inc. Ruby 1.6 • VALUE object_id nil

    4 4 false 0 0 true 2 2 undef 6 – VALUE object_id Fixnum 2n + 1 2n + 1 Symbol 256 × ID + 14 256 × ID + 14 Object 8n 4n Object 4n 2n 32bitの場合
  48. © 2024 Wantedly, Inc. Ruby 1.6 • 形式 ID 例

    演算子 < LAST_ID :+ ローカル 8n + 1 :foo インスタンス 8n + 2 :@foo グローバル 8n + 3 :$foo 形式 ID 例 セッター 8n + 4 :foo= 定数 8n + 5 :Foo クラス変数 8n + 6 :@@foo
  49. © 2024 Wantedly, Inc. Ruby 1.8.0 Ruby 1.8.0 • IDの拡張

    b12904e ◦ 任意の文字列をinternできるように、未分類のIDを表すフラグが追加 • Kernel#object_id aae3675 ◦ Kernel#id を置き換える。 ◦ Kernel#id はこの時点では非推奨化されただけで、まだ使える
  50. © 2024 Wantedly, Inc. Ruby 1.8.0 • 形式 ID 例

    演算子 < LAST_ID :+ ローカル 8n + 1 :foo インスタンス 8n + 2 :@foo グローバル 8n + 3 :$foo 形式 ID 例 セッター 8n + 4 :foo= 定数 8n + 5 :Foo クラス変数 8n + 6 :@@foo その他 8n + 7 :")("
  51. © 2024 Wantedly, Inc. Ruby 1.8.5 Ruby 1.8.5 • SymbolとObjectの衝突回避

    6828bbe ◦ ObjectのC表現は4の倍数だが、object_idは2で割っているので2の倍数しか保証さ れず、そのままではSymbolと衝突する • Objectのアラインメント保証 (同上) ◦ 通常、ポインタのアラインメントは alignof(T) の範囲内でしか保証されない ◦ CRuby側で開始位置を調整することで、 sizeof(RVALUE) の倍数であることを保証す るようにした
  52. © 2024 Wantedly, Inc. Ruby 1.8.5 • VALUE object_id nil

    4 4 false 0 0 true 2 2 undef 6 – VALUE object_id Fixnum 2n + 1 2n + 1 Symbol 256 × ID + 14 20 × ID + 8 Object 40n 20n Symbol 256 × ID + 14 10 × ID + 8 Object 20n 10n 32bitの場合 (alignof(double) == 4 の場合)
  53. © 2024 Wantedly, Inc. Ruby 1.9.0 Ruby 1.9.0 • Kernel#id

    削除 ◦ Kernel#object_id への移行のため • ID割り当て変更 72f2d2a b83ed6d ◦ @_foo のような変数を「プライベートインスタンス変数」として特別扱いしようとしたが、 revertされた。この影響でIDのフラグ割り当てが変更に。
  54. © 2024 Wantedly, Inc. Ruby 1.9.0 • 形式 ID 例

    演算子 < LAST_ID :+ ローカル 8n + 0 :foo インスタンス 8n + 1 :@foo グローバル 8n + 3 :$foo 形式 ID 例 セッター 8n + 4 :foo= 定数 8n + 5 :Foo クラス変数 8n + 6 :@@foo その他 8n + 7 :")("
  55. © 2024 Wantedly, Inc. Ruby 1.9.3 Ruby 1.9.3 • Kernel#__id__

    移動 591ae37 049cdff ◦ BasicObjectに移動され、Proxy Objectからでも使えるようになった
  56. © 2024 Wantedly, Inc. Ruby 2.0.0 Ruby 2.0.0 • Flonum導入

    b3b5e62 ◦ 64bit環境で、範囲内のFloatが即値で表現されるようになった ◦ これらとの衝突を避けるため、定数やシンボルが移動し、 8n+4型の値を利用するように • 演算子IDの安定化 470c941 ◦ Yacc/BisonのLAST_TOKEN値に依存していた処理を書き直して、演算子に付与され るIDを安定化
  57. © 2024 Wantedly, Inc. Ruby 2.0.0 • 64bit VALUE object_id

    nil 8 8 false 0 0 true 20 20 undef 52 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum 4F(x) + 2 4F(x) + 2 Symbol 256 × ID + 12 20 × ID + 8 Object 40n 20n
  58. © 2024 Wantedly, Inc. Ruby 2.0.0 • 32bit VALUE object_id

    nil 4 4 false 0 0 true 2 2 undef 6 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum – – Symbol 256 × ID + 14 10 × ID + 8 Object 20n 10n (alignof(double) == 4 の場合)
  59. © 2024 Wantedly, Inc. Ruby 2.2.0 Ruby 2.2.0 • シンボルGC

    90b7073 ◦ String#to_sym などで動的に作成されたSymbolはGCの対象になる ◦ 内部的には、普通の RVALUE* オブジェクトとして確保されることになる ◦ これに合わせて、IDにフラグビットが追加 • セッターID紐付けの廃止 3e69b07 ◦ :foo と :foo= のように対応するSymbolに、同じカウンタに由来するIDを付与する機能 があったが、これが廃止された。
  60. © 2024 Wantedly, Inc. Ruby 2.2.0 • 64bit VALUE object_id

    nil 8 8 false 0 0 true 20 20 undef 52 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum 4F(x) + 2 4F(x) + 2 静的Symbol 256 × ID + 12 20 × ID + 8 Object 40n 20n
  61. © 2024 Wantedly, Inc. Ruby 2.2.0 • 32bit VALUE object_id

    nil 4 4 false 0 0 true 2 2 undef 6 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum – – 静的Symbol 256 × ID + 14 10 × ID + 8 Object 20n 10n (alignof(double) == 4 の場合)
  62. © 2024 Wantedly, Inc. Ruby 2.2.0 • 形式 ID (動的)

    ID (静的) 例 演算子 < LAST_ID :+ ローカル 16n + 0 16n + 1 :foo インスタンス 16n + 2 16n + 3 :@foo グローバル 16n + 6 16n + 7 :$foo 形式 ID (動的) ID (静的) 例 セッター 16n + 8 16n + 9 :foo= 定数 16n + 10 16n + 11 :Foo クラス変数 16n + 12 16n + 13 :@@foo その他 16n + 14 16n + 15 :")("
  63. © 2024 Wantedly, Inc. Ruby 2.7.0 Ruby 2.7.0 • コンパクションGC

    91793b8 b99833b ◦ コンパクションが起こると、オブジェクトのアドレスが変化するため、アドレスを object_id として使うことができない。 ◦ かわりに、object_idが必要になったタイミングでカウンタからユニークな値を生成し、そ れを使うようになった ◦ 既存のobject_idの計算に合わせるため、カウンタの値を sizeof(RVALUE)/2 倍して 使用
  64. © 2024 Wantedly, Inc. Ruby 2.7.0 • 64bit VALUE object_id

    nil 8 8 false 0 0 true 20 20 undef 52 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum 4F(x) + 2 4F(x) + 2 静的Symbol 256 × ID + 12 20 × ID + 8 Object 40n 20k
  65. © 2024 Wantedly, Inc. Ruby 2.7.0 • 32bit VALUE object_id

    nil 4 4 false 0 0 true 2 2 undef 6 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum – – 静的Symbol 256 × ID + 14 10 × ID + 8 Object 20n 10k (alignof(double) == 4 の場合)
  66. © 2024 Wantedly, Inc. Ruby 3.2.0 Ruby 3.2.0 • 定数値の変更

    f55212b ◦ 計算しやすいようにnil, true, undefの定数値を変更
  67. © 2024 Wantedly, Inc. Ruby 3.2.0 • 64bit VALUE object_id

    nil 4 4 false 0 0 true 20 20 undef 36 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum 4F(x) + 2 4F(x) + 2 静的Symbol 256 × ID + 12 20 × ID + 8 Object 40n 20k
  68. © 2024 Wantedly, Inc. Ruby 3.2.0 • 32bit VALUE object_id

    nil 2 2 false 0 0 true 6 6 undef 10 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum – – 静的Symbol 256 × ID + 14 10 × ID + 8 Object 20n 10k (alignof(double) == 4 の場合)
  69. © 2024 Wantedly, Inc. Ruby 3.4.0 Ruby 3.4.0 (未リリース) •

    SymbolとObjectの整理 edec690 403f44e ◦ Symbolのobject_idが複雑な変換を経ていたのをやめて、 VALUE値をそのまま返す ように変更 ◦ Objectは下位ビットが衝突しなければいいので、単に 4または8の倍数としてカウントす るように変更 (sizeof(RVALUE) が無関係に) • object_idカウンタの拡張 ee6e591 ◦ 32bit環境でも64bitカウンタを利用することで枯渇に対応
  70. © 2024 Wantedly, Inc. Ruby 3.4.0 • 64bit VALUE object_id

    nil 4 4 false 0 0 true 20 20 undef 36 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum 4F(x) + 2 4F(x) + 2 静的Symbol 256 × ID + 12 256 × ID + 12 Object 8n 8k
  71. © 2024 Wantedly, Inc. Ruby 3.4.0 • 32bit VALUE object_id

    nil 2 2 false 0 0 true 6 6 undef 10 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum – – 静的Symbol 256 × ID + 14 256 × ID + 14 Object 4n 4k