Slide 1

Slide 1 text

Copyright© M&AΫϥ΢υ PHPͷ؇΍͔ͳൺֱͷ࣮ଶ PHPerKaigi 2022

Slide 2

Slide 2 text

Copyright© M&AΫϥ΢υ 2 Profile גࣜձࣾM&AΫϥ΢υ ᅳଜʢΏ͍ʣ fyui001 @fyui_001

Slide 3

Slide 3 text

Copyright© M&AΫϥ΢υ 3 ֓ཁ PHPʹ͸౳Ձԋࢉࢠ͕2ͭ͋Γ·͢ɻʮ==ʯͱʮ===ʯͰ͢ɻ લऀ͸؇΍͔ͳൺֱɺޙऀ͸ݫີͳൺֱ͕ߦΘΕ·͢ɻ PHPerͷํͳΒΑ͘͝ଘ஌ͩͱࢥ͍·͢ɻ ࠓճ͸લऀͷ؇΍͔ͳൺֱΛ࣮ଶ͕Ͳ͏ͳ͍ͬͯΔͷ͔Λ௥ͬͯݟ͍ͨͱࢥ͍·͢ɻ

Slide 4

Slide 4 text

Copyright© M&AΫϥ΢υ 4 ؇΍͔ͳൺֱͷΧΦε͞ ྫ:

Slide 5

Slide 5 text

Copyright© M&AΫϥ΢υ 5 ؇΍͔ͳൺֱͷΧΦε͞ ͸͍ɺҙຯΘ͔Γ·ͤΜɻ 1, 2ߦ໨͸ཧղͰ͖ͳ͍͜ͱ΋͋Γ·ͤΜ͕ 3ߦ໨͕ԿނtrueʹͳΔͷ͔ɺݫີʹઆ໌͢Δʹ͸Ͳ͏ͨ͠Β͍͍Ͱ͠ΐ ͏͔ɻ ͜ͷൃදΛฉ͍ͯཧղ͠આ໌Ͱ͖ΔΑ͏ʹͳͬͯ໯͑Ε͹خ͍͠Ͱ͢ɻ

Slide 6

Slide 6 text

Copyright© M&AΫϥ΢υ 6 ؇΍͔ͳൺֱͷ࣮ମ͸Ͳ͜ʹ͋Δͷ͔ ݴޠ࢓༷ʹؔ͢Δઆ໌͸υΩϡϝϯτΛಡΊ͹ྑ͍ͷͰ͕͢ɺ ࠷΋ਖ਼֬ͳυΩϡϝϯτ͸ԿͰ͠ΐ͏ɻ ͦΕ͸ιʔείʔυͰ͢ɻ ιʔείʔυͱͦΕΛઆ໌͍ͯ͠ΔυΩϡϝϯτʹࠩҟ͕͋ͬͯ΋ɺͦ ͷιʔείʔυͰಈ͍͍ͯΔҎ্͸ιʔείʔυ͕ਖ਼֬ͳυΩϡϝϯτ ʹͳΓ·͢ɻ PHPͷ؇΍͔ͳൺֱΛߦ͍ͬͯΔιʔείʔυຊମΛݟͯΈ·͠ΐ͏ɻ

Slide 7

Slide 7 text

Copyright© M&AΫϥ΢υ 7 ؇΍͔ͳൺֱͷ࣮ମ͸Ͳ͜ʹ͋Δͷ͔ ࠓճ͸PHP8.0.9ͷιʔείʔυΛಡΜͰ͍͜͏ͱࢥ͍·͢ɻ

Slide 8

Slide 8 text

Copyright© M&AΫϥ΢υ 8 ιʔείʔυͷམͱ͠ํ ·ͣ͸ී௨ʹgit clone͠·͢ git clone https://github.com/php/php-src

Slide 9

Slide 9 text

Copyright© M&AΫϥ΢υ 9 ιʔείʔυͷམͱ͠ํ ࠓͷphp-srcͷ࠷৽͸PHP8.1.4ͷRCʹͳ͍ͬͯΔͷͰɺ8.0.9ʹΞοϓ σʔτ͞ΕͨίϛοτΛಛఆͯ͠νΣοΫΞ΢τͯ͋͛͠·͢ɻ git checkout a5368c55be0a42af9fdc2c76fb0c2a06a42ddf36

Slide 10

Slide 10 text

Copyright© M&AΫϥ΢υ 10 PHPͷ؇΍͔ͳൺֱͷ࣮ଶ ʊਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓʊ ʼɹPHPͷ؇΍͔ͳൺֱ͸ಈ࡞Λݫີʹઆ໌Ͱ͖Δਓ͔͠࢖ͬͯ͸͍͚·ͤΜɻɹʻ ʉY^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^ ʉ

Slide 11

Slide 11 text

Copyright© M&AΫϥ΢υ 11 ֘౰ιʔεʹḷΓண͘ํ๏ ϊʔώϯτͰPHPͷιʔείʔυΛಡΜͰ΋ɺ໨తͷ৔ॴʹͨͲΓண ͚ͳ͚Ε͹ҙຯ͕͋Γ·ͤΜɻ ݴޠಛ༗ͷԋࢉࢠΛจࣈྻͰgrep΍IDEͷϑΝΠϧݕࡧΛͯ͠Έ·͢ɻ ࠓճ͸Ӊ஦ધԋࢉࢠ(<=>)Ͱݕࡧͯ͠Έ·͢ɻ

Slide 12

Slide 12 text

Copyright© M&AΫϥ΢υ 12 ֘౰ιʔεʹḷΓண͘ํ๏ ͳΜ͔ͦΕͬΆ͍ϑΝΠϧ͕ݟ͔ͭΓ·ͨ͠ɻ PHPͷԋࢉࢠΛจࣈྻͱͯ͠ఆ͍ٛͯ͠Δࠜຊ͸Zend/ zend_language_parser.yʹ͋Γͦ͏Ͱ͢ɻ ※.yͷ֦ுࢠͷϑΝΠϧ͸ߏจղੳػΛੜ੒͢ΔͨΊʹɺYaccͱݴ͏πʔ ϧͷϑΝΠϧͷԋࢉࢠͰ͢ɻ Zend/zend_language_parser.yΛ։͍ͯΈ·͢ɻ

Slide 13

Slide 13 text

Copyright© M&AΫϥ΢υ 13 ֘౰ιʔεʹḷΓண͘ํ๏ Ӊ஦ધԋࢉࢠͷ্͙͢ʹո͍͠ߦ͕͋Γ·ͨ͠ɻ ໨తͷʮ==ʯ͸T_IS_EQUALͱ͍͏໊લ͕෇͍͍ͯΔΈ͍ͨͰ͢ɻ Zend/zend_language_parser.y಺ͰT_IS_EQUALΛݕࡧ͢Δͱ

Slide 14

Slide 14 text

Copyright© M&AΫϥ΢υ 14 ֘౰ιʔεʹḷΓண͘ํ๏ ͜Μͳιʔε͕ݟ͔ͭΓ·͢ɻ Ͳ͏΍ΒZEND_IS_EQUALͱ͍͏໊લͰதؒίʔυʹม׵͞ΕΔΈͨ ͍Ͱ͢ɻ

Slide 15

Slide 15 text

Copyright© M&AΫϥ΢υ 15 ZEND_IS_EQUALͱݴ͏ϫʔυΛෳ਺ϑΝΠϧݕࡧ͢Δͱɺ Zend/zend_opcode.cʹ͜Μͳߦ͕͋Γ·ͨ͠ case ZEND_IS_EQUAL:

Slide 16

Slide 16 text

Copyright© M&AΫϥ΢υ 16 Zend/zend_opcode.cͷத਎ END_API binary_op_type get_binary_op(int opcode) { switch (opcode) { /* ~~~~~~~~~~ */ case ZEND_IS_EQUAL: case ZEND_CASE: return (binary_op_type) is_equal_function; case ZEND_IS_NOT_EQUAL: return (binary_op_type) is_not_equal_function; /* ~~~~~~~~~~ */ default: ZEND_UNREACHABLE(); return (binary_op_type) NULL; } } ͜Μͳͷ͕͍·ͨ͠ɻ ZEND_IS_EQUAL͸is_equal_functionͱ͍͏ؔ਺ʹରԠ͍ͯ͠ΔΑ͏Ͱ͢Ͷɻ is_equal_functionͰݕࡧΛ͔͚ͯΈ·͢ɻ

Slide 17

Slide 17 text

Copyright© M&AΫϥ΢υ 17 is_equal_functionͰݕࡧΛ͔͚ͯΈΔ ZEND_API int ZEND_FASTCALL is_equal_function(zval *result, zval *op1, zval *op2) Zend/zend_operators.cʹḷΓண͖·ͨ͠ɻ ϊʔώϯτͰ΋ɺIDEͷϑΝΠϧݕࡧͰେͨ࣌ؒ͠Λ͔͚ͣʹ΄͍͠ ৘ใ·ͰḷΓண͚·͢ɻ ϥΠϒϥϦͷத਎Λௐ΂͍ͨͱ͖౳ʹ΋࢖͑ΔͷͰࢀߟʹͯ͠Έͯ͘ ͍ͩ͞ɻ

Slide 18

Slide 18 text

Copyright© M&AΫϥ΢υ 18 ؇΍͔ͳൺֱͷਖ਼ମݟͨΓʂ is_equal_function͸zend_compareͱݴ͏ؔ਺ʹରԠ͍ͯ͠ΔΑ͏Ͱ͢ɻ /* == ͷॲཧ */ ZEND_API zend_result ZEND_FASTCALL is_equal_function(zval *result, zval *op1, zval *op2) /* {{{ */ { ZVAL_BOOL(result, zend_compare(op1, op2) == 0); return SUCCESS; } /* }}} */

Slide 19

Slide 19 text

Copyright© M&AΫϥ΢υ 19 ؇΍͔ͳൺֱͷਖ਼ମݟͨΓʂ ZEND_API int ZEND_FASTCALL zend_compare(zval *op1, zval *op2) /* {{{ */ { int converted = 0; zval op1_copy, op2_copy; while (1) { switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { case TYPE_PAIR(IS_LONG, IS_LONG): return Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)

Slide 20

Slide 20 text

Copyright© M&AΫϥ΢υ 20 ؇΍͔ͳൺֱͷਖ਼ମݟͨΓʂ ௕͍... ΋͏ͳΜ͔ΠϠͳ༧ײ͕͠·͢Ͷɻ த਎Λཁ໿͍ͯ͘͠ͱɺԋࢉࢠͷࠨӈͷΦϖϥϯυͷܕͷ૊Έ߹ΘͤʹԠͯ͡ɺ ྑ͍ײ͡ʹॲཧΛ෼ذͯ͠ฦ͍ͯ͠ΔΈ͍ͨͰ͢ɻ ਺஋ಉ࢜ͷൺֱ͸ී௨ʹߦΘΕ͍ͯ·͕͢ɺจࣈྻͷൺֱ͸ͳΜ͔ؔ਺͕ݺ͹Εͯ·͢ɻ case TYPE_PAIR(IS_STRING, IS_STRING): if (Z_STR_P(op1) == Z_STR_P(op2)) { return 0; } return zendi_smart_strcmp(Z_STR_P(op1), Z_STR_P(op2)); zendi_smart_strcmpͱݴ͏ո͍ؔ͠਺͕ݺ͹Ε͍ͯ·͢ɻ ͲΜͳౕ͔ݟͯΈ·͠ΐ͏ɻ

Slide 21

Slide 21 text

Copyright© M&AΫϥ΢υ 21 zendi_smart_strcmpͱݴ͏ո͍ؔ͠਺ ZEND_API int ZEND_FASTCALL zendi_smart_strcmp(zend_string *s1, zend_string *s2) /* {{{ */ { zend_uchar ret1, ret2; int oflow1, oflow2; zend_long lval1 = 0, lval2 = 0; double dval1 = 0.0, dval2 = 0.0; if ((ret1 = is_numeric_string_ex(s1->val, s1->len, &lval1, &dval1, false, &oflow1, NULL)) && (ret2 = is_numeric_string_ex(s2->val, s2->len, &lval2, &dval2, false, &oflow2, NULL))) { #if ZEND_ULONG_MAX == 0xFFFFFFFF if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0. && ((oflow1 == 1 && dval1 > 9007199254740991. /*0x1FFFFFFFFFFFFF*/) || (oflow1 == -1 && dval1 < -9007199254740991.))) { #else if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0.) { #endif /* both values are integers overflown to the same side, and the * double comparison may have resulted in crucial accuracy lost */ goto string_cmp; } if ((ret1 == IS_DOUBLE) || (ret2 == IS_DOUBLE)) { if (ret1 != IS_DOUBLE) { if (oflow2) { /* 2nd operand is integer > LONG_MAX (oflow2==1) or < LONG_MIN (-1) */ return -1 * oflow2; } dval1 = (double) lval1; } else if (ret2 != IS_DOUBLE) { if (oflow1) { return oflow1; } dval2 = (double) lval2; } else if (dval1 == dval2 && !zend_finite(dval1)) { /* Both values overflowed and have the same sign, * so a numeric comparison would be inaccurate */ goto string_cmp; } dval1 = dval1 - dval2; return ZEND_NORMALIZE_BOOL(dval1); } else { /* they both have to be long's */ return lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0); } } else { int strcmp_ret; string_cmp: strcmp_ret = zend_binary_strcmp(s1->val, s1->len, s2->val, s2->len); return ZEND_NORMALIZE_BOOL(strcmp_ret); } } /* }}} */

Slide 22

Slide 22 text

Copyright© M&AΫϥ΢υ 22 zendi_smart_strcmpͱݴ͏ո͍ؔ͠਺ ͏͑ʙ ॲཧͷ಺༰͸ɺ ● ೖྗ͞Εͨจࣈྻ͕ʮ਺஋ͱͯ͠ධՁͰ͖Δ৔߹͸਺஋ͱͯ͠ѻ͍ൺֱ͢Δʯ ● ਺஋ͱͯ͠ධՁग़དྷͳ͍৔߹͸จࣈྻಉ࢜ͷൺֱΛߦ͏ strcmp໋໊ͬͯ͸ͳΜͳΜͩ... ͭ·Γstrcmpͱ͸໊͹͔ΓͰɺจࣈྻͱͯ͠ҟͳ͍ͬͯͯ΋਺஋ͱͯ͠߹͍ͬͯΕ͹ true Ͱ͢ɻ ୭ͩ͜ΜͳΫιΈ͍ͨͳ࢓༷ࢥ͍͍ͭͨ΍ͭʙ

Slide 23

Slide 23 text

Copyright© M&AΫϥ΢υ 23 PHPͷ؇΍͔ͳൺֱͷ࣮ଶ ͜ΕΛ౿·͑ͯ΋͏Ұ౓ίʔυΛݟͯΈ·͠ΐ͏ ιʔείʔυɿ

Slide 24

Slide 24 text

Copyright© M&AΫϥ΢υ 24 ݫີͳൺֱͷιʔε͸Ͳ͜ʁ Zend/zend_operators.cʹ͍·͢ɻ ZEND_API zend_bool ZEND_FASTCALL zend_is_identical(zval *op1, zval *op2) /* {{{ */ { if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { return 0; } switch (Z_TYPE_P(op1)) { case IS_NULL: case IS_FALSE: case IS_TRUE: return 1; case IS_LONG: return (Z_LVAL_P(op1) == Z_LVAL_P(op2)); case IS_RESOURCE: return (Z_RES_P(op1) == Z_RES_P(op2)); case IS_DOUBLE: return (Z_DVAL_P(op1) == Z_DVAL_P(op2)); case IS_STRING: return zend_string_equals(Z_STR_P(op1), Z_STR_P(op2)); case IS_ARRAY: return (Z_ARRVAL_P(op1) == Z_ARRVAL_P(op2) || zend_hash_compare(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2), (compare_func_t) hash_zval_identical_function, 1) == 0); case IS_OBJECT: return (Z_OBJ_P(op1) == Z_OBJ_P(op2)); default: return 0; } } /* }}} */

Slide 25

Slide 25 text

Copyright© M&AΫϥ΢υ 25 ݫີͳൺֱͷιʔε͸Ͳ͜ʁ ·ͣ࠷ॳʹܕҧ͍ͰfalseʹͳΓ·͢ɻ ܕ͕Ұக্ͨ͠ͰɺͦΕͧΕͷܕͰγϯϓϧͳൺֱΛ͍ͯ͠·͢ɻ ʮ==ʯͷιʔείʔυΑΓང͔ʹγϯϓϧͰ͢ɻ

Slide 26

Slide 26 text

Copyright© M&AΫϥ΢υ 26 ͍͞͝ʹ ࣗ෼΋ࠓ·ͰͳΜͱͳ͘Ͱ͔͠ɺཧղͯ͠ͳ͔ͬͨͰ͕͢ɺࠓճͷௐ ࠪͰͲΕ͚ͩةݥͳ୅෺͔Α͘ཧղͰ͖·ͨ͠ɻ օ͞ΜPHPͷൺֱԋࢉࢠ͸໧ͬͯݫ֨ͳൺֱΛ࢖͍·͠ΐ͏ɻ

Slide 27

Slide 27 text

Copyright© M&AΫϥ΢υ ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ 27