Remember that the Internet is widely circulated "PHP is the best language in the world", for the moment not to discuss whether it is exaggerated, but at least PHP does have a unique advantage, such as its weak type, that is, only the $ sign to declare variables, so that PHP threshold is very low to become the preferred Web server language. So how is the variable implemented? Let's learn the basic variables of PHP today.
First, Introduction
PHP variables are stored in the ZVAL structure and can be seen zval when compiled into Op_array in the execution phase. The structure is defined in theZend/zend_types.hdefinition content as follows:
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) /* Reserved field */
} 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;
};
II. Structure Analysis 2.1, Zend_value
The first variable of the struct is Zend_value, as the name implies, it is also a struct, used to store the value of a variable, such as Integer, float, reference count, String, array, object, resource, and so on.zend_valueMany types of pointers are defined, but these types are not all types of variables, and some are used by the kernel itself, such as pointer ast, ZV, PTR.
Typedef union _zend_value {
Zend_long lval; /* Integer */
Double dval; /* floating point */
Zend_refcounted *counted; /* reference count */
Zend_string *str; /* string */
Zend_array *arr; /* array */
Zend_object *obj; /* object */
Zend_resource *res; /* resources */
Zend_reference *ref; /* reference */
Zend_ast_ref *ast; /* abstract syntax tree */
Zval *zv; /* zval type */
Void *ptr; /* pointer type */
Zend_class_entry *ce; /* class type */
Zend_function *func; /* function type */
Struct {
Uint32_t w1;
Uint32_t w2;
} ww;
} zend_value;
2.2, U1
U1 is a consortium that unites structuresvand integral typestype_info. Let's lookvat the composition of the structure first.
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;
2.2.1, type
Type refers to the types of variables, just in the2.1Zend_value is used to store the value of the variable, so there should be a place to store the variable type, and this is the role of type. The following are all the variable types defined by PHP, with the types of Boolean, NULL, floating point, Array, String, and so on known to us. There are also unfamiliar undef, indirect, PTR types, variable types are explained in the next chapter, and are not described here.
/* regular data types */
#define IS_UNDEF 0
#define IS_NULL 1
#define IS_FALSE 2
#define IS_TRUE 3
#define IS_LONG 4
#define IS_DOUBLE 5
#define IS_STRING 6
#define IS_ARRAY 7
#define IS_OBJECT 8
#define IS_RESOURCE 9
#define IS_REFERENCE 10
/* constant expressions */
#define IS_CONSTANT 11
#define IS_CONSTANT_AST 12
/* fake types */
#define _IS_BOOL 13
#define IS_CALLABLE 14
/* internal types */
#define IS_INDIRECT 15
#define IS_PTR 17
2.2.2, Type_flags
It can be understood as a subtype, which refers to the type of the variable, which is for different types of subtypes or tags,type_flagsaltogether the following 6 kinds.
/* zval.u1.v.type_flags */
#define IS_TYPE_CONSTANT (1<<0) /* Constant */
#define IS_TYPE_IMMUTABLE (1<<1) /* Immutable type */
#define IS_TYPE_REFCOUNTED (1<<2) /* Type of reference count required */
#define IS_TYPE_COLLECTABLE (1<<3) /* May contain types of circular references */
#define IS_TYPE_COPYABLE (1<<4) /* Types that can be copied */
#define IS_TYPE_SYMBOLTABLE (1<<5) /* Symbol table type */
2.2.3, Const_flags
The tag for the constant type, the corresponding property is:
/* zval.u1.v.const_flags */
#define IS_CONSTANT_UNQUALIFIED 0x010
#define IS_LEXICAL_VAR 0x020
#define IS_LEXICAL_REF 0x040
#define IS_CONSTANT_CLASS 0x080 /* __CLASS__ in trait */
#define IS_CONSTANT_IN_NAMESPACE 0x100 /* used only in opline->extended_value */
2.2.4, Type_info
Type_info and struct v share memory, modifying Type_info is equivalent to modifying the value of struct V, so type_info is a combination of four char in V.
2.3, U2
U1 and Zend_value can be used to represent variables, there is no need to define U2, but let's take a look, if there is no U2, in the case of memory alignment zval memory size is 16 bytes, when the union of U2 still occupies 16 bytes. Since there is or is not occupying the same amount of memory, it is better to use it to record some ancillary information. Let's look at what is stored in U2.
2.3.1, Next
Used to resolve the problem of the hash conflict and record the next element location of the conflict.
2.3.2, Cache_slot
Run-time caching, which is returned to the cache when the function is executed, and is found in the global function table if it is not in the cache.
2.3.3, Lineno
The line number of the file execution, applied on the AST node. The Zend Engine records the line number of the currently executed file in lexical and syntactic parsing and records it in the Lineno in Zend_ast.
2.3.4, Num_args
The number of arguments passed into the function when the function is called.
2.3.5, Fe_pos
The location where the current traversal is logged when iterating through an array, such as Fe_pos each time a foreach is executed, and when the foreach is called again for traversal, Fe_post resets.
2.3.6, Fe_iter_idx
This is similar to Fe_pos, except that it is object-oriented. The properties of the object are also hashtable, and when the passed parameter is an object, it gets the properties of the object, so traversing the object is the property of the Variable object.
Iii. Reference Documents
- Anatomy of the PHP7 kernel
- "PHP7 bottom design and source code implementation"
- Deep understanding of the zval of the PHP7 kernel