php unset变量

<?php
 $a="abc";
 $b="def";
 unset($a,$b);
 echo $a."
";
 echo $b."
";

1)词法分析

<ST_IN_SCRIPTING>"unset" {
    return T_UNSET;
}

2)语法分析

unticked_statement:

    |    T_UNSET '(' unset_variables ')' ';'          //unset($a,$b) 还能这么用呢,第一次知道 吐舌笑脸

unset_variables:
        unset_variable
    |    unset_variables ',' unset_variable
;

unset_variable:
        variable    { zend_do_end_variable_parse(&$1, BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1 TSRMLS_CC); }
;

3)生成opcode

void zend_do_unset(const znode *variable TSRMLS_DC) /* {{{ */
{
    zend_op *last_op;

    zend_check_writable_variable(variable);

    if (variable->op_type == IS_CV) {
        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        opline->opcode = ZEND_UNSET_VAR;
        SET_NODE(opline->op1, variable);
        SET_UNUSED(opline->op2);
        SET_UNUSED(opline->result);
        opline->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
    } else {
        //不是IS_CV类型的处理
    }
}

4)执行opcode

static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
    USE_OPLINE
    zval tmp, *varname;
    HashTable *target_symbol_table;


    SAVE_OPLINE();
    if (IS_CV == IS_CV &&
        IS_UNUSED == IS_UNUSED &&
        (opline->extended_value & ZEND_QUICK_SET)) {
if (EG(active_symbol_table)) {
            zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);

            zend_delete_variable(EX(prev_execute_data), EG(active_symbol_table),  cv->name, cv->name_len+1, cv->hash_value TSRMLS_CC); //从active_symbol_table中清除cv->name以及相应值,再从CV数组中清除此值
            EX_CV(opline->op1.var) = NULL;
        } else if (EX_CV(opline->op1.var)) {
            zval_ptr_dtor(EX_CV(opline->op1.var));
            EX_CV(opline->op1.var) = NULL;
        }
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
    }
    //不会被执行了
}
 
#define CV_DEF_OF(i) (EG(active_op_array)->vars[i])

#undef EX_CV
#define EX_CV(var) EX(CVs)[var]
#undef EX_CVs
#define EX_CVs() EX(CVs)
#undef EX_T
#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset))
#undef EX_Ts
#define EX_Ts() EX(Ts)

 

ZEND_API void zend_delete_variable(zend_execute_data *ex, HashTable *ht, const char *name, int name_len, ulong hash_value TSRMLS_DC) /* {{{ */
{
    if (zend_hash_quick_del(ht, name, name_len, hash_value) == SUCCESS) {
        name_len--;
        while (ex && ex->symbol_table == ht) {
            int i;

            if (ex->op_array) {
                for (i = 0; i < ex->op_array->last_var; i++) {
                    if (ex->op_array->vars[i].hash_value == hash_value &&
                        ex->op_array->vars[i].name_len == name_len &&
                        !memcmp(ex->op_array->vars[i].name, name, name_len)) {
                        ex->CVs[i] = NULL;
                        break;
                    }
                }
            }
            ex = ex->prev_execute_data;
        }
    }
}

ZEND_API int zend_hash_del_key_or_index(HashTable *ht, const char *arKey, uint nKeyLength, ulong h, int flag)
{
    uint nIndex;
    Bucket *p;
#ifdef ZEND_SIGNALS
    TSRMLS_FETCH();
#endif

    IS_CONSISTENT(ht);

    if (flag == HASH_DEL_KEY) {
        h = zend_inline_hash_func(arKey, nKeyLength);
    }
    nIndex = h & ht->nTableMask;

    p = ht->arBuckets[nIndex];
    while (p != NULL) {
        if ((p->h == h)
             && (p->nKeyLength == nKeyLength)
             && ((p->nKeyLength == 0) /* Numeric index (short circuits the memcmp() check) */
                 || !memcmp(p->arKey, arKey, nKeyLength))) { /* String index */
            HANDLE_BLOCK_INTERRUPTIONS();
            if (p == ht->arBuckets[nIndex]) {
                ht->arBuckets[nIndex] = p->pNext;
            } else {
                p->pLast->pNext = p->pNext;
            }
            if (p->pNext) k{
                p->pNext->pLast = p->pLast;
            }
            if (p->pListLast != NULL) {
                p->pListLast->pListNext = p->pListNext;
            } else {
                /* Deleting the head of the list */
                ht->pListHead = p->pListNext;
            }
            if (p->pListNext != NULL) {
                p->pListNext->pListLast = p->pListLast;
            } else {
                ht->pListTail = p->pListLast;
            }
            if (ht->pInternalPointer == p) {
                ht->pInternalPointer = p->pListNext;
            }
            if (ht->pDestructor) {
                ht->pDestructor(p->pData);
            }
            if (p->pData != &p->pDataPtr) {
                pefree(p->pData, ht->persistent);
            }
            pefree(p, ht->persistent);
            HANDLE_UNBLOCK_INTERRUPTIONS();
            ht->nNumOfElements--;
            return SUCCESS;
        }
        p = p->pNext;
    }
    return FAILURE;
}

原文地址:https://www.cnblogs.com/taek/p/3875524.html