成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

PHP-7.1 源代碼學(xué)習(xí):字節(jié)碼生成 之 "$a = 1"

ConardLi / 3619人閱讀

摘要:前言本文通過(guò)分析這個(gè)語(yǔ)句的編譯和執(zhí)行來(lái)窺探解釋執(zhí)行邏輯準(zhǔn)備參考之前的系列文章,在環(huán)境下下載,編譯源代碼將代碼導(dǎo)入中編輯運(yùn)行選項(xiàng),增加運(yùn)行參數(shù)設(shè)置斷點(diǎn)開(kāi)始調(diào)試是一個(gè)測(cè)試腳本,放在目錄下,中只包含一條簡(jiǎn)單的賦值語(yǔ)句調(diào)用堆棧參考之前的系列文章

前言

本文通過(guò)分析 "$a=1" 這個(gè) PHP 語(yǔ)句的編譯和執(zhí)行來(lái)窺探 php-cli 解釋執(zhí)行邏輯

準(zhǔn)備

參考之前的系列文章,在 ubuntu 環(huán)境下下載,編譯 PHP 源代碼

將代碼導(dǎo)入 idea clion IDE 中

編輯運(yùn)行選項(xiàng),增加運(yùn)行參數(shù):-f test.php

設(shè)置斷點(diǎn)開(kāi)始調(diào)試

test.php 是一個(gè)測(cè)試腳本,放在 sapi/cli/ 目錄下,test.php 中只包含一條簡(jiǎn)單的賦值語(yǔ)句:


調(diào)用堆棧

參考之前的系列文章來(lái)了解 php-cli 啟動(dòng)過(guò)程以及語(yǔ)法分析和字節(jié)碼生成的基本概念,這里直接給出調(diào)用堆棧:

我們嘗試從 zend_compile_expr 函數(shù)說(shuō)起

zend_compile_expr

賦值語(yǔ)句 is-a 表達(dá)式,zend_compile_expr 函數(shù)根據(jù) ast 類(lèi)型選擇調(diào)用 zend_compile_assign:

// zend_compile.c

void zend_compile_expr(znode *result, zend_ast *ast) {
    ...
    switch (ast->kind) {
        ...
        case ZEND_AST_ASSIGN:
            zend_compile_assign(result, ast);
            break;
    }
}
zend_compile_assign

賦值語(yǔ)句的 ast 包含兩個(gè) child ast,即 left hand side var(ast->child[0]) 和 right hand side expr(ast->child[1]),var_node 和 expr_node 兩個(gè) znode 類(lèi)型的變量是生成字節(jié)碼過(guò)程使用的中間變量

// zend_compile.c

void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
{
    zend_ast *var_ast = ast->child[0];
    zend_ast *expr_ast = ast->child[1];

    znode var_node, expr_node;
    zend_op *opline;
    uint32_t offset;

    if (is_this_fetch(var_ast)) {
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
    }

    zend_ensure_writable_variable(var_ast);

然后我們來(lái)看看 switch case 語(yǔ)句

// zend_compile.c

switch (var_ast->kind) {
    case ZEND_AST_VAR:
    case ZEND_AST_STATIC_PROP:
        offset = zend_delayed_compile_begin();
        zend_delayed_compile_var(&var_node, var_ast, BP_VAR_W);
        zend_compile_expr(&expr_node, expr_ast);
        zend_delayed_compile_end(offset);
        zend_emit_op(result, ZEND_ASSIGN, &var_node, &expr_node);
        return;
}

剛看到這段代碼可能會(huì)覺(jué)得挺繞的:zend_delayed_xxx 函數(shù)是干啥的?最終生成的字節(jié)碼又保存在哪呢?

zend_emit_op

emit 有 "發(fā)射,散播"的意思,所以 zend_emit_op 可能和字節(jié)碼保存相關(guān):

// zend_compile.c

static zend_op *zend_emit_op(znode *result, zend_uchar opcode,   
znode *op1, znode *op2) /* {{{ */
{
    zend_op *opline = get_next_op(CG(active_op_array));
    opline->opcode = opcode;

    if (op1 == NULL) {
        SET_UNUSED(opline->op1);
    } else {
        SET_NODE(opline->op1, op1);
    }

    if (op2 == NULL) {
        SET_UNUSED(opline->op2);
    } else {
        SET_NODE(opline->op2, op2);
    }

    zend_check_live_ranges(opline);
    if (result) {
        zend_make_var_result(result, opline);
    }
    return opline;
}

這里我們又遇到了全局變量 CG(compile globals),zend_emit_op 先調(diào)用 get_next_op 獲取可用的 zend_op(虛擬機(jī)指令),然后設(shè)置 op1, op2 為 opline 的兩個(gè)操作數(shù)

現(xiàn)在我們知道生成的字節(jié)碼保存在 CG 的 active_op_array 數(shù)組里

總結(jié)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/22318.html

相關(guān)文章

  • PHP-7.1 源代學(xué)習(xí)字節(jié)生成 概述

    摘要:前言字節(jié)碼生成編譯的代碼主要集中在,文件中包含大量的函數(shù),基本上一個(gè)函數(shù)對(duì)應(yīng)語(yǔ)法規(guī)則文件一個(gè)非終結(jié)符,函數(shù)是所有函數(shù)的入口數(shù)據(jù)結(jié)構(gòu)結(jié)構(gòu)體是字節(jié)碼抽象結(jié)構(gòu)體并沒(méi)有像名字那樣簡(jiǎn)單,它包含了大量的字段供虛擬機(jī)在運(yùn)行時(shí)使用一如既往的簡(jiǎn)單,直觀,相比 前言 字節(jié)碼生成(編譯)的代碼主要集中在 zend_compile.c ,文件中包含大量的 zend_compile_xxx 函數(shù),基本上一個(gè)函數(shù)...

    1fe1se 評(píng)論0 收藏0
  • PHP-7.1 源代學(xué)習(xí)字節(jié)在 Zend 虛擬機(jī)中的解釋執(zhí)行 概述

    摘要:前言本文簡(jiǎn)要介紹虛擬機(jī)解釋執(zhí)行字節(jié)碼的基本邏輯以及相關(guān)的數(shù)據(jù)結(jié)構(gòu),關(guān)于源代碼的下載,編譯,調(diào)試可以參考之前的系列文章我們來(lái)看看執(zhí)行一個(gè)簡(jiǎn)單的腳本的調(diào)用棧由于是執(zhí)行腳本文件,所以調(diào)用了函數(shù),最終調(diào)用函數(shù)和其它語(yǔ)言編寫(xiě)的系統(tǒng)軟件類(lèi)似,函數(shù)中 前言 本文簡(jiǎn)要介紹 zend 虛擬機(jī)解釋執(zhí)行字節(jié)碼的基本邏輯以及相關(guān)的數(shù)據(jù)結(jié)構(gòu),關(guān)于 PHP 源代碼的下載,編譯,調(diào)試可以參考之前的系列文章 exec...

    Tamic 評(píng)論0 收藏0
  • 重學(xué)計(jì)算機(jī)組成原理(五)- "旋轉(zhuǎn)跳躍"的指令實(shí)現(xiàn)

    摘要:在中央處理器的控制部件中,包含的寄存器有指令寄存器和程序計(jì)數(shù)器。這條指令的第一個(gè)操作數(shù),代表累加寄存器在中央處理器中,累加器是一種寄存器,用來(lái)儲(chǔ)存計(jì)算產(chǎn)生的中間結(jié)果。第二個(gè)操作數(shù)則是進(jìn)制的的表示。 showImg(https://ask.qcloudimg.com/http-save/1752328/57mlmnq3i5.png); CPU執(zhí)行的也不只是一條指令,一般一個(gè)程序包含很多條...

    siberiawolf 評(píng)論0 收藏0
  • 從指令的角度看"abc"和new String("abc")

    摘要:但是有一個(gè)的指令,可以把字節(jié)碼翻譯成人類(lèi)能看懂的東西。是文件分解器,可以反編譯即對(duì)編譯的文件進(jìn)行反編譯,也可以查看編譯器生成的字節(jié)碼。現(xiàn)在有一個(gè)類(lèi),定義入下先用編譯成字節(jié)碼,再使用進(jìn)行反編譯。 概要 Java工程師面試官偏愛(ài)的問(wèn)題之一,就是abc和 new String(abc)的區(qū)別是什么?回答的比較好的會(huì)帶出Java堆,棧,常量池,引用等概念。但今天不止如此,我們從指令的角度,去看...

    doodlewind 評(píng)論0 收藏0
  • PHP-7.1 源代學(xué)習(xí):代生成 函數(shù)定義

    摘要:前言本文從函數(shù)定義的語(yǔ)法規(guī)則開(kāi)始,簡(jiǎn)要介紹解釋器如何編譯函數(shù)定義函數(shù)對(duì)應(yīng)的節(jié)點(diǎn)為了看起來(lái)清楚一些,我們將語(yǔ)法規(guī)則定義與語(yǔ)法動(dòng)作分開(kāi)根據(jù)語(yǔ)法動(dòng)作,這條函數(shù)定義規(guī)則會(huì)創(chuàng)建一個(gè)類(lèi)型的結(jié)點(diǎn),我們來(lái)看看方法是一個(gè)通用的方法,通 前言 本文從函數(shù)定義的語(yǔ)法規(guī)則開(kāi)始,簡(jiǎn)要介紹 PHP 解釋器如何 編譯 函數(shù)定義 函數(shù)對(duì)應(yīng)的 AST 節(jié)點(diǎn) 為了看起來(lái)清楚一些,我們將 語(yǔ)法規(guī)則定義 與 語(yǔ)法動(dòng)作分開(kāi): ...

    aisuhua 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<