root/docs/yappo/20080625-shibuyapm9/shibuyapm9-pl_check-hacks.pl

Revision 14654, 6.3 kB (checked in by yappo, 6 months ago)

i love PL_check

Line 
1use strict;
2use warnings;
3use utf8;
4use lib 'lib';
5
6use Plusen;
7
8my $p = Plusen->bootstrap({
9    config => {
10        meta  => {
11            title  => "PL_check hacks",
12            author => 'Kazuhiro Osawa - ( Yappo )',
13            email  => 'yappo <at> shibuya <döt> pl',
14        },
15        plugins => [
16            { module => 'ScriptLoader::Simple' },
17#            { module => 'Device::MozRepl', },
18            { module => 'Device::Term', },
19            { module => 'Device::Growl', },
20#            { module => 'Device::ControlFromFile', config => { path => '/tmp/devsumi-ctl.txt' } },
21        ],
22    },
23});
24
25__DATA__
26
27===
28title: XSとは
29
30===
31title: CライブラリとPerlを繋げる物
32
33===
34title: では無くて
35
36===
37title: パッチをあてずにPerlのコアをhackする物である
38
39===
40title: 謝罪
41
42===
43title: XS厨どころかInternal厨でごめんなさい
44
45===
46title: 謝罪おわり
47
48===
49title: 50%くらいtokuhiromとかぶったな
50
51===
52title: PL_checkとはなんぞや
53
54===
55title: what is PL_check?
56list:
57 - 関数のフックテーブル
58 - なんのフック?
59 - 構文チェック的な事担当
60 - BEGINフェーズで実行
61 - 構文チェック的な事担当
62 - BEGINフェーズで実行
63 - 大切な事なので2度言いました
64
65===
66title: 例えばこんなコード書いたら
67code: |
68  use strict;
69  use warnings;
70  my $x;
71  delete $x;
72
73===
74title: delete argument is not a HASH or ARRAY element or slice
75
76===
77title: と怒られますよね
78
79===
80title: この怒ってる部分がPL_checkで登録された関数が出してる
81
82===
83title: 実装はop.cのPerl_ck_delete(pTHX_ OP *o)を見てね
84
85===
86title: こんなの
87code: |
88  OP *
89  Perl_ck_delete(pTHX_ OP *o)
90  {
91    o = ck_fun(o);
92    o->op_private = 0;
93    if (o->op_flags & OPf_KIDS) {
94        OP * const kid = cUNOPo->op_first;
95        switch (kid->op_type) {
96        case OP_ASLICE:
97        o->op_flags |= OPf_SPECIAL;
98            /* FALL THROUGH */
99
100===
101title: つづき
102code: |
103        case OP_HSLICE:
104                o->op_private |= OPpSLICE;
105        break;
106        case OP_AELEM:
107        o->op_flags |= OPf_SPECIAL;
108            /* FALL THROUGH */
109        case OP_HELEM:
110                break;
111
112===
113title: つづき(ここでエラー出す)
114code: |
115      default:
116            Perl_croak(aTHX_ "%s argument is not a HASH or ARRAY element or slice",
117                       OP_DESC(o));
118        }
119        op_null(kid);
120    }
121    return o;
122  }
123
124===
125title: 前ふり終わり、本題に入る
126
127===
128title: tokuhiromの日記見てれば理解できるはずだよ
129
130===
131title: その前にオペコードの構造体の前提知識式だけ
132
133===
134title: OPの定義 see op.h
135code: |
136  struct op {//超抜粋
137   /* 次のオペコード */
138   OP* op_next;
139   /* 兄弟オペコード? ちょっとわからない */
140   OP* op_sibling;
141   /* 実行フェーズで担当する関数 */
142   OP* (CPERLscope(*op_ppaddr))(pTHX);
143   /* バイトコード的なコードの種類 */
144   OPCODE op_type;
145   // 省略
146  }
147
148
149===
150title: OPの定義 see perl.h
151code: |
152  typedef struct op OP;
153
154===
155title: OP は 基本的に OP *o として使うとマクロで扱い易い
156
157===
158title: 何故かというと see op.h
159code: |
160  #define cUNOPo          cUNOPx(o)
161  みたいな定義があるから
162
163===
164title: PL_checkどこで定義されてる?
165list:
166 - opecode.h に乗ってる
167 - このヘッダファイルには
168 - オペコードに対する関数テーブルもある
169 - PL_ppaddr がそれ
170 - OP で定義された変数の名前は
171 - OP_NAME(OP *o)
172 - OP で定義された変数の説明は
173 - OP_DESC(OP *o)
174 - で見れるよ!
175
176
177===
178title: 実際の関数はどこに書いてある?
179list:
180 - わかり易く op.c に書いてある
181 - Perl_ck_ で始まるのがそうだよ
182 - OP *o を受け取ってチェックとかして
183 - 構造体とかいじって、OP *oを返す
184 - この時 o->op_next は存在しない(はず)
185 - なぜなら
186 - BEGINフェーズで準備出来てないから
187
188===
189title: ここ迄の知識さえあればPL_checkを書き換えてautoboxみたいなのが作れる!
190
191===
192title: PL_checkを書き換える事、すなわちPerlのコアに麻薬を打ち込んであり得ない幻覚症状を引き起こす
193
194===
195title: そのためには、どのオペコードがどういう役割を持っているかを熟知してる必要がある
196
197===
198title: 俺は熟知して無い
199
200===
201title: オペコード一覧はperl-users.jpのエキスパートPerlに置いてある
202
203===
204title: http://perl-users.jp/expert_perl/op.html
205
206===
207title: PL_check のついでに ppaddr (PL_ppaddr) について
208
209===
210title: ppaddr概要
211list:
212 - オペコード毎に指定されてる
213 - OP で言う所の o->op_ppaddr
214 - 実行フェーズでは、これに登録されてる関数を
215 - オペコードの実際の処理として処理する
216 - 実際は pp.c や pp_*.c に関数定義されてる
217 - OP_ENTERSUB なら PP(pp_entersub) {} な感じ
218
219===
220title: ppaddrのhack
221list:
222 - OP * ppaddr_hack(pTHX) {}
223 - こんな感じで pTHX 受け取って OP *o 返す
224 - 返す o は次に実行するオペコード
225 - とは言っても、返す o は自分で作んない方がよい
226 - 今実行してるオペコードは PL_op で取る
227
228===
229title: ppaddrまとめ
230list:
231 - PL_checkはPerlコア全体に影響があるが
232 - ppaddrはhackしても影響範囲が
233 - 特定のオペコードのみという特性がある
234 - 特定のクロージャ関数だけ実行方法を
235 - 変えるhackとかが出来る
236
237===
238title: そういうhackをちょっとやってみてる(まだ動かない><)
239
240===
241title: http://svn.coderepos.org/share/dan/perl/Object-with/branches/yappo/
242
243===
244title: ppaddrの使い方(超略例)
245code: |
246  static OP *(*next_bak)(pTHX_ OP *op) = NULL;
247  OP * ppaddr_hack(pTHX) {
248    PerlIO_printf(PerlIO_stderr(), "わーい\n");
249    return PL_ppaddr[PL_op->op_type](aTHX);
250  }
251  OP * hack_next(pTHX_ OP *o) {
252    o->op_ppaddr = ppaddr_hack;
253    return CALL_FPTR(next_bak)(aTHX_ o);
254  }
255
256===
257title: ppaddrの使い方(超略例)XS部分
258code: |
259  BOOT:
260  next_bak = PL_check[OP_NEXT];
261  PL_check[OP_NEXT] = hack_next;
262
263===
264title: これを使うとPerl の next を実行するたびに「わーい」と表示されてうざくなります
265
266
267===
268title:
269
270===
271title: 実際のコードを見ながら説明する時間があれば?
272
273===
274title: http://svn.coderepos.org/share/dan/perl/PL_check/trunk/
275
276===
277title: 以上です、ご清聴ありがとうございました
Note: See TracBrowser for help on using the browser.