PHP kernel parsing (ii)

Source: Internet
Author: User

Read the PHP version for PHP-7.1.0 RC3, read the code platform for Linux

In fact, starting with this function, we have entered the range of the Zend engine.

zend_eval_string_ex(exec_direct, NULL, "Command line code", 1)

is actually called ZEND/ZEND_EXECUTE_API.C

zend_eval_stringl_ex(str, strlen(str), retval_ptr, string_name, handle_exceptions);

To go in again is to invoke

result = zend_eval_stringl(str, str_len, retval_ptr, string_name);

Here retval_ptr is null,string_name for "Command Line Code", STR is "echo 12;"

Zend_eval_stringl

In fact, the main process of this function is not complicated. Simplify it down as follows

ZEND_API int zend_eval_stringl(char *str, size_t str_len, zval *retval_ptr, char *string_name) /* {{{ */{ ... new_op_array = zend_compile_string(&pv, string_name); // 这个是把php代码编译成为opcode的过程 ... zend_execute(new_op_array, &local_retval); // 这个是具体的执行过程,执行opcode,把结果存储到local_retval中 ... retval = SUCCESS; return retval;}

First compile php into opcode, then execute this opcode. It's just that this function has some key constructs that need a haircut.

Zval

We'll see

local_retval;

Such a variable, and then do the following for this variable:

Zval_undef (&local_retval); Zval_null (Z) zval_false (Z) zval_true (Z) Zval_bool (Z, b) Zval_long (Z, L) zval_double (Z, D) zval_str (Z, s) zval_interned_str (Z, s) zval_new_str (z, s) Zval_str_copy (z, s) zval_arr (z, a) Zval_new_arr ( z) Zval_new_persistent_arr (z) zval_obj (z, O) ZVAL_RES ( z, R) Zval_new_res (z, H, p, t) zval_new_persistent_res (z, H, p, t) zval_ref (z, R) zval_new_empty_ref (z) zval_new_ref (z, R) zval_new_persistent_ref (z , R) zval_new_ast (z, a) zval_indirect (z, v) zval_ptr (z, p) zval_func (z, f) zval_ce (z, c) zval_error (z)              

PHP is a weak type of language, it can use a $var to represent string,int,array,object and so on. This is thanks to the zval_struct structure.

Structure of the Zvalstruct _zval_struct {zend_value value;Stores a specific value, and its structure varies by typeUnion {struct {zend_endian_lohi_4 (Zend_uchar type,This position marks the type of this Val (is_string/is_int) Zend_uchar type_flags,This position marks the attribute of this Val (is_callable, etc.) Zend_uchar const_flags,Some properties of constants (Is_constant_class) Zend_uchar reserved)Some of the reserved fields} V;uint32_t Type_info;Some additional information about the type} u1;Some key information for saving typesUnion {uint32_t next; //if it is in the hash list, this pointer represents the next element's index 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 */} U2; //some subordinate fields};            

The most important two fields of this interface are value, which stores the values of the variables. The other is the type of the U1.v.type storage variable. Here, value is also a structure

typedefUnion _zend_value {Zend_long lval;/* Long value */double dval; /* Double value */zend_refcounted *counted; zend_string *str; //string Zend_array *arr; //array zend_object *obj; //object Zend_resource *res; //resource zend_reference *ref; //pointer zend_ast_ref *ast; //ast pointer zval *zv; void *ptr; zend_class_entry *ce; //class entity zend_function *func; //function entity struct {uint32_t W1; uint32_t W2; } ww;} Zend_value               

if U1.v.type = = is_string, then VALUE.STR is pointing to the zend_string structure. Well, PHP's garbage collection is done by reference counting, and this counter of the reference count is placed in the zval.value.counted.

We set some macros to set the Zval setting, such as: Zval_stringl is set string, we look at the downward stack:

ZVAL_STRINGL(&pv, str, str_len); // 把pv设置为string类型,值为str

This function is to set the PV to zend_string type

// 带字符串长度的设置zend_sting类型的zval#define ZVAL_STRINGL(z, s, l) do {                        ZVAL_NEW_STR(z, zend_string_init(s, l, 0));            } while (0)

Notice that here is a notation, do {} and (0) to set a macro, this is a good way to write in C, so that the definition of things in the macro for,if, and so on in various process statements will not appear syntax errors. But in fact, when we learn the code, we can ignore the wording of this box.

0)...// 从char* + 长度 + 是否是临时变量(persistent为0表示最迟这个申请的空间在请求结束的时候就进行释放),转变为zend_string*static zend_always_inline zend_string *zend_string_init(const char *str, size_t len, int persistent){ zend_string *ret = zend_string_alloc(len, persistent); // 申请空间,申请的大小为zend_string结构大小(除了val)+ len + 1 memcpy(ZSTR_VAL(ret), str, len); ZSTR_VAL(ret)[len] = ‘\0‘; return ret;}

This function can be seen in a few points:

Persistent

This parameter is used to represent whether the application space is "temporary". The temporary is a memory manager provided by Zend, and the related request data only serves a single request and is released at the end of the request at the latest.

The functions corresponding to the temporary memory request are:

void *emalloc(size_t size)

The function for permanent memory requests is:

malloc
Zend_string_alloc
len, int persistent){    zend_string *ret = (zend_string *)pemalloc(ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(len)), persistent);    GC_REFCOUNT(ret) = 1;    GC_TYPE_INFO(ret) = IS_STRING | ((persistent ? IS_STR_PERSISTENT : 0) << 8); zend_string_forget_hash_val(ret); ZSTR_LEN(ret) = len; return ret;}

Let's look at the structure of zend_string first:

 //string struct _zend_string {Zend  _refcounted_h GC;                //the number of citations used by the GC Zend_ulong H; //if the string as a key in Hashtable needs to be repeated to calculate its hash value, so save a copy here size _t Len; //string length char val[1]; //Flexible array, although we define an array of only one element, but in the actual allocation of memory, will allocate enough memory};_zstr_struct_size (len) Gc+h+len space, and finally gave Val left len+< Span class= "Hljs-number" >1 length #define _ZSTR_STRUCT_SIZE ( Len) (_zstr_header_size + len + 1) ## gc_refcount (ret) = 1; #define Gc_refcount (P) (p)->gc.refcount      

Here we see a structure zend_refcounted_h

typedef struct _zend_refcounted_h {    uint32_t         refcount;            // 真正的计数    union { struct { ZEND_ENDIAN_LOHI_3( zend_uchar type, // 冗余了zval中的类型值 zend_uchar flags, // used for strings & objects中有特定作用 uint16_t gc_info) // 在GC缓冲区中的索引位置 } v; uint32_t type_info; // 冗余zval中的type_info } u; // 类型信息} zend_refcounted_h;

Back to our example, we call the

zend_string_init(s, l, 0) // s=char*(echo 12;) l=8

The actual value of the returned zend_string is:

struct _zend_string {struct  {    uint32_t         refcount;            // 1    union { struct { ZEND_ENDIAN_LOHI_3( zend_uchar type, // IS_STRING zend_uchar flags, uint16_t gc_info) } v; uint32_t type_info; //IS_STRING | 0 => IS_STRING } u; } gc; zend_ulong h; // 0 size_t len; // 8 char val[1]; // echo 12;\0};

Combined into the Zval, then Zval_stringl (&PV, str, str_len); The Zval returned is

Structure of the Zvalstruct _zval_struct {Union _zend_value {Zend_long lval;Double Dval;    Zend_refcounted *counted; Zend_string *str;Point to the zend_string defined above 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, Zend_uchar type_flags, Zend_uchar const_flags, Zend_uchar re served)} V; uint32_t type_info; //is_string_ex} U1; Union { uint32_t next; uint32_t Cache_slot; uint32_t Lineno; uint32_t Num_args; uint32_t Fe_pos; uint32_t Fe_iter_idx; uint32_t access_flags; uint32_t Property_guard;} U2;};               

Here, we have a preliminary understanding of the zval structure.

It is also recommended to remember several common types, which can be useful for subsequent debugging

/* 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*/constant expressions * *#define is_constant#define Is_constant_ast 12
Transfer from http://www.cnblogs.com/yjf512/

PHP kernel parsing (ii)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.