tokuhirom's blog

MoarVM における DESTROY メソッドの呼び出し手順

refcnt 型のインタープリタの場合デストラクタの呼び出しは極めて容易だが、GC の場合はちょっと面倒だ。

Rakudo の場合は、src/Perl6/Metamodel/Finalization.nqp にコードがある。

以下のように、DESTROY メソッドを持っているクラスを MoarVM に settypefinalize している。 ``` role Perl6::Metamodel::Finalization { has @!destroyers;

method setup_finalization($obj) {
    my @mro   := self.mro($obj);
    my int $i := nqp::elems(@mro);
    my @destroyers;
    while --$i >= 0 {
        my $class   := @mro[$i];
        my $destroy := $class.HOW.find_method($class, 'DESTROY', :no_fallback(1));
        if !nqp::isnull($destroy) && $destroy {
            nqp::push(@destroyers, $destroy);
        }
    }
    @!destroyers := @destroyers;
    if @destroyers {
        nqp::settypefinalize($obj, 1);
    }
}

method destroyers($obj) {
    @!destroyers
}

} ```

settypefinalize の処理は src/core/interp.c の以下の部分で処理される。

            OP(settypefinalize):
                MVM_gc_finalize_set(tc, GET_REG(cur_op, 0).o, GET_REG(cur_op, 2).i64);
                cur_op += 4;
                goto NEXT;

MVMgcfinalizeset により、クラスに MVMFINALIZETYPE フラグが付与される。 このフラグが付与されているとオブジェクトの新規作成を行う MVMgcallocateobject の中で、MVM_gc_finalize_add_to_queue(tc, obj); が呼ばれ、ファイナライズキューに詰められる。

というわけで、ファイナライズ処理が必要になっているものは別枠で処理される、ということでした。

Created: 2015-12-19 10:14:59 +0900
Updated: 2015-12-19 10:14:59 +0900