Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
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.4k
Rubyのobject_id
Rubyのobject_idを入口にして、Rubyの実装詳細について学びます。
Masaki Hara
August 28, 2024
Tweet
Share
More Decks by Masaki Hara
See All by Masaki Hara
Prolog入門
qnighy
4
1.1k
Getting along with YAML comments with Psych
qnighy
2
2k
状態設計から「なんとなく」を無くそう
qnighy
84
27k
日付時刻A to Z
qnighy
1
540
Hands-on Native ESM @ JSConf JP 2022
qnighy
0
5.6k
computed_modelの紹介 / Introducing computed_model (2)
qnighy
0
580
computed_modelの紹介 / Introducing computed_model
qnighy
0
350
Rust: imperative language 2.0
qnighy
10
2.5k
Making an opinionated Web framework
qnighy
2
4.4k
Other Decks in Programming
See All in Programming
Vue :: Better Testing 2024
up1
1
360
グローバルなソフトウェアテスト組織における課題と戦略 / Challenges and Strategies in a Global Software Testing Organization #mf_techday
imtnd
0
230
The Efficiency Paradox and How to Save Yourself and the World
hollycummins
0
130
AWS CDKを用いたセキュアなCI/CDパイプラインの構築 / Build a secure CI/CD pipeline using AWS CDK
seike460
PRO
3
500
AWS Lambda Web Adapterを活用する新しいサーバーレスの実装パターン
tmokmss
6
5.4k
XP2024 っていう国際会議に行ってきたよの記 / XP2024 Conference Report
bonotake
4
150
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
1.1k
5年分のツケを一気に払った話
soogie
3
1.1k
M5Stackボードの選び方
tanakamasayuki
0
200
tsconfig.jsonの最近の新機能 ファイルパス編
uhyo
6
1.3k
個人開発で使ってるやつを紹介する回
yohfee
1
640
ファーストペンギンBot @Qiita Hackathon 2024 予選
dyson_web
0
210
Featured
See All Featured
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
158
15k
Code Reviewing Like a Champion
maltzj
519
39k
Designing with Data
zakiwarfel
98
5.1k
Agile that works and the tools we love
rasmusluckow
327
21k
Bash Introduction
62gerente
608
210k
How to Think Like a Performance Engineer
csswizardry
16
1k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
Rails Girls Zürich Keynote
gr2m
93
13k
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
1
230
The Straight Up "How To Draw Better" Workshop
denniskardys
231
130k
Statistics for Hackers
jakevdp
796
220k
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. 以上