PHP內核研究 靜態變量

靜態變量

它可以是 靜態全局變量,如果不調用unset,那麼這個靜態變量會一直存在,直到程序退出時才由Zend內存管理來釋放

它可以是 靜態局部變量:在函數裏定義,函數執行完後,該靜態變量不會消失

它可以是 靜態成員變量:在類裏定義,它可以在所有類的對象中共享

例如

 

  1. <?php 
  2.   
  3. function test(){ 
  4.   
  5. static $a=1; 
  6.   
  7. $a++; 
  8.   
  9.   
  10. test(); //$a=2 
  11.   
  12. test();//$a=3 
  13.   
  14. test();//$a=4 

 

最後 $a=4了..

下面我們從內核裏面分析它

static不是一個函數 ,它是一個關鍵字 ,所以只能從LEX語法分析中來查找

打開 zend/zend_language_scanner.l 查找 static

找到代碼

 

  1. <ST_IN_SCRIPTING>"static" { 
  2.         return T_STATIC; 

 

是一個宏
再打開 zend/zend_language_pareser.l
搜 T_STATIC
找到代碼

 

  1. T_STATIC static_var_list ';' 

跟進 static_var_list
找到代碼

 

  1. static_var_list: 
  2.                 static_var_list ',' T_VARIABLE { zend_do_fetch_static_variable(&$3, NULL, ZEND_FETCH_STATIC TSRMLS_CC); } 
  3.         |       static_var_list ',' T_VARIABLE '=' static_scalar { zend_do_fetch_static_variable(&$3, &$5, ZEND_FETCH_STATIC TSRMLS_CC); } 
  4.         |       T_VARIABLE  { zend_do_fetch_static_variable(&$1, NULL, ZEND_FETCH_STATIC TSRMLS_CC); } 
  5.         |       T_VARIABLE '=' static_scalar { zend_do_fetch_static_variable(&$1, &$3, ZEND_FETCH_STATIC TSRMLS_CC); } 
  6.   

就是這裏了..它由PHP的語法分析程序 解析成上面的代碼
zend_do_fetch_static_variable 這個函數就是了
它在zend/zend_compile.c裏定義
代碼如下

 

  1. void zend_do_fetch_static_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC) 
  2.         zval *tmp;  //一個臨時變量 
  3.         zend_op *opline; 
  4.         znode lval; 
  5.         znode result; 
  6.   
  7.         ALLOC_ZVAL(tmp); //申請一塊內存 
  8.   
  9.         if (static_assignment) { 
  10.                 *tmp = static_assignment->u.constant; 
  11.         } else { 
  12.                 INIT_ZVAL(*tmp); 
  13.         } 
  14.         if (!CG(active_op_array)->static_variables) {//初始化靜態變量的HASH 鍵值 
  15.                 ALLOC_HASHTABLE(CG(active_op_array)->static_variables); 
  16.                  //初始化HASH值 
  17.                 zend_hash_init(CG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0); 
  18.         } 
  19.         zend_hash_update(CG(active_op_array)->static_variables, varname->u.constant.value.str.val, varname->u.constant.value.str.len+1, &tmp, sizeof(zval *), NULL); 
  20.   
  21.         if (varname->op_type == IS_CONST) { 
  22.                 if (Z_TYPE(varname->u.constant) != IS_STRING) { 
  23.                         convert_to_string(&varname->u.constant); 
  24.                 } 
  25.         } 
  26.   
  27.         opline = get_next_op(CG(active_op_array) TSRMLS_CC); 
  28.         opline->result.op_type = IS_VAR; 
  29.         opline->result.u.EA.type = 0; 
  30.         opline->result.u.var = get_temporary_variable(CG(active_op_array)); 
  31.         opline->op1 = *varname; 
  32.         SET_UNUSED(opline->op2); 
  33.         opline->op2.u.EA.type = ZEND_FETCH_STATIC; 
  34.         result = opline->result; 
  35.   
  36.         if (varname->op_type == IS_CONST) { 
  37.                 zval_copy_ctor(&varname->u.constant); 
  38.         } 
  39.         fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */ 
  40.   
  41.         if (fetch_type == ZEND_FETCH_LEXICAL) { 
  42.                 znode dummy; 
  43.   
  44.                 zend_do_begin_variable_parse(TSRMLS_C); 
  45.                 zend_do_assign(&dummy, &lval, &result TSRMLS_CC); 
  46.                 zend_do_free(&dummy TSRMLS_CC); 
  47.         } else { 
  48.                 zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC); 
  49.         } 
  50.         CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED; 
  51.   
  52. /*      zval_dtor(&varname->u.constant); */ 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章