PHP7內核學習筆記 - zval中的知識點

  • PHP5中的zval結構
struct _zval_struct {
    union {
        long lval;
        double dval;
        struct {
            char *val;
            int len;
        } str;
        HashTable *ht;
        zend_object_value obj;
        zend_ast *ast;
    } value;
    zend_uint refcount__gc;
    zend_uchar type;
    zend_uchar is_ref__gc;
};
  • PHP7中的zval結構
struct _zval_struct {
    union {
        zend_long         lval;             /* long value */
        double            dval;             /* double value */
        zend_refcounted  *counted;
        zend_string      *str;
        zend_array       *arr;
        zend_object      *obj;
        zend_resource    *res;
        zend_reference   *ref;
        zend_ast_ref     *ast;
        zval             *zv;
        void             *ptr;
        zend_class_entry *ce;
        zend_function    *func;
        struct {
            uint32_t w1;
            uint32_t w2;
        } ww;
    } value;
    union {
        struct {
            ZEND_ENDIAN_LOHI_4(
                zend_uchar    type,         /* active type */
                zend_uchar    type_flags,
                zend_uchar    const_flags,
                zend_uchar    reserved)     /* call info for EX(This) */
        } v;
        uint32_t type_info;
    } u1;
    union {
        uint32_t     var_flags;
        uint32_t     next;                 /* hash collision chain */
        uint32_t     cache_slot;           /* literal cache slot */
        uint32_t     lineno;               /* line number (for ast nodes) */
        uint32_t     num_args;             /* arguments number for EX(This) */
        uint32_t     fe_pos;               /* foreach position */
        uint32_t     fe_iter_idx;          /* foreach iterator index */
    } u2;
};
  • GC機制:僅支持數組和對象(IS_TYPE_COLLECTABLE)
  • 第一步將紫色標記爲灰色,並將計數引用減1
  • 第二步僅操作灰色。若計數引用大於0,則說明非垃圾,標爲黑色,並將計數引用加1(第一步中做了減1操作)。若計數引用等於0,則說明是垃圾,標爲白色。
  • 移除黑色(非垃圾,不需要處理),保留白色(垃圾,需要回收)。將白色的計數引用加1,然後將處理後的roots鏈表移動到待釋放列表(to_free
  • 釋放to_free
  • 計數引用和寫時複製
  • 計數引用說白了就是用來標記一個變量所指向的值被使用了多少次
  • 簡單類型的變量(true/false/double/long/null)不需要引用計數
  • 臨時字符串會用到引用計數。但如果變量是字符常量,則不會用到
  • 對象、資源和引用在賦值時一定會用到引用計數
  • 普通數組在賦值時也會用到引用計數,但是變量是IS_ARRAY_IMMUTABLE時,賦值不使用引用計數
  • 一個zval是否支持引用計數是通過zval.u1.type_flag來標識的。當type_flag的第三位被標記爲1(IS_TYPE_REFCOUNTED標識),則代表可以引用計數。
  • 寫時複製這種機制是用於節省資源的。當變量只是複製後用來展示而不做改變,那麼新老變量指向的都是同一個值。當新老變量有任何一方作出變動,都會觸發寫時複製的機制,使得兩者脫離,分別指向自己私有的值了(這時候不再共用)。
  • 變量的作用域
  • 局部變量
  • 全局變量
  • 對於複製的支持(IS_TYPE_COPYABLE)
  • 需要查找IS_TYPE_COPYABLE,除了對象和資源,其他都支持。意味着對象和資源在賦值操作之後,新的變量和老的變量指向的是同一個對象(資源)。而其他的變量類型則支持賦值(整型和浮點型會直接生成一份新的,不需要計數引用和寫時複製)。
  • 只有stringarray支持複製
  • 對於引用計數的支持(IS_TYPE_REFCOUNTED)
  • 支持技術引用的類型有:stringarrayobjectresourcerefrence
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章