opcode.h
opcode.hには、それぞれのオペレーションに関する情報が記載されている。Perl言語研究では、「OP型」のデータのことを、オペレーションと呼ぶことにしています。Perlは、構文解析が終わると、構文木に変換されますが、このそれぞれのノードは「OP型」になっています。
オペレーションは、オペレーションコードによって、分類され、それぞれが情報を持ちます。その情報が記述されています。
オペレーションの名前
たとえば、オペレーションの名前が記述されています。
EXTCONST char* const PL_op_name[] = {
"null",
"stub",
"scalar",
"pushmark",
"wantarray",
"const",
"gvsv",
...
};
=====
オペレーションの解説
次に、オペレーションの解説が記述されています。
EXTCONST char* const PL_op_desc[] = {
"null operation",
"stub",
"scalar",
"pushmark",
"wantarray",
"constant item",
"scalar variable",
"glob value",
...
};
オペレーションが実行する関数のアドレス
各オペレーションは、対応する関数がありますが、その関数へのアドレスが記述されています。
EXT Perl_ppaddr_t PL_ppaddr[] /* or perlvars.h */
# endif
#endif /* PERL_GLOBAL_STRUCT */
#if (defined(DOINIT) && !defined(PERL_GLOBAL_STRUCT)) || defined(PERL_GLOBAL_STRUCT_INIT)
# define PERL_PPADDR_INITED
= {
Perl_pp_null,
Perl_pp_stub,
Perl_pp_scalar, /* implemented by Perl_pp_null */
Perl_pp_pushmark,
Perl_pp_wantarray,
Perl_pp_const,
Perl_pp_gvsv,
Perl_pp_gv,
...
}
「pp」というプレフィックスは、「push pop」という意味で、実行される関数は、引数スタックを操作する関数です。
オペレーションの最適化を行う関数
各オペレーションは「ck」というプレフィックスがつく関数で、最適化されます。その関数のアドレスが記述されています。「ck」は「check」の略です。
#if (defined(DOINIT) && !defined(PERL_GLOBAL_STRUCT)) || defined(PERL_GLOBAL_STRUCT_INIT)
# define PERL_CHECK_INITED
= {
Perl_ck_null, /* null */
Perl_ck_null, /* stub */
Perl_ck_fun, /* scalar */
Perl_ck_null, /* pushmark */
Perl_ck_null, /* wantarray */
Perl_ck_svconst, /* const */
Perl_ck_null, /* gvsv */
};
関数の引数の情報
実行される関数の引数情報が、記述されています。
EXTCONST U32 PL_opargs[] = {
0x00000000, /* null */
0x00000000, /* stub */
0x00001b04, /* scalar */
0x00000004, /* pushmark */
0x00000004, /* wantarray */
0x00000604, /* const */
0x00000644, /* gvsv */
0x00000644, /* gv */
...
};
これは、数値で記述されていて、なにがなんだかわかりませんね。これは「op.h」で定義されています。上記の値は、以下の値の、ビット演算の論理和の値です。
/* op.h */ /* Lowest byte of PL_opargs */ #define OA_MARK 1 #define OA_FOLDCONST 2 #define OA_RETSCALAR 4 #define OA_TARGET 8 #define OA_TARGLEX 16 #define OA_OTHERINT 32 #define OA_DANGEROUS 64 #define OA_DEFGV 128 /* The next 4 bits (8..11) encode op class information */ #define OCSHIFT 8 #define OA_CLASS_MASK (15 << OCSHIFT) #define OA_BASEOP (0 << OCSHIFT) #define OA_UNOP (1 << OCSHIFT) #define OA_BINOP (2 << OCSHIFT) #define OA_LOGOP (3 << OCSHIFT) #define OA_LISTOP (4 << OCSHIFT) #define OA_PMOP (5 << OCSHIFT) #define OA_SVOP (6 << OCSHIFT) #define OA_PADOP (7 << OCSHIFT) #define OA_PVOP_OR_SVOP (8 << OCSHIFT) #define OA_LOOP (9 << OCSHIFT) #define OA_COP (10 << OCSHIFT) #define OA_BASEOP_OR_UNOP (11 << OCSHIFT) #define OA_FILESTATOP (12 << OCSHIFT) #define OA_LOOPEXOP (13 << OCSHIFT) #define OA_METHOP (14 << OCSHIFT) #define OA_UNOP_AUX (15 << OCSHIFT) /* Each remaining nybble of PL_opargs (i.e. bits 12..15, 16..19 etc) * encode the type for each arg */ #define OASHIFT 12 #define OA_SCALAR 1 #define OA_LIST 2 #define OA_AVREF 3 #define OA_HVREF 4 #define OA_CVREF 5 #define OA_FILEREF 6 #define OA_SCALARREF 7 #define OA_OPTIONAL 8
そして、上記には、この値の説明がありませんが、それは「regen/opcodes」にあります。
# Other options are: # needs stack mark - m (OA_MARK) # needs constant folding - f (OA_FOLDCONST) # produces a scalar - s (OA_RETSCALAR) # produces an integer - i (unused) # needs a target - t (OA_TARGET) # target can be in a pad - T (OA_TARGET|OA_TARGLEX) # has a corresponding integer version - I (OA_OTHERINT) # make temp copy in list assignment - d (OA_DANGEROUS) # uses $_ if no argument given - u (OA_DEFGV)
オペレーションに関するプライベートなフラグ
そして、オペレーションに関するプライベートなフラグ情報があります。これらの詳細な説明は「regen/op_private」にあります。
#define OPpLVREF_SV 0x00 #define OPpARG1_MASK 0x01 #define OPpCOREARGS_DEREF1 0x01 #define OPpENTERSUB_INARGS 0x01 #define OPpSORT_NUMERIC 0x01 #define OPpTRANS_FROM_UTF 0x01 #define OPpCONST_NOVER 0x02 #define OPpCOREARGS_DEREF2 0x02 #define OPpEVAL_HAS_HH 0x02 #define OPpFT_ACCESS 0x02 #define OPpHINT_STRICT_REFS 0x02 #define OPpITER_REVERSED 0x02 ...
Perlゼミ

