ÒªÀí½â±¾ÎÄ£¬ÄãÓ¦¸Ã¶Ô PHP5 ÖбäÁ¿µÄʵÏÖÓÐÁËһЩÁ˽⣬±¾ÎÄÖØµãÔÚÓÚ½âÊÍ PHP7 ÖÐ zval µÄ±ä»¯¡£
µÚÒ»²¿·Ö½²ÁË PHP5 ºÍ PHP7 ÖйØÓÚ±äÁ¿×î»ù´¡µÄʵÏֺͱ仯¡£ÕâÀïÔÙÖØ¸´Ò»Ï£¬Ö÷ÒªµÄ±ä»¯¾ÍÊÇ zval ²»ÔÙµ¥¶À·ÖÅäÄڴ棬²»×Ô¼º´æ´¢ÒýÓüÆÊý¡£ÕûÐ͸¡µãÐ͵ȼòµ¥ÀàÐÍÖ±½Ó´æ´¢ÔÚ zval ÖС£¸´ÔÓÀàÐÍÔòͨ¹ýÖ¸ÕëÖ¸ÏòÒ»¸ö¶ÀÁ¢µÄ½á¹¹Ìå¡£
¸´Ô zval Êý¾ÝÖµÓÐÒ»¸ö¹²Í¬µÄÍ·£¬Æä½á¹¹ÓÉ zend_refcounted ¶¨Ò壺
struct _zend_refcounted { uint32_t refcount; union { struct { ZEND_ENDIAN_LOHI_3( zend_uchar type, zend_uchar flags, uint16_t gc_info) } v; uint32_t type_info; } u; }; |
Õâ¸öÍ·´æ´¢ÓÐ refcount£¨ÒýÓüÆÊý£©£¬ÖµµÄÀàÐÍ type ºÍÑ»·»ØÊÕµÄÏà¹ØÐÅÏ¢ gc_info ÒÔ¼°ÀàÐͱê־λ flags¡£
½ÓÏÂÀ´»á¶ÔÿÖÖ¸´ÔÓÀàÐ͵ÄʵÏÖµ¥¶À½øÐзÖÎö²¢ºÍ PHP5 µÄʵÏÖ½øÐбȽϡ£ÒýÓÃËäȻҲÊôÓÚ¸´ÔÓÀàÐÍ£¬µ«ÊÇÉÏÒ»²¿·ÖÒѾ½éÉܹýÁË£¬ÕâÀï¾Í²»ÔÙ׸Êö¡£ÁíÍâÕâÀïÒ²²»»á½²µ½×ÊÔ´ÀàÐÍ£¨ÒòΪ×÷Õß¾õµÃ×ÊÔ´ÀàÐÍûʲôºÃ½²µÄ£©¡£
×Ö·û´®
PHP7 Öж¨ÒåÁËÒ»¸öеĽṹÌå zend_string ÓÃÓÚ´æ´¢×Ö·û´®±äÁ¿£º
struct _zend_string { zend_refcounted gc; zend_ulong h; /* hash value */ size_t len; char val[1]; }; |
³ýÁËÒýÓüÆÊýµÄÍ·ÒÔÍ⣬×Ö·û´®»¹°üº¬¹þÏ£»º´æ h£¬×Ö·û´®³¤¶È len ÒÔ¼°×Ö·û´®µÄÖµ val¡£¹þÏ£»º´æµÄ´æÔÚÊÇΪÁË·ÀֹʹÓÃ×Ö·û´®×öΪ hashtable µÄ key ÔÚ²éÕÒʱÐèÒªÖØ¸´¼ÆËãÆä¹þÏ£Öµ£¬ËùÒÔÕâ¸öÔÚʹÓÃ֮ǰ¾Í¶ÔÆä½øÐгõʼ»¯¡£
Èç¹ûÄã¶Ô C ÓïÑÔÁ˽âµÄ²»ÊǺÜÉîÈëµÄ»°£¬¿ÉÄÜ»á¾õµÃ val µÄ¶¨ÒåÓÐÐ©Ææ¹Ö£ºÕâ¸öÉùÃ÷Ö»ÓÐÒ»¸öÔªËØ£¬µ«ÊÇÏÔÈ»ÎÒÃÇÏë´æ´¢µÄ×Ö·û´®³¥¸¶¿Ï¶¨´óÓÚÒ»¸ö×Ö·ûµÄ³¤¶È¡£ÕâÀïÆäʵʹÓõÄÊǽṹÌåµÄÒ»¸ö¡ººÚ¡»·½·¨£ºÔÚÉùÃ÷Êý×éʱֻ¶¨ÒåÒ»¸öÔªËØ£¬µ«ÊÇʵ¼Ê´´½¨ zend_string ʱÔÙ·ÖÅä×ã¹»µÄÄÚ´æÀ´´æ´¢Õû¸ö×Ö·û´®¡£ÕâÑùÎÒÃÇ»¹ÊÇ¿ÉÒÔͨ¹ý val ·ÃÎÊÍêÕûµÄ×Ö·û´®¡£
µ±È»ÕâÊôÓڷdz£¹æµÄʵÏÖÊֶΣ¬ÒòΪÎÒÃÇʵ¼ÊµÄ¶ÁºÍдµÄÄÚÈݶ¼³¬¹ýÁ˵¥×Ö·ûÊý×éµÄ±ß½ç¡£µ«ÊÇ C ÓïÑÔ±àÒëÆ÷È´²»ÖªµÀÄãÊÇÕâô×öµÄ¡£ËäÈ» C99 Ò²ÔøÃ÷È·¹æ¶¨¹ýÖ§³Ö¡ºÈáÐÔÊý×é¡»£¬µ«ÊǸÐлÎÒÃǵĺÃÅóÓÑ΢Èí£¬Ã»ÈËÄÜÔÚ²»Í¬µÄƽ̨Éϱ£Ö¤ C99 µÄÒ»ÖÂÐÔ£¨ËùÒÔÕâÖÖÊÖ¶ÎÊÇΪÁ˽â¾ö Windows ƽ̨ÏÂÈáÐÔÊý×éµÄÖ§³ÖÎÊÌ⣩¡£
еÄ×Ö·û´®ÀàÐ͵Ľṹ±ÈÔÉúµÄ C ×Ö·û´®¸ü·½±ãʹÓ㺵ÚÒ»ÊÇÒòΪֱ½Ó´æ´¢ÁË×Ö·û´®µÄ³¤¶È£¬ÕâÑù¾Í²»ÓÃÿ´ÎʹÓÃʱ¶¼È¥¼ÆËã¡£µÚ¶þÊÇ×Ö·û´®Ò²ÓÐÒýÓüÆÊýµÄÍ·£¬ÕâÑùÒ²¾Í¿ÉÒÔÔÚ²»Í¬µÄµØ·½¹²Ïí×Ö·û´®±¾Éí¶øÎÞÐèʹÓà zval¡£Ò»¸ö¾³£Ê¹Óõĵط½¾ÍÊǹ²Ïí hashtable µÄ key¡£
µ«ÊÇеÄ×Ö·û´®ÀàÐÍÒ²ÓÐÒ»¸öºÜ²»ºÃµÄµØ·½£ºËäÈ»¿ÉÒԺܷ½±ãµÄ´Ó zend_string ÖÐÈ¡³ö C ×Ö·û´®£¨Ê¹Óà str->val ¼´¿É£©£¬µ«·´¹ýÀ´£¬Èç¹û½« C ×Ö·û´®±ä³É zend_string ¾ÍÐèÒªÏÈ·ÖÅä zend_string ÐèÒªµÄÄڴ棬ÔÙ½«×Ö·û´®¸´ÖƵ½ zend_string ÖС£ÕâÔÚʵ¼ÊʹÓõĹý³ÌÖв¢²»ÊǺܷ½±ã¡£
×Ö·û´®Ò²ÓÐÒ»Ð©ÌØÓеıêÖ¾£¨´æ´¢ÔÚ GC µÄ±ê־λÖеģ©£º
#define IS_STR_PERSISTENT (1 /* allocated using malloc */ #define IS_STR_INTERNED (1 /* interned string */ #define IS_STR_PERMANENT (1 /* interned string surviving request boundary */ |
³Ö¾Ã»¯µÄ×Ö·û´®ÐèÒªµÄÄÚ´æÖ±½Ó´Óϵͳ±¾Éí·ÖÅä¶ø²»ÊÇ zend ÄÚ´æ¹ÜÀíÆ÷£¨ZMM£©£¬ÕâÑùËü¾Í¿ÉÒÔÒ»Ö±´æÔÚ¶ø²»ÊÇÖ»ÔÚµ¥´ÎÇëÇóÖÐÓÐЧ¡£¸øÕâÖÖÌØÊâµÄ·ÖÅä´òÉϱê¼Ç±ãÓÚ zval ʹÓó־û¯×Ö·û´®¡£ÔÚ PHP5 Öв¢²»ÊÇÕâÑù´¦ÀíµÄ£¬ÊÇÔÚʹÓÃǰ¸´ÖÆÒ»·Ýµ½ ZMM ÖС£
±£Áô×Ö·û£¨interned strings£©ÓеãÌØÊ⣬Ëü»áÒ»Ö±´æÔÚÖ±µ½ÇëÇó½áÊøÊ±²ÅÏú»Ù£¬ËùÒÔÒ²¾ÍÎÞÐè½øÐÐÒýÓüÆÊý¡£±£Áô×Ö·û´®Ò²²»¿ÉÖØ¸´£¨duplicate£©£¬ËùÒÔÔÚ´´½¨Ðµı£Áô×Ö·ûʱҲ»áÏȼì²éÊÇ·ñÓÐͬÑù×Ö·ûµÄÒѾ´æÔÚ¡£ËùÓÐ PHP Ô´ÂëÖв»¿É±äµÄ×Ö·û´®¶¼ÊDZ£Áô×Ö·û£¨°üÀ¨×Ö·û´®³£Á¿¡¢±äÁ¿Ãûº¯ÊýÃûµÈ£©¡£³Ö¾Ã»¯×Ö·û´®Ò²ÊÇÇëÇó¿ªÊ¼Ö®Ç°ÒѾ´´½¨ºÃµÄ±£Áô×Ö·û¡£µ«ÆÕͨµÄ±£Áô×Ö·ûÔÚÇëÇó½áÊøºó»áÏú»Ù£¬³Ö¾Ã»¯×Ö·û´®È´Ê¼ÖÕ´æÔÚ¡£
Èç¹ûʹÓÃÁË opcache µÄ»°±£Áô×Ö·û»á±»´æ´¢ÔÚ¹²ÏíÄڴ棨SHM£©ÖÐÕâÑù¾Í¿ÉÒÔÔÚËùÓÐ PHP ½ø³ÌÖʼ칲Ïí¡£ÕâÖÖÇé¿öϳ־û¯×Ö·û´®Ò²¾ÍûÓдæÔÚµÄÒâÒåÁË£¬ÒòΪ±£Áô×Ö·ûÒ²ÊDz»»á±»Ïú»ÙµÄ¡£
Êý×é
ÒòΪ֮ǰµÄÎÄÕÂÓн²¹ýеÄÊý×éʵÏÖ£¬ËùÒÔÕâÀï¾Í²»ÔÙÏêϸÃèÊöÁË¡£ËäÈ»×î½üÓÐЩ±ä»¯µ¼ÖÂ֮ǰµÄÃèÊö²»ÊÇÊ®·Ö׼ȷÁË£¬µ«ÊÇ»ù±¾µÄ¸ÅÄÊÇÒ»Öµġ£
ÕâÀïҪ˵µÄÊÇ֮ǰµÄÎÄÕÂÖÐûÓÐÌáµ½µÄÊý×éÏà¹ØµÄ¸ÅÄ²»¿É±äÊý×é¡£Æä±¾ÖÊÉϺͱ£Áô×Ö·ûÀàËÆ£ºÃ»ÓÐÒýÓüÆÊýÇÒÔÚÇëÇó½áÊøÖ®Ç°Ò»Ö±´æÔÚ£¨Ò²¿ÉÄÜÔÚÇëÇó½áÊøÖ®ºó»¹´æÔÚ£©¡£
ÒòΪijЩÄÚ´æ¹ÜÀí·½±ãµÄÔÒò£¬²»¿É±äÊý×éÖ»»áÔÚ¿ªÆô opcache ʱ»áʹÓõ½¡£ÎÒÃÇÀ´¿´¿´Êµ¼ÊʹÓõÄÀý×Ó£¬ÏÈ¿´ÒÔϵĽű¾£º
for ($i = 0; $i 1000000; ++$i) { $array[] = ['foo']; } var_dump(memory_get_usage()); |
¿ªÆô opcache ʱ£¬ÒÔÉÏ´úÂë»áʹÓà 32MB µÄÄڴ棬²»¿ªÆôµÄÇé¿öÏÂÒòΪ $array ÿ¸öÔªËØ¶¼»á¸´ÖÆÒ»·Ý ['foo'] £¬ËùÒÔÐèÒª 390MB¡£ÕâÀï»á½øÐÐÍêÕûµÄ¸´Öƶø²»ÊÇÔö¼ÓÒýÓüÆÊýÖµµÄÔÒòÊÇ·ÀÖ¹ zend ÐéÄâ»ú²Ù×÷·ûÖ´ÐеÄʱºò³öÏÖ¹²ÏíÄÚ´æ³ö´íµÄÇé¿ö¡£ÎÒÏ£Íû²»Ê¹Óà opcache ʱÄڴ汩ÔöµÄÎÊÌâÒÔºóÄܵõ½¸ÄÉÆ¡£
PHP5 ÖеĶÔÏó
ÔÚÁ˽â PHP7 ÖеĶÔÏóʵÏÖÖ±ÏßÎÒÃÇÏÈ¿´Ò»Ï PHP5 µÄ²¢ÇÒ¿´Ò»ÏÂÓÐʲôЧÂÊÉϵÄÎÊÌâ¡£PHP5 ÖÐµÄ zval »á´æ´¢Ò»¸ö zend_object_value ½á¹¹£¬Æä¶¨ÒåÈçÏ£º
typedef struct _zend_object_value { zend_object_handle handle; const zend_object_handlers *handlers; } zend_object_value; |
handle ÊǶÔÏóµÄΨһ ID£¬¿ÉÒÔÓÃÓÚ²éÕÒ¶ÔÏóÊý¾Ý¡£handles ÊDZ£´æ¶ÔÏó¸÷ÖÖÊôÐÔ·½·¨µÄÐ麯Êý±íÖ¸Õ롣ͨ³£Çé¿öÏ PHP ¶ÔÏó¶¼ÓÐ×ÅͬÑùµÄ handler ±í£¬µ«ÊÇ PHP À©Õ¹´´½¨µÄ¶ÔÏóÒ²¿ÉÒÔͨ¹ý²Ù×÷·ûÖØÔØµÈ·½Ê½¶ÔÆäÐÐΪ×Ô¶¨Òå¡£
¶ÔÏó¾ä±ú£¨handler£©ÊÇ×÷ΪË÷ÒýÓÃÓÚ¡º¶ÔÏó´æ´¢¡»£¬¶ÔÏó´æ´¢±¾ÉíÊÇÒ»¸ö´æ´¢ÈÝÆ÷£¨bucket£©µÄÊý×飬bucket ¶¨ÒåÈçÏ£º
typedef struct _zend_object_value { zend_object_handle handle; const zend_object_handlers *handlers; } zend_object_value; |
Õâ¸ö½á¹¹Ìå°üº¬Á˺ܶණÎ÷¡£Ç°Èý¸ö³ÉÔ±Ö»ÊÇЩÆÕͨµÄÔªÊý¾Ý£¨¶ÔÏóµÄÎö¹¹º¯ÊýÊÇ·ñ±»µ÷Óùý¡¢bucke ÊÇ·ñ±»Ê¹ÓùýÒÔ¼°¶ÔÏ󱻵ݹéµ÷Óùý¶àÉٴΣ©¡£½ÓÏÂÀ´µÄÁªºÏÌåÓÃÓÚÇø·Ö bucket ÊÇ´¦ÓÚʹÓÃÖеÄ״̬»¹ÊÇ¿ÕÏÐ״̬¡£ÉÏÃæµÄ½á¹¹ÖÐ×îÖØÒªµÄÊÇ struct _store_object ×ӽṹÌ壺
µÚÒ»¸ö³ÉÔ± object ÊÇÖ¸Ïòʵ¼Ê¶ÔÏó£¨Ò²¾ÍÊǶÔÏó×îÖÕ´æ´¢µÄλÖ㩵ÄÖ¸Õë¡£¶ÔÏóʵ¼Ê²¢²»ÊÇÖ±½ÓǶÈëµ½¶ÔÏó´æ´¢µÄ bucket Öеģ¬ÒòΪ¶ÔÏó²»ÊǶ¨³¤µÄ¡£¶ÔÏóÖ¸ÕëÏÂÃæÊÇÈý¸öÓÃÓÚ¹ÜÀí¶ÔÏóÏú»Ù¡¢ÊÍ·ÅÓë¿Ë¡µÄ²Ù×÷¾ä±ú£¨handler£©¡£ÕâÀïҪעÒâµÄÊÇ PHP Ïú»ÙºÍÊͷŶÔÏóÊDz»Í¬µÄ²½Ö裬ǰÕßÔÚijЩÇé¿öÏÂÓпÉÄÜ»á±»Ìø¹ý£¨²»ÍêÈ«ÊÍ·Å£©¡£¿Ë¡²Ù×÷ʵ¼ÊÉϼ¸ºõ¼¸ºõ²»»á±»Óõ½£¬ÒòΪÕâÀï°üº¬µÄ²Ù×÷²»ÊÇÆÕͨ¶ÔÏó±¾ÉíµÄÒ»²¿·Ö£¬ËùÒÔ£¨ÈκÎʱºò£©ËûÃÇÔÚÿ¸ö¶ÔÏóÖÐËûÃǶ¼»á±»µ¥¶À¸´ÖÆ£¨duplicate£©Ò»·Ý¶ø²»Êǹ²Ïí¡£
ÕâЩ¶ÔÏó´æ´¢²Ù×÷¾ä±úºóÃæÊÇÒ»¸öÆÕͨµÄ¶ÔÏó handlers Ö¸Õë¡£´æ´¢Õ⼸¸öÊý¾ÝÊÇÒòΪÓÐʱºò¿ÉÄÜ»áÔÚ zval δ֪µÄÇé¿öÏÂÏú»Ù¶ÔÏó£¨Í¨³£Çé¿öÏÂÕâЩ²Ù×÷¶¼ÊÇÕë¶Ô zval ½øÐеģ©¡£
bucket Ò²°üº¬ÁË refcount µÄ×ֶΣ¬²»¹ýÕâÖÖÐÐΪÔÚ PHP5 ÖÐÏÔµÃÓÐÐ©Ææ¹Ö£¬ÒòΪ zval ±¾ÉíÒѾ´æ´¢ÁËÒýÓüÆÊý¡£ÎªÊ²Ã´»¹ÐèÒªÒ»¸ö¶àÓàµÄ¼ÆÊýÄØ£¿ÎÊÌâÔÚÓÚËäȻͨ³£Çé¿öÏ zval µÄ¡º¸´ÖÆ¡»ÐÐΪ¶¼ÊǼòµ¥µÄÔö¼ÓÒýÓüÆÊý¼´¿É£¬µ«ÊÇż¶ûÒ²»áÓÐÉî¶È¸´ÖƵÄÇé¿ö³öÏÖ£¬±ÈÈç´´½¨Ò»¸öÈ«Ð嵀 zval µ«ÊDZ£´æÍ¬ÑùµÄ zend_object_value¡£ÕâÖÖÇé¿öÏÂÁ½¸ö²»Í¬µÄ zval ¾ÍÓõ½ÁËͬһ¸ö¶ÔÏó´æ´¢µÄ bucket£¬ËùÒÔ bucket ×ÔÉíÒ²ÐèÒª½øÐÐÒýÓüÆÊý¡£ÕâÖÖ¡ºË«ÖؼÆÊý¡»µÄ·½Ê½ÊÇ PHP5 µÄʵÏÖÄÚÔÚµÄÎÊÌâ¡£GC ¸ù»º³åÇøÖÐµÄ buffered Ö¸ÕëÒ²ÊÇÓÉÓÚͬÑùµÄÔÒò²ÅÐèÒª½øÐÐÍêÈ«¸´ÖÆ£¨duplicate£©¡£
ÏÖÔÚ¿´¿´¶ÔÏó´æ´¢ÖÐÖ¸ÕëÖ¸ÏòµÄʵ¼ÊµÄ object µÄ½á¹¹£¬Í¨³£Çé¿öÏÂÓû§²ãÃæµÄ¶ÔÏó¶¨ÒåÈçÏ£º
typedef struct _zend_object { zend_class_entry *ce; HashTable *properties; zval **properties_table; HashTable *guards; } zend_object; |
zend_class_entry Ö¸ÕëÖ¸ÏòµÄÊǶÔÏóʵÏÖµÄÀàÔÐÍ¡£½ÓÏÂÀ´µÄÁ½¸öÔªËØÊÇʹÓò»Í¬µÄ·½Ê½´æ´¢¶ÔÏóÊôÐÔ¡£¶¯Ì¬ÊôÐÔ£¨ÔËÐÐʱÌí¼ÓµÄ¶ø²»ÊÇÔÚÀàÖж¨ÒåµÄ£©È«²¿´æÔÚ properties ÖУ¬²»¹ýÖ»ÊÇÊôÐÔÃûºÍÖµµÄ¼òµ¥Æ¥Åä¡£
²»¹ýÕâÀïÓÐÕë¶ÔÒѾÉùÃ÷µÄÊôÐÔµÄÒ»¸öÓÅ»¯£º±àÒëÆÚ¼äÿ¸öÊôÐÔ¶¼»á±»Ö¸¶¨Ò»¸öË÷Òý²¢ÇÒÊôÐÔ±¾ÉíÊÇ´æ´¢ÔÚ properties_table µÄË÷ÒýÖС£ÊôÐÔÃû³ÆºÍË÷ÒýµÄÆ¥Åä´æ´¢ÔÚÀàÔÐ굀 hashtable ÖС£ÕâÑù¾Í¿ÉÒÔ·Àֹÿ¸ö¶ÔÏóʹÓõÄÄڴ泬¹ý hashtable µÄÉÏÏÞ£¬²¢ÇÒÊôÐÔµÄË÷Òý»áÔÚÔËÐÐʱÓжദ»º´æ¡£
guards µÄ¹þÏ£±íÊÇÓÃÓÚʵÏÖħÊõ·½·¨µÄµÝ¹éÐÐΪµÄ£¬±ÈÈç __get£¬ÕâÀïÎÒÃDz»ÉîÈëÌÖÂÛ¡£
³ýÁËÉÏÎÄÌáµ½¹ýµÄË«ÖØ¼ÆÊýµÄÎÊÌ⣬ÕâÖÖʵÏÖ»¹ÓÐÒ»¸öÎÊÌâÊÇÒ»¸ö×îСµÄÖ»ÓÐÒ»¸öÊôÐԵĶÔÏóÒ²ÐèÒª 136 ¸ö×Ö½ÚµÄÄڴ棨Õ⻹²»Ëã zval ÐèÒªµÄÄڴ棩¡£¶øÇÒÖÐ¼ä´æÔںܶà¼ä½Ó·ÃÎʶ¯×÷£º±ÈÈçÒª´Ó¶ÔÏó zval ÖÐÈ¡³öÒ»¸öÔªËØ£¬ÏÈÐèҪȡ³ö¶ÔÏó´æ´¢ bucket£¬È»ºóÊÇ zend object£¬È»ºó²ÅÄÜͨ¹ýÖ¸ÕëÕÒµ½¶ÔÏóÊôÐÔ±íºÍ zval¡£ÕâÑùÕâÀïÖÁÉÙ¾ÍÓÐ 4 ²ã¼ä½Ó·ÃÎÊ£¨²¢ÇÒʵ¼ÊʹÓÃÖпÉÄÜ×îÉÙÐèÒªÆß²ã£©¡£
PHP7 ÖеĶÔÏó
PHP7 µÄʵÏÖÖÐÊÔͼ½â¾öÉÏÃæÕâЩÎÊÌ⣬°üÀ¨È¥µôË«ÖØÒýÓüÆÊý¡¢¼õÉÙÄÚ´æÊ¹ÓÃÒÔ¼°¼ä½Ó·ÃÎÊ¡£Ð嵀 zend_object ½á¹¹ÌåÈçÏ£º
struct _zend_object { zend_refcounted gc; uint32_t handle; zend_class_entry *ce; const zend_object_handlers *handlers; HashTable *properties; zval properties_table[1]; }; |
¿ÉÒÔ¿´µ½ÏÖÔÚÕâ¸ö½á¹¹Ì弸ºõ¾ÍÊÇÒ»¸ö¶ÔÏóµÄÈ«²¿ÄÚÈÝÁË£ºzend_object_value ÒѾ±»Ìæ»»³ÉÒ»¸öÖ±½ÓÖ¸Ïò¶ÔÏóºÍ¶ÔÏó´æ´¢µÄÖ¸Õ룬ËäȻûÓÐÍêÈ«ÒÆ³ý£¬µ«ÒѾÊǺܴóµÄÌáÉýÁË¡£
³ýÁË PHP7 ÖйßÓÃµÄ zend_refcounted Í·ÒÔÍ⣬handle ºÍ ¶ÔÏóµÄ handlers ÏÖÔÚÒ²±»·Åµ½ÁË zend_object ÖС£ÕâÀïµÄ properties_table ͬÑùÓõ½ÁË C ½á¹¹ÌåµÄС¼¼ÇÉ£¬ÕâÑù zend_object ºÍÊôÐÔ±í¾Í»áµÃµ½Ò»Õû¿éÄÚ´æ¡£µ±È»£¬ÏÖÔÚÊôÐÔ±íÊÇÖ±½ÓǶÈëµ½ zval ÖеĶø²»ÊÇÖ¸Õë¡£
ÏÖÔÚ¶ÔÏó½á¹¹ÌåÖÐûÓÐÁË guards ±í£¬ÏÖÔÚÈç¹ûÐèÒªµÄ»°Õâ¸ö×ֶεÄÖµ»á±»´æ´¢ÔÚ properties_table µÄµÚһλÖУ¬Ò²¾ÍÊÇʹÓà __get µÈ·½·¨µÄʱºò¡£²»¹ýÈç¹ûûÓÐʹÓÃħÊõ·½·¨µÄ»°£¬guards ±í»á±»Ê¡ÂÔ¡£
dtor¡¢free_storage ºÍ clone Èý¸ö²Ù×÷¾ä±ú֮ǰÊÇ´æ´¢ÔÚ¶ÔÏó²Ù×÷ bucket ÖУ¬ÏÖÔÚÖ±½Ó´æÔÚ handlers ±íÖУ¬Æä½á¹¹Ì嶨ÒåÈçÏ£º
struct _zend_object_handlers { /* offset of real object header (usually zero) */ int offset; /* general object functions */ zend_object_free_obj_t free_obj; zend_object_dtor_obj_t dtor_obj; zend_object_clone_obj_t clone_obj; /* individual object functions */ // ... rest is about the same in PHP 5 }; |
handler ±íµÄµÚÒ»¸ö³ÉÔ±ÊÇ offset£¬ºÜÏÔÈ»Õâ²»ÊÇÒ»¸ö²Ù×÷¾ä±ú¡£Õâ¸ö offset ÊÇÏÖÔÚµÄʵÏÖÖбØÐë´æÔڵģ¬ÒòΪËäÈ»ÄÚ²¿µÄ¶ÔÏó×ÜÊÇǶÈëµ½±ê×¼µÄ zend_object ÖУ¬µ«ÊÇÒ²×Ü»áÓÐÌí¼ÓһЩ³ÉÔ±½øÈ¥µÄÐèÇó¡£ÔÚ PHP5 Öнâ¾öÕâ¸öÎÊÌâµÄ·½·¨ÊÇÌí¼ÓһЩÄÚÈݵ½±ê×¼µÄ¶ÔÏóºóÃæ£º
struct custom_object { zend_object std; uint32_t something; // ... }; |
ÕâÑùÈç¹ûÄã¿ÉÒÔÇáÒ׵Ľ« zend_object* Ìí¼Óµ½ struct custom_object* ÖС£ÕâÒ²ÊÇ C ÓïÑÔÖг£ÓõĽṹÌå¼Ì³ÐµÄ×ö·¨¡£µ«ÊÇÔÚ PHP7 ÖÐÕâÖÖʵÏÖ»áÓÐÒ»¸öÎÊÌ⣺ÒòΪ zend_object ÔÚ´æ´¢ÊôÐÔ±íʱÓÃÁ˽ṹÌå hack µÄ¼¼ÇÉ£¬zend_object β²¿´æ´¢µÄ PHP ÊôÐԻḲ¸ÇµôºóÐøÌí¼Ó½øÈ¥µÄÄÚ²¿³ÉÔ±¡£ËùÒÔ PHP7 µÄʵÏÖÖлá°Ñ×Ô¼ºÌí¼ÓµÄ³ÉÔ±Ìí¼Óµ½±ê×¼¶ÔÏó½á¹¹µÄÇ°Ãæ£º
struct custom_object { uint32_t something; // ... zend_object std; }; |
²»¹ýÕâÑùÒ²¾ÍÒâζ×ÅÏÖÔÚÎÞ·¨Ö±½ÓÔÚ zend_object* ºÍ struct custom_object* ½øÐмòµ¥µÄת»»ÁË£¬ÒòΪÁ½Õß¶¼Ò»¸öÆ«ÒÆ·Ö¸î¿ªÁË¡£ËùÒÔÕâ¸öÆ«ÒÆÁ¿¾ÍÐèÒª±»´æ´¢ÔÚ¶ÔÏó handler ±íÖеĵÚÒ»¸öÔªËØÖУ¬ÕâÑùÔÚ±àÒëʱͨ¹ý offsetof() ºê¾ÍÄÜÈ·¶¨¾ßÌåµÄÆ«ÒÆÖµ¡£
Ò²ÐíÄã»áºÃÆæ¼ÈÈ»ÏÖÔÚÒѾֱ½Ó£¨ÔÚ zend_value ÖУ©´æ´¢ÁË zend_object µÄÖ¸Õ룬ÄÇÏÖÔھͲ»ÐèÒªÔÙµ½¶ÔÏó´æ´¢ÖÐÈ¥²éÕÒ¶ÔÏóÁË£¬ÎªÊ²Ã´ PHP7 µÄ¶ÔÏóÕß»¹±£Áô×Å handle ×Ö¶ÎÄØ£¿
ÕâÊÇÒòΪÏÖÔÚ¶ÔÏó´æ´¢ÈÔÈ»´æÔÚ£¬ËäÈ»µÃµ½Á˼«´óµÄ¼ò»¯£¬ËùÒÔ±£Áô handle ÈÔÈ»ÊÇÓбØÒªµÄ¡£ÏÖÔÚËüÖ»ÊÇÒ»¸öÖ¸Ïò¶ÔÏóµÄÖ¸ÕëÊý×é¡£µ±¶ÔÏó±»´´½¨Ê±£¬»áÓÐÒ»¸öÖ¸Õë²åÈëµ½¶ÔÏó´æ´¢Öв¢ÇÒÆäË÷Òý»á±£´æÔÚ handle ÖУ¬µ±¶ÔÏó±»ÊÍ·Åʱ£¬Ë÷ÒýÒ²»á±»ÒƳý¡£
ÄÇôΪʲôÏÖÔÚ»¹ÐèÒª¶ÔÏó´æ´¢ÄØ£¿ÒòΪÔÚÇëÇó½áÊøµÄ½×¶Î»áÔÚ´æÔÚij¸ö½Úµã£¬ÔÚÕâÖ®ºóÔÙÈ¥Ö´ÐÐÓû§´úÂë²¢ÇÒȡָÕëÊý¾Ýʱ¾Í²»°²È«ÁË¡£ÎªÁ˱ÜÃâÕâÖÖÇé¿ö³öÏÖ PHP »áÔÚ¸üÔçµÄ½ÚµãÉÏÖ´ÐÐËùÓжÔÏóµÄÎö¹¹º¯Êý²¢ÇÒÖ®ºó¾Í²»ÔÙÓдËÀà²Ù×÷£¬ËùÒÔ¾ÍÐèÒªÒ»¸ö»îÔ¾¶ÔÏóµÄÁÐ±í¡£
²¢ÇÒ handle ¶ÔÓÚµ÷ÊÔÒ²ÊǺÜÓÐÓõģ¬ËüÈÃÿ¸ö¶ÔÏó¶¼ÓÐÁËÒ»¸öΨһµÄ ID£¬ÕâÑù¾ÍºÜÈÝÒ×Çø·ÖÁ½¸ö¶ÔÏóÊÇͬһ¸ö»¹ÊÇÖ»ÊÇÓÐÏàͬµÄÄÚÈÝ¡£ËäÈ» HHVM ûÓжÔÏó´æ´¢µÄ¸ÅÄµ«ËüÒ²´æÁ˶ÔÏóµÄ handle¡£
ºÍ PHP5 Ïà±È£¬ÏÖÔÚµÄʵÏÖÖÐÖ»ÓÐÒ»¸öÒýÓüÆÊý£¨zval ×ÔÉí²»¼ÆÊý£©£¬²¢ÇÒÄÚ´æµÄʹÓÃÁ¿ÓÐÁ˺ܴóµÄËõ¼õ£º40 ¸ö×Ö½ÚÓÃÓÚ»ù´¡¶ÔÏó£¬Ã¿¸öÊôÐÔÐèÒª 16 ¸ö×Ö½Ú£¬²¢ÇÒÕ⻹ÊÇËãÁË zval Ö®ºóµÄ¡£¼ä½Ó·ÃÎʵÄÇé¿öÒ²ÓÐÁËÏÔÖøµÄ¸ÄÉÆ£¬ÒòΪÏÖÔÚÖмä²ãµÄ½á¹¹ÌåҪô±»È¥µôÁË£¬ÒªÃ´¾ÍÊÇÖ±½ÓǶÈëµÄ£¬ËùÒÔÏÖÔÚ¶Áȡһ¸öÊôÐÔÖ»ÓÐÒ»²ã·ÃÎʶø²»ÔÙÊÇËIJ㡣
¼ä½Ó zval
µ½ÏÖÔÚÎÒÃÇÒѾ»ù±¾Ìáµ½¹ýÁËËùÓÐÕý³£µÄ zval ÀàÐÍ£¬µ«ÊÇÒ²ÓÐÒ»¶ÔÌØÊâÀàÐÍÓÃÓÚÄ³Ð©ÌØ¶¨µÄÇé¿öµÄ£¬ÆäÖÐÖ®Ò»¾ÍÊÇ PHP7 ÐÂÌí¼ÓµÄ IS_INDIRECT¡£
¼ä½Ó zval Ö¸µÄ¾ÍÊÇÆäÕæÕýµÄÖµÊÇ´æ´¢ÔÚÆäËûµØ·½µÄ¡£×¢ÒâÕâ¸ö IS_REFERENCE ÀàÐÍÊDz»Í¬µÄ£¬¼ä½Ó zval ÊÇÖ±½ÓÖ¸ÏòÁíÍâÒ»¸ö zval ¶ø²»ÊÇÏñ zend_reference ½á¹¹ÌåÒ»ÑùǶÈë zval¡£
ΪÁËÀí½âÔÚʲôʱºò»á³öÏÖÕâÖÖÇé¿ö£¬ÎÒÃÇÀ´¿´Ò»Ï PHP ÖбäÁ¿µÄʵÏÖ£¨Êµ¼ÊÉ϶ÔÏóÊôÐԵĴ洢ҲÊÇÒ»ÑùµÄÇé¿ö£©¡£
ËùÓÐÔÚ±àÒë¹ý³ÌÖÐÒÑÖªµÄ±äÁ¿¶¼»á±»Ö¸¶¨Ò»¸öË÷Òý²¢ÇÒÆäÖµ»á±»´æÔÚ±àÒë±äÁ¿£¨CV£©±íµÄÏàӦλÖÃÖС£µ«ÊÇ PHP Ò²ÔÊÐíÄ㶯̬µÄÒýÓñäÁ¿£¬²»¹ÜÊǾֲ¿±äÁ¿»¹ÊÇÈ«¾Ö±äÁ¿£¨±ÈÈç $GLOBALS£©£¬Ö»Òª³öÏÖÕâÖÖÇé¿ö£¬PHP ¾Í»áΪ½Å±¾»òÕߺ¯Êý´´½¨Ò»¸ö·ûºÅ±í£¬ÕâÆäÖаüº¬Á˱äÁ¿ÃûºÍËüÃǵÄÖµÖ®¼äµÄÓ³Éä¹ØÏµ¡£
µ«ÊÇÎÊÌâÔÚÓÚ£ºÔõôÑù²ÅÄÜʵÏÖÁ½¸ö±íµÄͬʱ·ÃÎÊÄØ£¿ÎÒÃÇÐèÒªÔÚ CV ±íÖÐÄܹ»·ÃÎÊÆÕͨ±äÁ¿£¬Ò²ÐèÒªÄÜÔÚ·ûºÅ±íÖзÃÎʱàÒë±äÁ¿¡£ÔÚ PHP5 ÖÐ CV ±íÓÃÁËË«ÖØÖ¸Õë zval**£¬Í¨³£ÕâЩָÕëÖ¸ÏòÖмäµÄ zval* µÄ±í£¬zval* ×îÖÕÖ¸ÏòµÄ²ÅÊÇʵ¼ÊµÄ zval:
+------ CV_ptr_ptr[0] | +---- CV_ptr_ptr[1] | | +-- CV_ptr_ptr[2] | | | | | +-> CV_ptr[0] --> some zval | +---> CV_ptr[1] --> some zval +-----> CV_ptr[2] --> some zval |
µ±ÐèҪʹÓ÷ûºÅ±íʱ´æ´¢ zval* µÄÖмä±íÆäʵÊÇûÓÐÓõ½µÄ¶ø zval** Ö¸Õë»á±»¸üе½ hashtable buckets µÄÏìӦλÖÃÖС£ÎÒÃǼٶ¨ÓÐ $a¡¢$b ºÍ $c Èý¸ö±äÁ¿£¬ÏÂÃæÊǼòµ¥µÄʾÒâͼ£º
CV_ptr_ptr[0] --> SymbolTable["a"].pDataPtr --> some zval CV_ptr_ptr[1] --> SymbolTable["b"].pDataPtr --> some zval CV_ptr_ptr[2] --> SymbolTable["c"].pDataPtr --> some zval |
µ«ÊÇ PHP7 µÄÓ÷¨ÖÐÒѾûÓÐÕâ¸öÎÊÌâÁË£¬ÒòΪ PHP7 ÖÐµÄ hashtable ´óС·¢Éú±ä»¯Ê± hashtable bucket ¾ÍʧЧÁË¡£ËùÒÔ PHP7 ÓÃÁËÒ»¸öÏà·´µÄ²ßÂÔ£ºÎªÁË·ÃÎÊ CV ±íÖд洢µÄ±äÁ¿£¬·ûºÅ±íÖд洢 INDIRECT À´Ö¸Ïò CV ±í¡£CV ±íÔÚ·ûºÅ±íµÄÉúÃüÖÜÆÚÄÚ²»»áÖØÐ·ÖÅ䣬ËùÒÔÒ²¾Í²»»á´æÔÚÓÐÎÞЧָÕëµÄÎÊÌâÁË¡£
ËùÒÔ¼ÓÈëÄãÓÐÒ»¸öº¯Êý²¢ÇÒÔÚ CV ±íÖÐÓÐ $a¡¢$b ºÍ $c£¬Í¬Ê±»¹ÓÐÒ»¸ö¶¯Ì¬·ÖÅäµÄ±äÁ¿ $d£¬·ûºÅ±íµÄ½á¹¹¿´ÆðÀ´´ó¸Å¾ÍÊÇÕâ¸öÑù×Ó£º
SymbolTable["a"].value = INDIRECT --> CV[0] = LONG 42 SymbolTable["b"].value = INDIRECT --> CV[1] = DOUBLE 42.0 SymbolTable["c"].value = INDIRECT --> CV[2] = STRING --> zend_string("42") SymbolTable["d"].value = ARRAY --> zend_array([4, 2]) |
¼ä½Ó zval Ò²¿ÉÒÔÊÇÒ»¸öÖ¸Ïò IS_UNDEF ÀàÐÍ zval µÄÖ¸Õ룬µ± hashtable ûÓкÍËü¹ØÁªµÄ key ʱ¾Í»á³öÏÖÕâÖÖÇé¿ö¡£ËùÒÔµ±Ê¹Óà unset($a) ½« CV[0] µÄÀàÐͱê¼ÇΪ UNDEF ʱ¾Í»áÅж¨·ûºÅ±í²»´æÔÚ¼üֵΪ a µÄÊý¾Ý¡£
³£Á¿ºÍ AST
»¹ÓÐÁ½¸öÐèҪ˵һϵÄÔÚ PHP5 ºÍ PHP7 Öж¼´æÔÚµÄÌØÊâÀàÐÍ IS_CONSTANT ºÍ IS_CONSTANT_AST¡£ÒªÁ˽âËûÃÇÎÒÃÇ»¹ÊÇÏÈ¿´ÒÔϵÄÀý×Ó£º
function test($a = ANSWER, $b = ANSWER * ANSWER) { return $a + $b; } define('ANSWER', 42); var_dump(test()); // int(42 + 42 * 42)¡¤ |
test() º¯ÊýµÄÁ½¸ö²ÎÊýµÄĬÈÏÖµ¶¼ÊÇÓɳ£Á¿ ANSWER¹¹³É£¬µ«ÊǺ¯ÊýÉùÃ÷ʱ³£Á¿µÄÖµÉÐ䶨Òå¡£³£Á¿µÄ¾ßÌåÖµÖ»ÓÐͨ¹ý define() ¶¨Òåʱ²ÅÖªµÀ¡£
ÓÉÓÚÒÔÉÏÎÊÌâµÄ´æÔÚ£¬²ÎÊýºÍÊôÐÔµÄĬÈÏÖµ¡¢³£Á¿ÒÔ¼°ÆäËû½ÓÊÜ¡º¾²Ì¬±í´ïʽ¡»µÄ¶«Î÷¶¼Ö§³Ö¡ºÑÓʱ°ó¶¨¡»Ö±µ½Ê×´ÎʹÓÃʱ¡£
³£Á¿£¨»òÕßÀàµÄ¾²Ì¬ÊôÐÔ£©ÕâЩÐèÒª¡ºÑÓʱ°ó¶¨¡»µÄÊý¾Ý¾ÍÊÇ×î³£ÐèÒªÓõ½ IS_CONSTANT ÀàÐÍ zval µÄµØ·½¡£Èç¹ûÕâ¸öÖµÊDZí´ïʽ£¬¾Í»áʹÓà IS_CONSTANT_AST ÀàÐ굀 zval Ö¸Ïò±í´ïʽµÄ³éÏóÓï·¨Ê÷£¨AST£©¡£
µ½ÕâÀïÎÒÃǾͽáÊøÁË¶Ô PHP7 ÖбäÁ¿ÊµÏֵķÖÎö¡£ºóÃæÎÒ¿ÉÄÜ»¹»áдÁ½ÆªÎÄÕÂÀ´½éÉÜһЩÐéÄâ»úÓÅ»¯¡¢ÐµÄÃüÃûÔ¼¶¨ÒÔ¼°Ò»Ð©±àÒëÆ÷»ù´¡½á¹¹µÄÓÅ»¯µÄÄÚÈÝ£¨ÕâÊÇ×÷ÕßÔ»°£©¡£ |