<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # zend執行過程 ## EG變量 executor_globals是一個全局變量,存儲著許多信息(當前上下文、符號表、函數/類/常量表、堆棧等),EG宏就是用于訪問executor_globals的某個成員. ```c //zend_global.h/_zend_executor_globals struct _zend_executor_globals { ... zend_array symbol_table; /* PHP全局變量表:$_GET,$_POST等 main symbol table */ HashTable included_files; /* 已經引入的腳本 files already included */ JMP_BUF *bailout; /* try-catch保存的catch跳轉位置 */ int error_reporting; int exit_status; HashTable *function_table; /* 全部已編譯的function哈希表,包括內部函數,用戶自定義函數,函數調用將從這里查找 function symbol table */ HashTable *class_table; /* 全部已編譯的class哈希表,new class 時從此查找 class table */ HashTable *zend_constants; /* 常量符號表 constants table */ zval *vm_stack_top;//棧內存池剩余可用內存起始位置 zval *vm_stack_end;//棧內存池結束位置 zend_vm_stack vm_stack; /* 運行棧內存池,一塊空白的內存,用于分配PHP執行期間的一些數據結構(zend_execute),局部變量從這里分配 */ struct _zend_execute_data *current_execute_data; /* 指向當前正在執行的運行棧,函數調用就是分配一個新的zend_execute_data,然后將EG(current_execute_data)指向新的結構繼續執行,調用完畢再還原回去,類似匯編call,ret指令的作用 */ zend_class_entry *fake_scope; /* used to avoid checks accessing properties */ ... HashTable *in_autoload; /* 在類的自動加載過程中會使用到 */ zend_function *autoload_func; /* 自動加載回調函數:__autoload() */ zend_bool full_tables_cleanup; ... HashTable regular_list; HashTable persistent_list; /* 持久化符號表,request請求結束后不釋放可以跨request共享,在php_module_shutdown()階段清理,*/ ... }; //zend/zend_globals_macros.h # define EG(v) (executor_globals.v) ``` # zend_compile.h/_zend_execute_data zend_execute_data是執行過程中最核心的一個結構,每次函數的調用、include/require、eval等都會生成一個新的結構,它表示當前的作用域、代碼的執行位置以及局部變量的分配等等,等同于機器碼執行過程中stack的角色. ```c //64位機器上,占80個字節 struct _zend_execute_data { const zend_op *opline;/* 指向當前執行的opcode,初始時指向zend_op_array起始位置executed opline */ zend_execute_data *call;/* 當前正在調用的子函數 current call */ zval *return_value;//返回值指針 zend_function *func;/* 當前執行的函數自身(非函數調用時為空)executed function */ zval This;/* 這個值并不僅僅是面向對象的this,還有另外兩個值也通過這個記錄:call_info + num_args,分別存在zval.u1.reserved、zval.u2.num_args */ zend_execute_data *prev_execute_data;//調用時指向父級調用位置作用空間 zend_array *symbol_table;//全局變量符號表 #if ZEND_EX_USE_RUN_TIME_CACHE void **run_time_cache;/* cache op_array->run_time_cache */ #endif #if ZEND_EX_USE_LITERALS zval *literals;/* 字面量數組,與func.op_array->literals相同 //cache op_array->literals*/ #endif }; ``` ![op_array與execute_data關系](https://box.kancloud.cn/005c7ed47923adba803d0f313417ad5f_450x676.png) ### 運行棧幀布局: #### linux程序運行內存分配 ![linux程序運行內存分配圖](https://box.kancloud.cn/54c6b45c720066c49af3c93e125832b5_517x366.jpg) #### C程序運行棧 ![C程序運行棧](https://box.kancloud.cn/765da843dfd4eba7b53ad9301fc8adaa_328x492.png) ### ZEND分配運行棧 ```c //Zend/zend_execute.c : 2094 /* * 棧幀布局,所有運行棧空間是同時分配的 / Stack Frame Layout (the whole stack frame is allocated at once) * ================== * * +=========================================================+ * EG(current_execute_data) -> | zend_execute_data | * +---------------------------------------------------------+ * EX_CV_NUM(0) ---------> | VAR[0] = ARG[1] | 參數(arguments) * | ... | * | VAR[op_array->num_args-1] = ARG[N] | * | VAR[num_args] = CV[num_args] | 局部變量(remaining CVs) * | ... | * | VAR[op_array->last_var-1] = CV[last_var-1] | * | VAR[op_array->last_var] = TMP[0] | 臨時變量(TMP/VARs) * | ... | * | VAR[op_array->last_var+op_array->T-1] = TMP[T] | * | ARG[N+1] (extra_args) | 其余參數(extra arguments) * | ... | * +---------------------------------------------------------+ */ ``` #### 變量類型: ```c // Zend/zend_compile.h #define IS_CONST (1<<0) //1 #define IS_TMP_VAR (1<<1) //2 #define IS_VAR (1<<2) //4 #define IS_UNUSED (1<<3) //8 #define IS_CV (1<<4) //16 ``` * IS_CONST:字面量,編譯時就可確定且不會改變的值,比如:$a = "hello~",其中字符串"hello~"就是常量 * IS_TMP_VAR:臨時變量,比如:$a = "hello~" . time(),其中"hello~" . time()的值類型就是IS_TMP_VAR,再比如:$a = "123" + $b,"123" + $b的結果類型也是IS_TMP_VAR,從這兩個例子可以猜測,臨時變量多是執行期間其它類型組合現生成的一個中間值,由于它是現生成的,所以把IS_TMP_VAR賦值給IS_CV變量時不會增加其引用計數 * IS_VAR:PHP變量,這個很容易認為是PHP腳本里的變量,其實不是,這里PHP變量的含義可以這樣理解:PHP變量是沒有顯式的在PHP腳本中定義的,不是直接在代碼通過$var_name定義的.這個類型最常見的例子是PHP函數的返回值,再如$a[0]數組這種,它取出的值也是IS_VAR,再比如$$a這種 * IS_UNUSED:表示操作數沒有用 * IS_CV:PHP腳本變量,即腳本里通過$var_name定義的變量,這些變量是編譯階段確定的,所以是compile variable, 除了分配execute_data的存儲空間外,還分配了CV(compiled variable,即PHP變量)、TMP_VAR(臨時變量,例如執行if (!$a) echo 'a';,就需要一個臨時變量來存儲!$a的結果)的存儲空間. EX宏是用于訪問execute_data的成員 堆棧的結構體,堆棧的設計跟PHP 5類似: struct _zend_vm_stack { zval *top; /* 指向堆棧的頂端 */ zval *end; /* 指向堆棧的底端 */ zend_vm_stack prev; /* 指向上一個堆棧,當前堆棧剩余空間不足時,會向內存管理器申請新的內存創建新的堆棧 */ }; #### opcode執行時使用的寄存器優化 ```c define ZEND_VM_FP_GLOBAL_REG "%r14" //棧幀指針(frame pointer)寄存器 define ZEND_VM_IP_GLOBAL_REG "%r15" //指令指針寄存器 register const zend_op* volatile opline __asm__(ZEND_VM_IP_GLOBAL_REG); register zend_execute_data* volatile execute_data __asm__(ZEND_VM_FP_GLOBAL_REG); ``` ## 參考資料: https://yangxikun.github.io/php/2016/11/04/php-7-func-call.html https://github.com/pangudashu/php7-internal/ https://nikic.github.io/2017/04/14/PHP-7-Virtual-machine.html
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看