K.Sasada's Home Page

こめんとのついか

こめんとこめんと!

message

please set comment :).

_9(Sun)

Ruby VM アドベントカレンダーの 9 日目です.

昨日の記事では,ObjectSpace::InternalObjectWrapper というものが登場しました.さて,これはいったいなんでしょうか.

ObjectSpace.reachable_objects_from(obj) は,obj が直接参照するすべてのオブジェクトを返すのですが,中には Ruby からは触るべきではないオブジェクトが存在します.そのようなものの場合,一度 InternalObjectWrapper で wrap してから返すようにしています.

ちなみに,触るべきでないオブジェクトは,通常のメソッドの返値などで取ることが出来ないのはもちろんのこと,ObjectSpace.each_object でも取ることは出来ないようになっています.

実際に,どのようなものがあるか,試してみましょう.

require 'objspace'
require 'pp'

iseq = RubyVM::InstructionSequence.compile("puts 'hello'")
pp ObjectSpace.reachable_objects_from(iseq)
#=>
[RubyVM::InstructionSequence,
 #<InternalObject:0x1062c54 T_ARRAY>,
 "<compiled>",
 "<compiled>",
 #<InternalObject:0x1062c7c T_NODE>]

ここでは,4つのオブジェクトが取れました.そのうち2つが InternalObject になっています.残り2つの "<compiled>" という文字列は,ISeq#path とかで取るための文字列ですね.

では,隠された Array を示す #<InternalObject:0x1062c54 T_ARRAY> に,何が入っているか見てみましょう.

require 'objspace'
require 'pp'

iseq = RubyVM::InstructionSequence.compile("puts 'hello'")
hide_array = ObjectSpace.reachable_objects_from(iseq)[1]
pp ObjectSpace.reachable_objects_from(hide_array)
#=>
["hello"]

文字列リテラルとして利用した "hello" という文字列を格納しているということがわかりました.

そもそも,なぜこの配列を隠しオブジェクトにしているかというと,この配列を ObjectSpace.each_object などで取り出して,勝手に変更を加えると,このバイトコード列を実行するのに問題が生じるためです.で,この隠し配列オブジェクトがなんだったかというと,バイトコードが利用するオブジェクトを,バイトコードが生存しているあいだは mark するための配列です.具体的には rb_iseq_t::mark_ary です.

なお,InternalObjectWrapper に対して ObjectSpace.reachable_objects_from を行うと,その wrap した対象である内部オブジェクトが参照しているオブジェクト群を返します.この機能を加えることで,「あるオブジェクトを起点とした,オブジェクトの関係グラフ」が利用できることになります.

もう1つ加えておくと,今回は 1 番目にこの隠し配列オブジェクトがある,ということがわかりましたが,この順番はとくに保証されていません.具体的には,mark 処理の順番で格納されていくことになります.

さて,InternalObjectWrapper#object_id は,もちろんこの wrapper オブジェクトの object_id を取り出しますが,wrap したオブジェクトの object_id が取り出したいことがあります.それを,InternalObjectWrapper#internal_object_id によって得ることが出来ます.昨日の記事では,この機能を使って memsize_of_all_reachable_objects_from(obj) を実現していました.

では,今日はこの辺で.


好きにコメントを編集してください。ただし、あまり他の人のコメントを書き換えることは感心しません。



back

tton 記述が使えます。YukiWikiな記述してりゃ問題ありません。

「行頭に#code」 と、「行頭に#end」 で挟むと、その間の行は pre で囲まれます。プログラムのソースを書くときに使ってください。

例:

#code

(なんかプログラム書く)

#end

リンクは

[[なまえ|http://www.example.org]]

とか

[[http://www.example.org]]

で貼れます。

$Date: 2003/04/28 10:27:51 $