【PHP7源碼學習】2019-04-04 PHP中while的實現

grapephp

所有視頻:https://segmentfault.com/a/11...segmentfault


引入

在咱們日常寫PHP代碼老是會用到while語句,那麼咱們有沒有去考慮過while語句是怎麼實現的呢?函數

咱們來看下面的這段代碼:學習

<?php
$a = 1;
while($a){
}

咱們知道這段代碼是個死循環,毋庸置疑,可是在PHP中,它是如何作到的呢?請看下文。spa

分析

首先,咱們本身分析一下這個while語句,若是讓咱們來設計,咱們會如何設計呢?筆者寫出腦補幾點:設計

  1. PHP是C語言編寫的,直接去沿用C的語法,while套用。
  2. 在源碼設計中加入goto語句。
  3. for循環嵌套if語句
  4. 等等(你們能夠頭腦風暴下)

接下來咱們看一下PHP源碼中是如何實現的。
俗話說,實踐是檢驗真理的惟一道路,那麼咱們就去gdb一下,調試上邊的代碼,用事實說話。
接下來是gdb的過程,由於是ast樹的構建過程,以前文章已經詳細解釋過,此處再也不贅述,文章傳送門:2019-05-07 發佈【PHP源碼學習】2019-03-21 AST,gdb過程如圖1所示:
clipboard.png
此時咱們能夠知道AST就是長的圖二的樣子,如圖2:
clipboard.png
ast樹創建好了,可是他執行了什麼指令,咱們仍是得去看看他的opcode是什麼,繼續gdb代碼,執行到zend_file_context_end以後,此時opcode已經執行完成,咱們打印下gdb結果,如圖3所示:
clipboard.png
ps:在圖三中咱們能夠看到有四條指令,對應下分別爲:調試

  • ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_UNUSED_HANDLER:對應$a = 1;
  • ZEND_JMP_SPEC_HANDLER:跳轉到下一條opcode
  • ZEND_JMPNZ_SPEC_CV_HANDLER:進行while循環,若是循環條件不爲0則跳回循環體
  • ZEND_RETURN_SPEC_CONST_HANDLER:PHP虛擬機自動給腳本加的return

由此咱們能夠發現while語句的實現由ZEND_JMP_SPEC_HANDLER與ZEND_JMPNZ_SPEC_CV_HANDLER來實現,學過彙編的同窗應該知道,JMP是無條件跳轉的意思,在這裏是跳轉到下一個opcode,即JMPNZ,JMPNZ則是條件不爲0時纔會跳轉。由此咱們能夠畫出while的執行流程,如圖所示:
clipboard.png
至此咱們能夠獲得while的執行流程了,固然若是想知道這些是如何進行運做的,建議你們去看一看pass_two這個函數,裏邊有如何設置opcode的。code

結論

while語句並非嵌套C語言的while語句,也不是咱們以前的種種猜想,他的核心是經過jump,jumpnz來進行控制的。
ps:設計者可真是個天才。 :手動滑稽視頻

延伸

若是說明白了while語句,那麼do_while又是怎麼一回事呢?你們能夠自行思考一下blog

相關文章
相關標籤/搜索