Home >Backend Development >PHP7 >Let's talk about the basic variables of PHP7

Let's talk about the basic variables of PHP7

藏色散人
藏色散人forward
2021-09-16 15:15:341675browse

Basic structure of variables

We all know that PHP variables are weakly typed, and there is no need to specify the type when declaring them. So how is this implemented? This has to start with the basic structure of variables.

Implementation of zval

In the source code file zend_type.h, you can see the definition of zval:

typedef struct _zval_struct     zval;

struct _zval_struct {
    zend_value        value;            /* 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     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 */
        uint32_t     access_flags;         /* class constant access flags */
        uint32_t     property_guard;       /* single property guard */
        uint32_t     extra;                /* not further specified */
    } u2;
}

The zval structure consists of a value or pointer that holds the variable type. The union zend_value and the two unions u1 and u2 form

  • u1

u1 is used to save the variable type and its information, and the fields inside it The uses are as follows:

type: record variable type. You can access

type_flags through u2.v.type: flags corresponding to the unique types of variables (such as constant types, reference counting types, immutable types). Different types of variables have different flags.

const_flags: constant type flags

reserved: reserved fields

  • u2

u2 is mainly an auxiliary function, due to the structure The memory is aligned, so the space of u2 has already occupied space with or without u2, so it is used. The auxiliary field of u2 records a lot of type information, which is of great benefit to internal functions, or improves cache friendliness or reduces memory addressing operations. Some of these fields are introduced here.

next: Used to solve hash conflict problems (hash conflicts are not understood yet) and record the position of the next element of the conflict.

cache_slot: Runtime cache. When executing a function, it will first search in the cache. If it is not found in the cache, it will then search in the global function table.

num_args: The number of parameters passed in when the function is called

access_flags: The access flag of the object class, such as public protected private.

  • zend_value
typedef union _zend_value {
    zend_long         lval;                /* 整型*/
    double            dval;                /* 浮点型 */
    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;
} zend_value;

As can be seen from zend__value, long and double types store values ​​directly, while other types are pointers, pointing to their respective structures. Therefore, due to the structure of zval, PHP variables do not need to explicitly specify their type when declaring it, because no matter what type of value you assign to the variable, it can help you find the corresponding storage structure.

Take a variable whose value is a string as an example. Its structure is as follows:

Comparison of the zval structure of PHP5 and PHP7

  • PHP5
  • PHP7

You can see that the zval of php7 only occupies 16 bytes in total, which saves a lot of memory compared to the 48 bytes occupied by the zval of PHP5.

In addition, in PHP5, all variables are allocated in the heap, but for temporary variables, there is no need to apply in the heap. Therefore, this has been optimized in PHP7, and temporary variables are applied directly on the stack.

Common variable types

The following introduces several common types of variable structures. For more other types, you can view the source code yourself.

Integers and floating point types

For integers and floating point types, due to their small space, the integer values ​​​​are directly stored in zval and are stored in lval. Floating point The type value is stored in dval.

typedef union _zend_value {
    zend_long         lval;             /* 整型*/
    double            dval;             /* 浮点型 */
    ... 
 }

String

A new string structure is defined in PHP 7. The structure is as follows:

struct _zend_string {
    zend_refcounted_h ;
    zend_ulong        h;                /* hash value */
    size_t            len;
    char              val[1];
};

The meaning of each field above:

gc: Variable reference information, all variable types that use reference counting will have this structure.

h: Hash value, used when calculating index in array. (It is said that this operation improves the performance of PHP7 by 5%)

len: String length, binary security is ensured through this value

val: String content, variable length struct, press when allocating len length applies for memory
array

array is a very powerful data structure in PHP. Its underlying implementation is an ordinary ordered HashTable. Here is a brief look at its structure. More details will be given later.

typedef struct _zend_array HashTable;


struct _zend_array {
    zend_refcounted_h gc;
    union {
        struct {
            ZEND_ENDIAN_LOHI_4(
                zend_uchar    flags,
                zend_uchar    nApplyCount,
                zend_uchar    nIteratorsCount,
                zend_uchar    consistency)
        } v;
        uint32_t flags;
    } u;
    uint32_t          nTableMask;
    Bucket           *arData;
    uint32_t          nNumUsed;
    uint32_t          nNumOfElements;
    uint32_t          nTableSize;
    uint32_t          nInternalPointer;
    zend_long         nNextFreeElement;
    dtor_func_t       pDestructor;
}

Object

The object structure of PHP7 has also been redesigned, which is very different from the implementation of PHP5.

struct _zend_object {
    zend_refcounted_h gc;
    uint32_t          handle;
    zend_class_entry *ce; 
    const zend_object_handlers *handlers;
    HashTable        *properties; 
    zval              properties_table[1];
};

Here are some of the fields:

gc: gc header

*ce: Class corresponding to the object Class

*properties: HashTable Structure, key is the attribute name of the object, value is the offset of the attribute value in the properties_tables array, and the corresponding attribute value is found in properties_talbe through the offset.

properties_talbe[1]: Store the attribute value of the object


ok, let’s write this here first.

The above is the detailed content of Let's talk about the basic variables of PHP7. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:segmentfault.com. If there is any infringement, please contact admin@php.cn delete