ホームページ > php教程 > php手册 > PHPソースコード解析におけるグローバルキーワード

PHPソースコード解析におけるグローバルキーワード

WBOY
リリース: 2016-06-21 08:52:47
オリジナル
2314 人が閲覧しました

仕方がないので、PHP の字句解析、構文解析、オペコードの生成、実行、プロセス全体に至るまで、グローバル キーワードの実装を詳細に体系的に分析しました。

スクリプトに記述する場合:

$var = "ラルエンス";

関数サンプル(){

グローバル $var;

}

?>

、PHP が関数スコープ内のグローバル変数をどのように見つけるかご存知ですか?

前回の記事 (PHP 原則の深い理解: オペコード) で述べたように、PHP の実行は次の段階を経ます。

1.スキャン(Lexing)、PHPコードを言語フラグメント(トークン)に変換します

2. トークンを解析し、単純で意味のある表現に変換する

3. コンパイル、式を Opocdes にコンパイルします

4. 実行では、オペコードを一度に1つずつ順番に実行することで、PHPスクリプトの機能を実現します。

次に、最初の段階は当然のことながら、字句解析段階での

のスキャンです。

グローバル $var;

次のように解析されます:

T_GLOBAL 変数;

次は解析段階です:

T_GLOBAL 変数;

Yacc の受け渡しルール:

ステートメント:

T_GLOBAL global_var_list ';'

....

global_var_list:

global_var_list ',' global_var { zend_do_fetch_global_variable(&$3, NULL, ZEND_FETCH_GLOBAL_LOCK TSRMLS_CC) }

global_var { zend_do_fetch_global_variable(&$1, NULL, ZEND_FETCH_GLOBAL_LOCK TSRMLS_CC) }

;

このうち、zend_do_fetch_global_variable は実際にオペコードを生成する関数です:

zend_op *opline;

……

opline->opcode = ZEND_FETCH_W;

opline->result.op_type = IS_VAR;

……

opline->op2.u.EA.type = ZEND_FETCH_GLOBAL_LOCK;

ZEND_FETCH_W の op_handler は次のとおりです:

ZEND_VM_HANDLER(83, ZEND_FETCH_W, CONSTTMPVARCV, ANY) { ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, タイプ, BP_VAR_W) }

zend_fetch_var_adress_helper を見てみましょう:

..... target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), type, varname TSRMLS_CC);/* if (!target_symbol_table) { ZEND_VM_NEXT_OPCODE() }*/ if (zend_hash_find(target_symbol_table, varname->value.str) .val, varname->value.str.len+1, (void **) &retval) == FAILURE) { switch (type) { case BP_VAR_R: case BP_VAR_UNSET: zend_error(E_NOTICE,"未定義の変数: %s", Z_STRVAL_P(varname)); /* ブレークが意図的に欠落しています */ case BP_VAR_IS: retval = &EG(uninitialized_zval_ptr) Break; case BP_VAR_RW: zend_error(E_NOTICE,"未定義の変数: %s", Z_STRVAL_P(varname));意図的に */ case BP_VAR_W: { zval *new_zval = &EG(uninitialized_zval); new_zval->refcount++(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval) } EMPTY_SWITCH_DEFAULT_CASE() } }

コアは zend_get_targer_symbol_table 関数であることがわかります:

static inline HashTable *zend_get_target_symbol_table(zend_op *opline, temp_variable *Ts, int type, zval *variable TSRMLS_DC){ switch (opline->op2.u.EA.type) { case ZEND_FETCH_LOCAL: return EG(active_symbol_table); ZEND_FETCH_GLOBAL: ケース ZEND_FETCH_GLOBAL_LOCK: &EG(シンボルテーブル) を返す; ケース ZEND_FETCH_STATIC: if (!EG(active_op_array)->static_variables) { ALLOC_HASHTABLE(EG(active_op_array)->static_variables); gt ; static_variables, 2, NULL, ZVAL_PTR_DTOR, 0); } return EG(active_op_array)->static_variables() } return NULL;}

問題は明らかです。つまり、変数をグローバル化すると、Zend はグローバルのsymbol_table にアクセスしてそれを見つけ、対応する変数をグローバルのsymbol_table に割り当てます。

このメカニズムを通じて、グローバル変数が実装されます。



関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のおすすめ
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート