Upgrade to Pro — share decks privately, control downloads, hide ads and more …

php-srcを読んでみよう / php-src codereading

tzmfreedom
September 24, 2022

php-srcを読んでみよう / php-src codereading

PHP Conference Japan 2022の発表資料です。
https://fortee.jp/phpcon-2022/proposal/1addf51d-6f72-4c96-9337-034ec6cc0643

tzmfreedom

September 24, 2022
Tweet

More Decks by tzmfreedom

Other Decks in Technology

Transcript

  1. ࣗݾ঺հ w ా࣮੣!U[N@GSFFEPN w גࣜձࣾϠϓϦͷαʔόʔαΠυΤϯδχΞ w 1)1ྺ͸ʙ೥͘Β͍ w $ݴޠྺ͸̍೥͘Β͍ʹॳ৺ऀ w

    1)1FS,BJHJͰ͸1)1Ͱ1)1Λ࣮૷ 
 1)1$POGFSFODFͰ͸ಠࣗϑϨʔϜϫʔΫΛվળ 
 1)1FS,BJHJͰ͸1)1Ͱ1)1ͷσόοΨʔΛ࣮૷
  2. 1)1ͷσόοάϏϧυͷํ๏ Ϗϧυ͢ΔͱTBQJDMJQIQʹ1)1ͷ$-*͕࡞੒͞ΕΔ $ git clone [email protected]:php/php-src.git $ cd php-src $

    ./buildconf $ ./configure --enable-opcache --enable-debug $ make -j4 $ sapi/cli/php test.php
  3. ࣮ࡍͷίʔυྫ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *z; SAVE_OPLINE();

    z = RT_CONSTANT(opline, opline->op1); ͑ɺͳΜ͔ηϛίϩϯແ͍Μ͚ͩͲʜʂ ͑ɺܕ͕ϚΫϩʹͳ͍ͬͯΔʜʁ ͑ɺҾ਺Ͳ͏ͳͬͯΜͷʜʂʁ PQMJOF͍ͬͯ͏ม਺ɺͲ͜ʹ΋ఆٛ͞Ε͍ͯͳ͍ͷ͕ͩʜʁʁ
  4. ϚΫϩ͸͜Μͳײ͡Ͱఆٛ͞Ε͍ͯΔ # define ZEND_OPCODE_HANDLER_RET int # define ZEND_FASTCALL # define

    ZEND_OPCODE_HANDLER_ARGS zend_execute_data *execute_data # define USE_OPLINE const zend_op *opline = EX(opline); #define EX(element) ((execute_data)->element)
  5. ల։͢Δͱ͜Μͳײ͡ static int ZEND_ECHO_SPEC_CONST_HANDLER(zend_execute_data *execute_data) { const zend_op *opline =

    ((execute_data)->opline); zval *z; static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *z;
  6. ͜ΜͳϚΫϩ΋͋Δ ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) { //… } ZEND_HASH_FOREACH_END(); do { for(...)

    { { //... } } } while(0) w ։࢝ͷϚΫϩͱऴྃͷϚΫϩͰରʹͳ Δɻ w ͪͳΈʹEPʙXIJMF  ΛೖΕ͍ͯΔͷ ͸JGจͳͲͰෳ਺จͷల։Λͨ͠ͱ͖ʹ ҙਤͨ͠ڍಈʹ͢ΔͨΊ
  7. ίʔϧϑϨʔϜͷϝϞϦ഑ஔྫ w [FOE@FYFDVUF@EBUBม਺ [WBM ʜͱ͍͏ײ͡Ͱ഑ஔ͞Εͯ ͍Δ w ϝϞϦΛಈతʹ֬อͯ͠[FOE@FYFDVUF@EBUBͱ[WBMͷྖҬΛܾΊͯ ഑ஔ 


    [FOE@FYFDVUF@EBUBͷఆ͚ٛͩͰ͸ϝϞϦ഑ஔ͸Θ͔Βͳ͍ [WBM FYFDVUF@EBUB ࣮ߦதͷؔ਺΍0QDPEF౳ΛؚΉߏ଄ମ [WBM ൪໨ͷม਺ ൪໨ͷม਺
  8. 4"1*;FOE&OHJOFͷ֓ཁਤ BQBDIF NPE@QIQ 4"1* ;FOE&OHJOF )551 ϦΫΤετ $-* 4"1* ;FOE&OHJOF

    ίϚϯυ ࣮ߦ OHJOY QIQGQN 4"1* ;FOE&OHJOF )551 ϦΫΤετ
  9. $-*ͷFDIPͷελοΫτϨʔε NBJO TBQJDMJQIQ@DMJD EP@DMJ TBQJDMJQIQ@DMJD QIQ@FYFDVUF@TDSJQU NBJONBJOD [FOE@FYFDVUF@TDSJQUT ;FOE[FOED [FOE@FYFDVUF

    ;FOE[FOE@WN@FYFDVUFI FYFDVUF@FY ;FOE[FOE@WN@FYFDVUFI ;&/%@&$)0@41&$@$0/45@)"/%-&3 ;FOE[FOE@WN@FYFDVUFI 4"1* ;FOE&OHJOF
  10. ࣈ۟ղੳɾߏจղੳͷίʔυ͸ࣗಈੜ੒͞ΕΔ start: top_statement_list { CG(ast) = $1; (void) zendnerrs; }

    ; echo_expr_list: echo_expr_list ',' echo_expr { $$ = zend_ast_list_add($1, $3); } | echo_expr { $$ = zend_ast_create_list(1, ZEND_AST_STMT_LIST, $1); } ; echo_expr: expr { $$ = zend_ast_create(ZEND_AST_ECHO, $1); } ; w ;FOE[FOE@MBOHVBHFZ΍;FOE[FOE@MBOHVBHF@TDBOOFSM͔Β 
 ύʔαʔͷίʔυ͕ࣗಈੜ੒͞ΕΔ
  11. "45͔Β0QDPEFΛੜ੒ [FOE@BTU "[email protected]@-*45 [FOE@BTU "45@"44*(/ [FOE@BTU "45@&$)0 "44*(/ &$)0 $7

    JOU  TUSJOH lIPHFz  PQDPEF PQ PQ   SFTVMU w ωετͨ͠ଟ֊૚ͷߏ଄ମ͔Β̍֊૚ͷߏ଄ମͷ഑ྻʹม׵
  12. ม׵͍ͯ͠Δॲཧͷྫ static void zend_compile_echo(zend_ast *ast) /* {{{ */ { zend_op

    *opline; zend_ast *expr_ast = ast->child[0]; znode expr_node; zend_compile_expr(&expr_node, expr_ast); opline = zend_emit_op(NULL, ZEND_ECHO, &expr_node, NULL); opline->extended_value = 0; } &$)0ͷ0QDPEFΛ࡞੒ w ;FOE[FOE@DPNQJMFDʹ"45͔Β0QDPEFΛੜ੒͢Δؔ਺͕͋Δ
  13. 0QDPEFͷ֬ೝํ๏ w 0QDBDIFͷΦϓγϣϯΛࢦఆ͢Δͱ0QDPEFΛμϯϓͰ͖Δ $ sapi/cli/php -dopcache.opt_debug_level=0x10000 test.php $_main: ; (lines=3,

    args=0, vars=1, tmps=1) ; (before optimizer) ; /Users/nuser/phpconf2022/php-src/test.php:1-5 ; return [] RANGE[0..0] 0000 ASSIGN CV0($i) int(1) 0001 ECHO CV0($i) 0002 RETURN int(1)
  14. 0QDPEFͷ࣮ߦ w 0QDPEFͱΦϖϨʔλͭɺ ݁Ռͷ֨ೲઌ͕ೖ͍ͬͯΔ w 0QDPEFΛ࣮ߦ͢Δϋϯυϥ ʔʢؔ਺ϙΠϯλʣ΋ඥ෇͍ ͍ͯΔ struct _zend_op

    { const void *handler; znode_op op1; znode_op op2; znode_op result; uint32_t extended_value; uint32_t lineno; zend_uchar opcode; zend_uchar op1_type; zend_uchar op2_type; zend_uchar result_type; };
  15. 0QDPEFΛ࣮ߦ͍ͯ͠Δίʔυ while (1) { int ret; if (UNEXPECTED((ret = ((opcode_handler_t)OPLINE-

    >handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)) != 0)) { if (EXPECTED(ret > 0)) { execute_data = EG(current_execute_data); ZEND_VM_LOOP_INTERRUPT_CHECK(); } else { return; } } }
  16. class ast\Node#1 (4) { public $kind => int(132) public $flags

    => int(0) public $lineno => int(1) public $children => array(1) { [0] => class ast\Node#2 (4) { public $kind => int(283) public $flags => int(0) public $lineno => int(1) public $children => array(1) { 'expr' => string(4) "hoge" } } } } w  ;&/%@"[email protected]@-*45 w  ;&/%@"45@&$)0 [FOE@BTU "[email protected]@-*45 [FOE@BTU "45@&$)0 [FOE@BTU@[WBM 
 TUSJOH
  17. ϋϯυϥʔΛ֬ೝ͢Δ w ;FOE[FOE@WN@FYFDVUFIʹఆٛ͞Ε͍ͯΔ w ;&/%@\0QDPEF^@41&$@\Ҿ਺ͷछผ^@)"/%-&3ͱ͍͏໊લʹͳ͍ͬͯΔ w &$)0ͷϋϯυϥʔͰ͸[FOE@XSJUF ؔ਺͕ݺ͹Ε͍ͯΔ static ZEND_OPCODE_HANDLER_RET

    ZEND_FASTCALL ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { // …লུ… if (ZSTR_LEN(str) != 0) { zend_write(ZSTR_VAL(str), ZSTR_LEN(str));
  18. [FOE@XSJUF w ؔ਺ϙΠϯλ w 4"1*ʹΑͬͯηοτ͞ΕΔؔ਺͕มΘΔ w $-*͸ඪ४ग़ྗʹॻ͖ࠐΉ w NPE@QIQ͸BQBDIFͷؔ਺ܦ༝Ͱ)551ϨεϙϯεΛฦ͢ extern

    ZEND_API zend_write_func_t zend_write; typedef size_t (*zend_write_func_t)(const char *str, size_t str_length);