This article mainly introduces the storage process decomposition of PHP source code analysis variables. after the declaration of PHP variables, this article breaks down a series of actions behind the interpreter, for more information, see the following PHP code:
The code is as follows:
$ Php_var = 1;
The code corresponding to C is:
The code is as follows:
Zval * c_var; // defines the PHP variable pointer
MAKE_STD_ZVAL (c_var); // initialize the PHP variable
ZVAL_LONG (c_var, 1); // value assignment
ZEND_SET_SYMBL (EG (active_symbol_table), "php_var", c_var); // register with the global variable symbol table
I. first look at the first line: zval * c_var; // declare a zval pointer c_var; the structure of zval is as follows:
The code is as follows:
Struct _ zval_struct {
/* Variable information */
Zvalue_value value;/* Variable value */
Zend_uint refcount;/* reference count, used for garbage collection */
Zend_uchar type;/* variable type */
Zend_uchar is_ref;/* whether it is a reference variable */
};
Typedef struct _ zval_struct zval;
The structure of zvalue_value is as follows:
The code is as follows:
Typedef union _ zvalue_value {
Long lval;/* long integer */
Double dval;/* double precision type */
Struct {/* string type value */
Char * val;
Int len;
} Str;
HashTable * ht;/* array type value */
Zend_object_value obj;/* object type value */
} Zvalue_value;
II. Next, let's take a look at the second line: MAKE_STD_ZVAL (new_val); // variables related to macro initialization, as shown below: // Initialization
The code is as follows:
# Define MAKE_STD_ZVAL (zv )\
ALLOC_ZVAL (zv );\
INIT_PZVAL (zv );
# Define ALLOC_ZVAL (z )\
ZEND_FAST_ALLOC (z, zval, ZVAL_CACHE_LIST)
# Define ZEND_FAST_ALLOC (p, type, fc_type )\
(P) = (type *) emalloc (sizeof (type ))
# Define INIT_PZVAL (z )\
(Z)-> refcount = 1 ;\
(Z)-> is_ref = 0;
Expanded:
The code is as follows:
(C_var) = (zval *) emalloc (sizeof (zval); // allocate memory
(C_var)-> refcount = 1; // the reference count is initialized.
(C_var)-> is_ref = 0; // whether to reference
We can see that the function is to allocate memory and initialize refcount, is_ref
3. the macro related to ZVAL_LONG (c_var, 1) in the third row is as follows:
The code is as follows:
// Define the value
# Define ZVAL_LONG (z, l ){\
Z_TYPE_P (z) = IS_LONG ;\
Z_LVAL_P (z) = l ;\
}
# Define Z_TYPE_P (zval_p) Z_TYPE (* zval_p)
# Define Z_TYPE (zval). type
# Define Z_LVAL_P (zval_p) Z_LVAL (* zval_p)
# Define Z_LVAL (zval). value. lval
Expanded:
The code is as follows:
(* C_var). type = IS_LONG;
(* C_var). value = 1;
4. Next, let's look at the fourth line: ZEND_SET_SYMBOL (EG (active_symbol_table), "php_var", c_var). First, it indicates that the PHP variable exists in a hashtable
The code is as follows:
Struct _ zend_executor_globals {
....
HashTable symbol_table; // symbol table of global variables
HashTable * active_symbol_table; // symbol table of local variables
.....
};
The Key of Hashtable is the name of the variable, that is, php_var. The value is the pointer to the PHP variable, that is, the c_var pointer. the related macro is:
The code is as follows:
# Define ZEND_SET_SYMBOL (symtable, name, var )\{\
Char * _ name = (name );\
ZEND_SET_SYMBOL_WITH_LENGTH (symtable, _ name, strlen (_ name) + 1, var, 1, 0 );\
}
// The main implementation is the following function:
# Define ZEND_SET_SYMBOL_WITH_LENGTH (symtable, name, name_length, var, _ refcount, _ is_ref )\
{
Zval ** orig_var ;\
If (zend_hash_find (symtable, (name), (name_length), (void **) & orig_var) = SUCCESS \
& PZVAL_IS_REF (* orig_var )){\
(Var)-> refcount = (* orig_var)-> refcount ;\
(Var)-> is_ref = 1 ;\
If (_ refcount ){\
(Var)-> refcount + = _ refcount-1 ;\
}\
Zval_dtor (* orig_var );\
** Orig_var = * (var );\
FREE_ZVAL (var );\
} Else {\
(Var)-> is_ref = _ is_ref ;\
If (_ refcount ){\
(Var)-> refcount = _ refcount ;\
}\
Zend_hash_update (symtable, (name), (name_length), & (var), sizeof (zval *), NULL );\
}\
}
This function has the following functions:
1. if the global symbol table already has this variable and it is of reference type
A. assign the reference count refcount and is_ref information of the original variable to c_var;
B. release the zvalue of the original variable. for example, if the original value points to a mysql connection resource, the resource is released.
C. assign the variable pointed to by c_var to the original variable d. release the memory space of c_var to ensure that, if the variable is applied, the value changes together. For example, if $ B = &;
2. if the global symbol table does not exist or the variable does not reference the variable, the value is changed directly.