php unset變量

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

1)詞法分析php

 

<ST_IN_SCRIPTING>"unset" {
    return T_UNSET;
}

 

2)語法分析node

unticked_statement:數組

    |    T_UNSET '(' unset_variables ')' ';'          //unset($a,$b) 還能這麼用呢,第一次知道 吐舌笑臉ui

 

unset_variables:
        unset_variable
    |    unset_variables ',' unset_variable
;spa

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

 

3)生成opcodeblog

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)執行opcodeci

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) get

 

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;hash

            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; }

相關文章
相關標籤/搜索