Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
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
Symfony Mapper Component
soyuka
2
560
romajip: 日本の住所CSVデータを活用した英語住所変換ライブラリを作った話
sangunkang
0
2.4k
React CompilerとFine Grained Reactivityと宣言的UIのこれから / The next chapter of declarative UI
ssssota
7
3.4k
物流システムにおけるリファクタリングとアーキテクチャの再構築 〜依存関係とモジュール分割の重要性〜
deeprain
1
740
コンテンツの主権を守るため(?)、高機能画像CDNからAWS自前対応に乗り換えた話
lengthtail
1
120
Missing parts when designing and implementing Android UI
ericksli
0
390
ソフトウェアの振る舞いに着目し 複雑な要件の開発に立ち向かう
rickyban
0
820
Cursorでアプリケーションの追加開発や保守をどこまでできるか試したら得るものが多かった話
drumnistnakano
0
280
useSyncExternalStoreを使いまくる
ssssota
2
380
42 best practices for Symfony, a decade later
tucksaun
1
140
Serverless苦闘史
mosh_inc
0
140
第5回日本眼科AI学会総会_AIコンテスト_3位解法
neilsaw
0
140
Featured
See All Featured
Why Our Code Smells
bkeepers
PRO
334
57k
Docker and Python
trallard
41
3.1k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
126
18k
Practical Orchestrator
shlominoach
186
10k
A better future with KSS
kneath
238
17k
Facilitating Awesome Meetings
lara
50
6.1k
Building Applications with DynamoDB
mza
91
6.1k
No one is an island. Learnings from fostering a developers community.
thoeni
19
3k
How to Think Like a Performance Engineer
csswizardry
21
1.2k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5.1k
The Cost Of JavaScript in 2023
addyosmani
45
6.9k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
8
1.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. 以上