Variable Assignment PHP kernel implementation (ii)

Source: Internet
Author: User

<?php
$a = 1;
$b =& $a;
$c = 2;
$a =& $c;
echo $a. " \ n ";
Echo $b;

2

1

Conclusion:

The memory address of the left value is saved first, because the memory address will be assigned again

1) The right value is a reference

Go to 2.2 2.3 2.4 step

Example:

<? PHP $a=1;
$c = 2; $b=&$a; When executed here, it belongs to the 2nd case $c=&$a; When executed here, it belongs to the 1th case,

2) Rvalue is not a reference, REFCOUNT_GC minus 1 of the right value

2.1) If refcount_gc minus 1, greater than 0, indicating that there are other variables used together with zval, you need to allocate memory to the right value separately

2.2) Assign an rvalue (memory address) to an Lvalue value

2.3) refcount_gc plus 1, and set is_ref=1

2.4) Destroy the left value

2.3.1) minus 1 of the zval of the left value saved above. refcount_gc

2.3.1.1) The face value is 0, then Zval_dtor

2.3.1.2) above value greater than 0, enter GC buffer, but the Zval type must be an object or array

  

You can find $ A, $b, $c all CV variables

When the PHP interpreter executes to the $b=& $a, it executes to the following handler

Static intzend_fastcall Zend_assign_ref_spec_cv_cv_handler (Zend_opcode_handler_args) {use_opline zend_free_op free_op2; Zval**variable_ptr_ptr; Zval**value_ptr_ptr;    Save_opline (); Value_ptr_ptr= _get_zval_ptr_ptr_cv_bp_var_w (Ex_cvs (), Opline->op2.vartsrmls_cc); if(IS_CV = = Is_var &&value_ptr_ptr&&! Z_ISREF_PP (value_ptr_ptr) &&Opline->extended_value = = Zend_returns_function &&! ex_t (OPLINE-&GT;OP2.var).var. Fcall_returned_reference) {        if(FREE_OP2.var==NULL) {Pzval_lock (*VALUE_PTR_PTR);/*undo the effect of Get_zval_ptr_ptr ()*/} zend_error (E_strict,"Only variables should is assigned by reference"); if(Unexpected (EG (exception)! =NULL))        {handle_exception (); }        returnZend_assign_spec_cv_cv_handler (Zend_opcode_handler_args_passthru); } Else if(IS_CV = = Is_var && Opline->extended_value = =zend_returns_new) {Pzval_lock (*value_ptr_ptr); }    if(IS_CV = = Is_var && Unexpected (ex_t (OPLINE-&GT;OP1.var).var. ptr_ptr = = &ex_t (opline->op1.var).var. PTR)) {Zend_error_noreturn (E_error,"cannot assign by reference to overloaded object"); } variable_ptr_ptr= _get_zval_ptr_ptr_cv_bp_var_w (Ex_cvs (), Opline->op1.vartsrmls_cc); if((IS_CV = = Is_var && unexpected (value_ptr_ptr = = NULL)) | |(IS_CV= = Is_var && unexpected (variable_ptr_ptr = =NULL))) {Zend_error_noreturn (E_error,"cannot create references To/from string offsets nor overloaded objects"); } zend_assign_to_variable_reference (Variable_ptr_ptr, value_ptr_ptr tsrmls_cc); Perform the assigned operation hereif(IS_CV = = Is_var && Opline->extended_value = =zend_returns_new)    {z_delref_pp (variable_ptr_ptr); }    if(return_value_used (opline)) {Pzval_lock (*variable_ptr_ptr); Ai_set_ptr (&ex_t (Opline->result.var), *variable_ptr_ptr);    } check_exception (); Zend_vm_next_opcode ();}

Static voidZend_assign_to_variable_reference (Zval **variable_ptr_ptr, Zval * *value_ptr_ptr tsrmls_dc) {Zval*variable_ptr = *variable_ptr_ptr;    For $b=& $a, variable_ptr store is $b corresponding to the value zval the corresponding memory address (there is no zval), VARIABLE_PTR_PTR implementation is the address of the $b variable, $b store the corresponding Zval memory address Zval*value_ptr = *value_ptr_ptr; For $b=& $a, Value_ptr is the address of the value 1 of the $a, Value_ptr_ptr holds the address of a $ A variable, $a holds 1 of the memory addressif(Variable_ptr = = &eg (error_zval) | | value_ptr = = &EG (Error_zval)) {Variable_ptr_ptr= &EG (UNINITIALIZED_ZVAL_PTR); } Else if(Variable_ptr! =value_ptr) {        if(!pzval_is_ref (value_ptr)) {//The right value is not a reference at this time/*Break it away*/z_delref_p (VALUE_PTR); The effect of REFCOUNT_GC minus 1 is to see if there are other variables that also use the valu_ptr_ptr corresponding zval, and if so, reassign Zvalif(Z_refcount_p (VALUE_PTR) >0) {Alloc_zval (*value_ptr_ptr); Zval_copy_value (*value_ptr_ptr, value_ptr); Value_ptr= *value_ptr_ptr; Zendi_zval_copy_ctor (*value_ptr); } z_set_refcount_p (Value_ptr,1); Because the above minus 1, so here to add 1, z_set_isref_p (VALUE_PTR);//Set Is_ref to 1}*variable_ptr_ptr =value_ptr;//will variable_ptr_ptr this address pointer content to 1 of the address z_addref_p (VALUE_PTR);//REFCOUNT_GC plus 1 zval_ptr_dtor (&variable_ptr); freeing memory as appropriate
} Else if(!z_isref_p (variable_ptr)) { if(Variable_ptr_ptr = =value_ptr_ptr) {Separate_zval (variable_ptr_ptr); } Else if(variable_ptr==&EG (uninitialized_zval)|| Z_refcount_p (VARIABLE_PTR) >2) { /*we need to separate*/z_set_refcount_p (Variable_ptr, Z_refcount_p (variable_ptr)-2); Alloc_zval (*variable_ptr_ptr); Zval_copy_value (*variable_ptr_ptr, variable_ptr); Zval_copy_ctor (*variable_ptr_ptr); *value_ptr_ptr = *variable_ptr_ptr; Z_SET_REFCOUNT_PP (Variable_ptr_ptr,2); } z_set_isref_pp (VARIABLE_PTR_PTR); }}

//ZEND_VARIABLES.CZend_apivoid_zval_copy_ctor_func (Zval *Zvalue zend_file_line_dc) {    Switch(Z_type_p (Zvalue) &is_constant_type_mask) {         CaseIs_resource: {tsrmls_fetch (); Zend_list_addref (Zvalue-value.lval); }             Break;  CaseIs_bool: CaseIs_long: CaseIs_null: Break;  Caseis_constant: CaseIs_string:check_zval_string_rel (Zvalue); if(!is_interned (zvalue->value.str.val)) {Zvalue->value.str.val = (Char*) Estrndup_rel (Zvalue->value.str.val, zvalue->Value.str.len); }             Break;  CaseIs_array: CaseIs_constant_array: {zval*tmp; HashTable*original_ht = zvalue->value.ht; HashTable*tmp_ht =NULL;                Tsrmls_fetch (); if(zvalue->value.ht = = &EG (symbol_table)) {                    return;/* do nothing*/} alloc_hashtable_rel (TMP_HT); Zend_hash_init (Tmp_ht, Zend_hash_num_elements (ORIGINAL_HT), NULL, Zval_ptr_dtor,0); Zend_hash_copy (Tmp_ht, Original_ht, (copy_ctor_func_t) Zval_add_ref, (void*) &tmp,sizeof(Zval *)); Zvalue->value.ht =Tmp_ht; }             Break;  Caseis_object: {tsrmls_fetch (); Z_obj_ht_p (Zvalue)-add_ref (Zvalue tsrmls_cc); }             Break; }}
// zend_api.h #define Check_zval_string_rel (z)     if'""STRING is not Zero-terminated (%s) (Source:%s:%d)", Z_strval_p (Z) zend_file_line_relay_cc);}

// zend_alloc.h #define Estrndup_rel (s, length)                    _estrndup ((s), (length) zend_file_line_relay_cc zend_file_line_cc)
//ZEND_ALLOC.CZend_apiChar*_estrndup (Const Char*s,UINTlength zend_file_line_dc zend_file_line_orig_dc) {    Char*p; #ifdef zend_signals tsrmls_fetch ();#endifhandle_block_interruptions (); P= (Char*) _emalloc (length+1zend_file_line_relay_cc zend_file_line_orig_relay_cc); if(Unexpected (P = =NULL))        {handle_unblock_interruptions (); returnp;    } memcpy (P, s, length); P[length]=0;    Handle_unblock_interruptions (); returnp;}

Zend_execute_api.c
Zend_apivoid_zval_ptr_dtor (zval **zval_ptr zend_file_line_dc)/* {{{ */{#ifdebug_zend>=2printf ("reducing refcount for%x (%x):%d->%d\n", *zval_ptr, Zval_ptr, Z_refcount_pp (zval_ptr), z_refcount_pp (zval_ptr)-1);#endifz_delref_pp (ZVAL_PTR); if(Z_REFCOUNT_PP (zval_ptr) = =0) {tsrmls_fetch (); if(*zval_ptr! = &EG (Uninitialized_zval)) {Gc_remove_zval_from_buffer (*zval_ptr); Zval_dtor (*zval_ptr); Efree_rel (*zval_ptr); } } Else{tsrmls_fetch (); if(Z_REFCOUNT_PP (zval_ptr) = =1) {z_unset_isref_pp (zval_ptr); } gc_zval_check_possible_root (*zval_ptr); }}

#include <stdio.h>#include<stdlib.h>intMain () {Char*variable="ABC"; Char**variable_ptr_ptr=variable; Char*variable_ptr=*variable_ptr_ptr; Char*value="Def"; Char**value_ptr_ptr=value; Char*value_ptr=*value_ptr_ptr; *variable_ptr_ptr=value_ptr; return 0; }

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.