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.3k
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
3
570
Getting along with YAML comments with Psych
qnighy
2
1.9k
状態設計から「なんとなく」を無くそう
qnighy
84
27k
日付時刻A to Z
qnighy
1
530
Hands-on Native ESM @ JSConf JP 2022
qnighy
0
5.6k
computed_modelの紹介 / Introducing computed_model (2)
qnighy
0
570
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
『ドメイン駆動設計をはじめよう』中核の業務領域
masuda220
PRO
5
930
Modular Monolith Go Server with GraphQL Federation + gRPC
110y
1
570
【TID2024】模擬講義:プログラマと一緒にゲームをデザインしてみよう!
akatsukigames_tech
0
490
Rubyとクリエイティブコーディングの輪の広がり / The Growing Circle of Ruby and Creative Coding
chobishiba
1
240
仮想ファイルシステムを導入して開発環境のストレージ課題を解消する
segadevtech
2
460
大公開!iOS開発の悩みトップ5 〜iOSDC Japan 2024〜
ryunakayama
0
190
[DroidKaigi 2024] Android ViewからJetpack Composeへ 〜Jetpack Compose移行のすゝめ〜 / From Android View to Jetpack Compose: A Guide to Migration
syarihu
1
200
Desafios e Lições Aprendidas na Migração de Monólitos para Microsserviços em Java
jessilyneh
2
140
オートマトン学習しろ / Do automata learning
makenowjust
3
110
令和トラベルにおけるLLM活用事例:社内ツール開発から得た学びと実践
ippo012
0
120
Regular Expressions, REXML, Automata Learning
makenowjust
0
190
GoのIteratorに詳しくなってしまう
inatonix
1
190
Featured
See All Featured
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
88
16k
Building Flexible Design Systems
yeseniaperezcruz
325
37k
Art, The Web, and Tiny UX
lynnandtonic
294
20k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
25
1.3k
Product Roadmaps are Hard
iamctodd
PRO
48
10k
Robots, Beer and Maslow
schacon
PRO
157
8.1k
The Pragmatic Product Professional
lauravandoore
31
6.2k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
123
18k
For a Future-Friendly Web
brad_frost
174
9.3k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
248
20k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
226
52k
No one is an island. Learnings from fostering a developers community.
thoeni
18
2.9k
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. 以上