Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Rubyのobject_id
Search
Masaki Hara
August 28, 2024
Programming
6
1.5k
Rubyのobject_id
Rubyのobject_idを入口にして、Rubyの実装詳細について学びます。
Masaki Hara
August 28, 2024
Tweet
Share
More Decks by Masaki Hara
See All by Masaki Hara
Arm移行タイムアタック
qnighy
0
410
Quine, Polyglot, 良いコード
qnighy
5
680
Prolog入門
qnighy
5
1.3k
Getting along with YAML comments with Psych
qnighy
2
2.2k
状態設計から「なんとなく」を無くそう
qnighy
85
28k
日付時刻A to Z
qnighy
1
590
Hands-on Native ESM @ JSConf JP 2022
qnighy
0
5.7k
computed_modelの紹介 / Introducing computed_model (2)
qnighy
0
590
computed_modelの紹介 / Introducing computed_model
qnighy
0
360
Other Decks in Programming
See All in Programming
物流システムにおけるリファクタリングとアーキテクチャの再構築 〜依存関係とモジュール分割の重要性〜
deeprain
1
730
StarlingMonkeyを触ってみた話 - 2024冬
syumai
2
120
Figma Dev Modeで変わる!Flutterの開発体験
watanave
0
3.7k
Java 23の概要とJava Web Frameworkの現状 / Java 23 and Java web framework
kishida
2
380
cmp.Or に感動した
otakakot
3
340
今からはじめるAndroidアプリ開発 2024 / DevFest 2024
star_zero
0
770
テスト自動化失敗から再挑戦しチームにオーナーシップを委譲した話/STAC2024 macho
ma_cho29
1
810
急成長期の品質とスピードを両立するフロントエンド技術基盤
soarteclab
0
740
テストコード文化を0から作り、変化し続けた組織
kazatohiei
2
930
型のインスタンス化は非常に深く、無限である可能性があります。
kimitashoichi
0
140
Welcome JSConf.jp 2024
yosuke_furukawa
PRO
0
3.1k
tidymodelsによるtidyな生存時間解析 / Japan.R2024
dropout009
1
590
Featured
See All Featured
It's Worth the Effort
3n
183
27k
The Cult of Friendly URLs
andyhume
78
6.1k
For a Future-Friendly Web
brad_frost
175
9.4k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
229
52k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
132
33k
The Invisible Side of Design
smashingmag
298
50k
How to train your dragon (web standard)
notwaldorf
88
5.7k
BBQ
matthewcrist
85
9.3k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
110
49k
Fontdeck: Realign not Redesign
paulrobertlloyd
82
5.3k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
95
17k
How STYLIGHT went responsive
nonsquared
95
5.2k
Transcript
© 2024 Wantedly, Inc. object_id Rubyの Aug. 28 2024 -
Masaki Hara @ Gotanda.rb #60
© 2024 Wantedly, Inc. Rubyの object_id
© 2024 Wantedly, Inc. Quiz 1 p 1.object_id == 1.object_id
p "foo".object_id == "foo".object_id p [].object_id == [].object_id
© 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 とは断言できない
© 2024 Wantedly, Inc. object_id • オブジェクトの同一性をあらわす整数 ◦ Kernel#object_id または
BasicObject#__id__ • #equal? と同等 ◦ a.equal?(b) ⇔ a.__id__ == b.__id__
© 2024 Wantedly, Inc. object_idの永続性 • object_id は現存する他のオブジェクトとは重複しない • 過去に存在したオブジェクトとは重複しうる
◦ ……ということになっているが、実は現行の CRuby実装では重複しない (後述)
© 2024 Wantedly, Inc. object_idの永続性 RubyVM::InstructionSequence.compile( "[].object_id == [].object_id" ).to_a[13]
© 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]]
© 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]
© 2024 Wantedly, Inc. CRuby の object_id
© 2024 Wantedly, Inc. Quiz 2 p false.object_id p 100.object_id
p 10000000000.object_id ※CRubyの場合
© 2024 Wantedly, Inc. Quiz 2 p false.object_id # =>
0 p 100.object_id # => 201 p 10000000000.object_id # => 32bit環境と64bit環境で異なる ※CRubyの場合
© 2024 Wantedly, Inc. 特別な値 • false, true, nil, および小さい整数値は特別なobject_id値
をもつ (即値) ◦ 短い整数値はFixnumとも呼ばれる • 小さい整数値の上限は32bit環境と64bit環境で異なる ◦ 32bitなら −230 ≤ n < 230, 64bitなら −262 ≤ n < 262
© 2024 Wantedly, Inc. Quiz 3 p [].object_id - [].object_id
※CRubyの一般的な結果
© 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の一般的な結果
© 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ずつ)
© 2024 Wantedly, Inc. Quiz 4 p :foo.object_id p "bar".to_sym.object_id
※CRubyの一般的な結果
© 2024 Wantedly, Inc. Quiz 4 p :foo.object_id # =>
12280076 (一例) p "bar".to_sym.object_id # => 8 (一例) ※CRubyの一般的な結果
© 2024 Wantedly, Inc. シンボルGC • 静的シンボル: GCされない。IDは 256n +
12 ◦ :foo など静的な構文によって生成されるとこの形になる ◦ Ruby 3.3 以前は別仕様 • 動的シンボル: GCされる。IDは 40n ◦ 一般のオブジェクトと同じ扱い ◦ 40 は 64bit環境における sizeof(RVALUE) ◦ String#to_sym など動的な処理で生成されるとこの形になる ◦ すでに静的シンボルが生成されていればそちらが使われる (逆も然り)
© 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とも異なる
© 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の値が割り当てられる
© 2024 Wantedly, Inc. Quiz 5 p 0.0.object_id p (-0.0).object_id
※CRubyの場合
© 2024 Wantedly, Inc. Quiz 5 p 0.0.object_id # =>
-9223372036854775806 p (-0.0).object_id # => 8 (一例) ※CRubyの場合
© 2024 Wantedly, Inc. Flonum • Ruby 2.0以降では、64bit環境でFlonumが有効 • Flonum:
特定範囲の浮動小数点数を即値で表現 ◦ 10-77 〜 1077 に限定すれば62bitで済む ◦ 使う機会の多い +0 は例外的に追加の即値として表現
© 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
© 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
© 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
© 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は奇数)
© 2024 Wantedly, Inc. まとめ • #object_id は内部表現 (VALUE) をそのまま返しているわ
けではない • とはいえ、Ruby 3.4では即値はそのまま返される • 小さいInteger, 妥当な範囲のFloat, 静的なSymbolは即値 で表現される • Ruby 2.7以降ではobject_idは再利用されない
© 2024 Wantedly, Inc. おまけ: JRuby の object_id
© 2024 Wantedly, Inc. JRuby JRubyにおける VALUE • Ruby ObjectをJavaのObjectとして表現
◦ Rubyの整数なども内部的にはJavaのObjectになる • JRubyからはJavaのObject IDは見えない ◦ System.identityHashCode がそれに近いが、32bitしかないので厳密な一意性は望 めない • したがって、VALUE相当の表現はないと言える
© 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
© 2024 Wantedly, Inc. おまけ: mruby の object_id
© 2024 Wantedly, Inc. mruby • mrubyは多様な環境で動くことを想定しているため、各環境 に適した動作ができるようになっている ◦ ポインタサイズ、整数サイズ
◦ boxing mode (後述) ◦ Floatの有無 • 環境によっては整数のビット数不足により object_id のユ ニーク性を担保できない ◦ 整数のビット数が十分な場合でも、 object_idのユニーク性については現時点であまり 考慮されていない
© 2024 Wantedly, Inc. boxing mode mrubyは3つのうちのいずれかのモードで動作する: • Unboxed (No
Boxing) ◦ 2ワード利用するシンプルな表現 • Word Boxing ◦ CRubyと似たアプローチ • NaN Boxing ◦ JavaScript処理系でよく使われるアプローチ rake MRUBY_CONFIG=build_config/boxing.rb でビルドしてテストできる
© 2024 Wantedly, Inc. Unboxed • UnboxedのVALUE表現 ◦ 型タグ +
整数 または ◦ 型タグ + ポインタ ◦ nilはfalseと同じ型タグを持ち、整数部分で区別 • Unboxedのobject_id (3.3.0時点) ◦ 型タグと値(整数またはポインタ)のXOR ◦ 容易にコンフリクトする (たとえば nil.object_id == 2.object_id)
© 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* のポインタ値
© 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 に正 規化する。
© 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本分を 確保できる
© 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を利用
© 2024 Wantedly, Inc. NaN Boxing • NaN Boxingのobject_id (3.3.0時点)
◦ VALUE表現をそのまま返す ◦ ただし、整数サイズが32bitの場合は上位32bitと下位32bitのXORに圧縮する (当然、 重複は発生する)
© 2024 Wantedly, Inc. おまけ: CRuby の object_id の歴史
© 2024 Wantedly, Inc. Ruby 0.49 Ruby 0.49 • 現存する最古のバージョン
• true/falseは無い (1/nilで代用) • Symbolも無い (String, Integerで代用) ◦ IDはあった • Kernel#id はあった ◦ 現在の #object_id に相当 ◦ n|1 を返す処理のため、重複が発生しうる
© 2024 Wantedly, Inc. Ruby 0.49 • VALUE object_id nil
0 0 Fixnum 2n + 1 n Object 4n 2n ※ alignof(RBasic) = 4
© 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 に変更
© 2024 Wantedly, Inc. Ruby 0.69 Ruby 0.69 • $1,
$2, … が登場 ◦ これにあわせて、IDのフラグ割り当てが変更
© 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
© 2024 Wantedly, Inc. Ruby 0.77 〜 0.95 Ruby 0.77
〜 0.95 のどこか • $1, $2, … のID は $foo と区別されなくなった ◦ 具体的なバージョンは不明
© 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
© 2024 Wantedly, Inc. Ruby 0.96 Ruby 0.96 • true/falseが追加
© 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
© 2024 Wantedly, Inc. Ruby 0.96 〜 0.99 Ruby 0.96
〜 0.99 のどこか • IDの割り当て変更 ◦ 具体的なバージョンは不明
© 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
© 2024 Wantedly, Inc. Ruby 1.1 Ruby 1.1 • Kernel#id
が INT2NUM を使うようになった ◦ 1/2ではなく、そのままの値が見えるようになる
© 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
© 2024 Wantedly, Inc. Ruby 1.1b9-07 Ruby 1.1b9-07 • Kernel#__id__
が新設 7253910 ◦ Kernel#id と同じ
© 2024 Wantedly, Inc. Ruby 1.2 Ruby 1.2 • 64bitアーキテクチャへの対応開始
◦ 64bitアーキテクチャではVALUEが64bitになり、sizeof(RVALUE), alignof(RVALUE) が大きくなる
© 2024 Wantedly, Inc. Ruby 1.3 Ruby 1.3 • オブジェクトのIDはアドレスの1/2
© 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
© 2024 Wantedly, Inc. Ruby 1.6 Ruby 1.6 • undef
(Qundef) 導入 de71615 ◦ Cコード用であり、Rubyの世界に出現することはない • クラス変数が登場 3d6fde3 ◦ 旧名: 共有変数。 Ruby 1.5で導入しようとしたものの再挑戦。 • Symbolが登場 4d215cd ◦ Internされた状態の文字列をRuby側から保持できるようになった。
© 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の場合
© 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
© 2024 Wantedly, Inc. Ruby 1.8.0 Ruby 1.8.0 • IDの拡張
b12904e ◦ 任意の文字列をinternできるように、未分類のIDを表すフラグが追加 • Kernel#object_id aae3675 ◦ Kernel#id を置き換える。 ◦ Kernel#id はこの時点では非推奨化されただけで、まだ使える
© 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 :")("
© 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) の倍数であることを保証す るようにした
© 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 の場合)
© 2024 Wantedly, Inc. Ruby 1.9.0 Ruby 1.9.0 • Kernel#id
削除 ◦ Kernel#object_id への移行のため • ID割り当て変更 72f2d2a b83ed6d ◦ @_foo のような変数を「プライベートインスタンス変数」として特別扱いしようとしたが、 revertされた。この影響でIDのフラグ割り当てが変更に。
© 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 :")("
© 2024 Wantedly, Inc. Ruby 1.9.3 Ruby 1.9.3 • Kernel#__id__
移動 591ae37 049cdff ◦ BasicObjectに移動され、Proxy Objectからでも使えるようになった
© 2024 Wantedly, Inc. Ruby 2.0.0 Ruby 2.0.0 • Flonum導入
b3b5e62 ◦ 64bit環境で、範囲内のFloatが即値で表現されるようになった ◦ これらとの衝突を避けるため、定数やシンボルが移動し、 8n+4型の値を利用するように • 演算子IDの安定化 470c941 ◦ Yacc/BisonのLAST_TOKEN値に依存していた処理を書き直して、演算子に付与され るIDを安定化
© 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
© 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 の場合)
© 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を付与する機能 があったが、これが廃止された。
© 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
© 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 の場合)
© 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 :")("
© 2024 Wantedly, Inc. Ruby 2.7.0 Ruby 2.7.0 • コンパクションGC
91793b8 b99833b ◦ コンパクションが起こると、オブジェクトのアドレスが変化するため、アドレスを object_id として使うことができない。 ◦ かわりに、object_idが必要になったタイミングでカウンタからユニークな値を生成し、そ れを使うようになった ◦ 既存のobject_idの計算に合わせるため、カウンタの値を sizeof(RVALUE)/2 倍して 使用
© 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
© 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 の場合)
© 2024 Wantedly, Inc. Ruby 3.2.0 Ruby 3.2.0 • 定数値の変更
f55212b ◦ 計算しやすいようにnil, true, undefの定数値を変更
© 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
© 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 の場合)
© 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カウンタを利用することで枯渇に対応
© 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
© 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
© 2024 Wantedly, Inc. 以上