introduction to perl magic

20
Introduction to Perl MAGIC for XS writers Fuji, Goro (gfx) <[email protected]> YAPC::Asia 2009, Sep 10th

Upload: guest6b8f09

Post on 29-Oct-2014

24 views

Category:

Technology


2 download

DESCRIPTION

Used for talks in YAPC::Asia 2009- gfx

TRANSCRIPT

Page 1: Introduction to Perl MAGIC

Introduction to Perl MAGIC for XS writers

Fuji, Goro (gfx) <[email protected]>

YAPC::Asia 2009, Sep 10th

Page 2: Introduction to Perl MAGIC

perlguts says: This section still under construction. Ignore

everything here. Post no bills. Everything not permitted is for bidden.

Page 3: Introduction to Perl MAGIC

perlguts says about "Magic Variable": Any SV may be magical, that is, it

has special features that a normal SV does not have. These features are stored in the SV structure in a linked list of struct magic's, typedef'ed to MAGIC.

MAGIC features: hook methods + managed data

Page 4: Introduction to Perl MAGIC

/* mg.h of 5.10.1 */struct magic { MAGIC* mg_moremagic;/* pointer to the next magic */ MGVTBL* mg_virtual; /* pointer to magic hook methods */ U16 mg_private; /* user data(1): small integer */ char mg_type; /* type identity, e.g. PERL_MAGIC_ext

*/ U8 mg_flags; /* flags reserved by core */ I32 mg_len; /* the length of mg_ptr (or

HEf_SVKEY) */ SV* mg_obj; /* user data(2): sv */ char* mg_ptr; /* user data(3): managed pointer or

sv */};/* perl.h */typedef struct magic MAGIC;

Page 5: Introduction to Perl MAGIC

/* mg.h of 5.10.1 */#ifdef STRUCT_MGVTBL_DEFINITIONSTRUCT_MGVTBL_DEFINITION;#elsestruct mgvtbl { int (CPERLscope(*svt_get)) (pTHX_ SV *sv, MAGIC* mg); int (CPERLscope(*svt_set)) (pTHX_ SV *sv, MAGIC* mg); U32 (CPERLscope(*svt_len)) (pTHX_ SV *sv, MAGIC* mg); int (CPERLscope(*svt_clear)) (pTHX_ SV *sv, MAGIC* mg); int (CPERLscope(*svt_free)) (pTHX_ SV *sv, MAGIC* mg); int (CPERLscope(*svt_copy)) (pTHX_ SV *sv, MAGIC* mg, SV *nsv, const char *name, int

namlen); int (CPERLscope(*svt_dup)) (pTHX_ MAGIC *mg,

CLONE_PARAMS *param); int (CPERLscope(*svt_local)) (pTHX_ SV *nsv, MAGIC

*mg);};#endif

Page 6: Introduction to Perl MAGIC

# perlgutsFunction pointer Action taken---------------- ------------svt_get Do something before the value of the SV is

retrieved.svt_set Do something after the SV is assigned a value.svt_len Report on the SV's length.svt_clear Clear something the SV represents.svt_free Free any extra storage associated with the SV.

svt_copy copy tied variable magic to a tied elementsvt_dup duplicate a magic structure during thread

cloningsvt_local copy magic to local value during 'local‘

(snip)

Page 7: Introduction to Perl MAGIC

Some special variables are bound to C variables $^H -> PL_hints $! -> errno

Weak references Defer elements UTF8 helpers

To look into MAGICs, you can use Devel::Peek perl –MDevel::Peek –e ‘Dump $^H;’

Page 8: Introduction to Perl MAGIC

B::Hooks::EndOfScope via Variable::Magic using hook methods

WeakRef::Auto using hook methods

Sub::Name using managed data

Class::MOP/Moose using managed data under construction!

Page 9: Introduction to Perl MAGIC

$ perl -MDevel::Peek -e 'Dump \@ISA'SV = RV(0x8ce3174) at 0x8ce3168 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x8cf33c0 SV = PVAV(0x8ce4038) at 0x8cf33c0 REFCNT = 2 FLAGS = (SMG,RMG) # has SetMagic and GetMagic MAGIC = 0x8cf62c8 MG_VIRTUAL = &PL_vtbl_isa # mg_virtual MG_TYPE = PERL_MAGIC_isa(I) # mg_type MG_OBJ = 0x8ce3208 # mg_obj ARRAY = 0x0 FILL = -1 MAX = -1 ARYLEN = 0x0 FLAGS = (REAL)

# @ISA magic will invalidate methods caches when class hierarchies are changed.

Page 10: Introduction to Perl MAGIC

If you don’t write XS, you need not to care about MAGIC, but otherwise you must care about it because Perl APIs do not always handle MAGIC.

PerlレベルではMAGICを意識する必要はないが, C レベルではMAGICを扱う APIと扱わない APIが区別されているので, XSを書くならば常に意識しなければならない。

Page 11: Introduction to Perl MAGIC

MAGI C をハンドルする APIを知る

MAGIC を起動する API SvIV/SvNV/SvPV など -> SetMAGIC sv_setsv_mg などの sv_setx_mg 系 ->

GetMAGIC sv_isobject など( perlapi に載っていないことが

多い) MAGIC を起動しない API

SvIVX/SvOK などSVの要素を直接参照するもの sv_setx 系で _mg の付かないもの xsubpp のデフォルト typemap のいくつか(後

述)

Page 12: Introduction to Perl MAGIC

xsubpp/typemap の特性を知る

typemap のうち、 MAGIC を起動しないものがある char*, int などは MAGIC をハンドルする HV*, AV*, CV* などは MAGIC をハンドルしない

ドキュメントには書いていないので注意 Magic::Example に例

http://github.com/gfx/YAPC-Asia-2009-gfx/tree/master

->> perl Makefile.PL && make test (should fail)

Page 13: Introduction to Perl MAGIC

[ah]v_store の戻り値

The return value will be NULL if the operation failed or if the value did not need to be actually stored within the hash (as in the case of tied hashes) (perlapi)

タイハッシュ・配列に store すると、 NULL を返す その場合、 store したSVを解放しなければならな

い XS内のみで使う hv/av ならば戻り値は無視で

きる (void)hv_store_ent(hv, key, val, 0U); /* OK */

Page 14: Introduction to Perl MAGIC

スタック操作を伴うケース Question

XPUSHs() などはSPを realloc() する可能性がある newSVsv() などは MAGIC を起動する可能性がある ∴newSVsv() の前後でSPの値が変わる可能性がある?

Answer No. メタスタック (PERL_SI) メカニズムによるSPの保護 MAGIC(tie), destructor などで自動的に呼び出されるサブ

ルーチンについては、SPが変わる心配はない ただし、エクステンションが hook methods 内でサブ

ルーチンを呼ぶ場合は、メタスタックの管理が必要 PUSHSTACK/POPSTACK (but no document)

Page 15: Introduction to Perl MAGIC

PERL_MAIGC_ext

sv_magicext(sv, mg_obj, PERL_MAGIC_ext, &mg_vritual, mg_ptr, mg_len) mg_ptr は char* で、 mg_len でその長さを指定

mg_len が 1 以上のとき、 mg_ptr は sv_magicext 内で malloc され、 sv が解放されるときに free される

mg_len が 0 のとき、 mg_ptr はそのまま保存される mg_len が HEf_SVKEY のとき、 mg_ptr は SV* と見な

され、 sv_magicext 内で SvREFCNT_inc され、 sv が解放されるときに SvREFCNT_dec される (mg_obj と同じ扱い )

つまり、 mg_obj と mg_ptr+HEf_SVKEY のSVは、 mortalize するか、 sv_magicext のあとに SvREFCNT_dec しなければならない

Page 16: Introduction to Perl MAGIC

PERL_MAGIC_ext の利用

hook methods 挙動が不気味すぎて扱いが難しい

Magic::Watch (on github) に例はあるが… :( 注意事項が沢山ありすぎる

managed data 時代は XS code templates!

Page 17: Introduction to Perl MAGIC

XS code templates (1)

XSUBを動的に生成するメカニズム クロージャのXS版 MAGIC を使って cv にデータを添付する Template (XSUB) + Parameters (MAGIC) Used by

Class::XSAccessor Class::MOP/Moose (future version)

Page 18: Introduction to Perl MAGIC

XS code templates (2)

動的コード生成の方法 eval $subroutine_source_code closure (anonymous subroutine) XS code templates Inline::x86 による JIT

Gen Time Run Time Maintain

eval slow moderate

hard

closure moderate

slow easy

XSt fast fast hard

Inline::x86

fastest fastest hellish

Page 19: Introduction to Perl MAGIC

Example

/* in XS */static MGVTBL xst_id; /* the MAGIC identity */CV* xsub = newXS(name, xs_impl, file);HV* hv = newHV();MAGIC* mg;mg = sv_magic((SV*)xsub, (HV*)hv, PERL_MAGIC_ext,

&xst_id, NULL, 0);SvREFCNT_dec(hv);CvXSUBANY(xsub).any_ptr = (void*)hv; /* shortcut *//* ... */XS(xs_impl){

dVAR; dXSARGS;HV* hv = (HV*)XSANY.any_ptr; /* shortcut *//* ... */

}

Page 20: Introduction to Perl MAGIC

That's all

Enjoy Perl MAGIC! Thank you for your attention.