日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

聊一聊關(guān)于php源碼中refcount的疑問(wèn)

瀏覽:264日期:2022-06-05 18:54:05

在瀏覽PHP源碼的時(shí)候,在眾多的*.stub.php中,發(fā)現(xiàn)了這樣的注釋,@refcount 1

通過(guò)翻看build/gen_stub.php源碼,發(fā)現(xiàn)了在解析*.stub.php文件時(shí),關(guān)于返回信息的代碼。

<?php
class ReturnInfo {
    const REFCOUNT_0 = "0";
    const REFCOUNT_1 = "1";
    const REFCOUNT_N = "N";

    const REFCOUNTS = [
self::REFCOUNT_0,
self::REFCOUNT_1,
self::REFCOUNT_N,
    ];

    //...
    
    private function setRefcount(?string $refcount): void
    {
$type = $this->phpDocType ?? $this->type;
$isScalarType = $type !== null && $type->isScalar();

if ($refcount === null) {
    $this->refcount = $isScalarType ? self::REFCOUNT_0 : self::REFCOUNT_N;
    return;
}

if (!in_array($refcount, ReturnInfo::REFCOUNTS, true)) {
    throw new Exception("@refcount must have one of the following values: \"0\", \"1\", \"N\", $refcount given");
}

if ($isScalarType && $refcount !== self::REFCOUNT_0) {
    throw new Exception("A scalar return type of "" . $type->__toString() . "" must have a refcount of "" . self::REFCOUNT_0 . """);
}

if (!$isScalarType && $refcount === self::REFCOUNT_0) {
    throw new Exception("A non-scalar return type of "" . $type->__toString() . "" cannot have a refcount of "" . self::REFCOUNT_0 . """);
}

$this->refcount = $refcount;
    }

明顯,如果返回值類型是scalar,也就是標(biāo)量(基本數(shù)據(jù)類型,整型、浮點(diǎn)型、字符串等),那么refcount指定為0,否則為N。如果設(shè)置了注釋,那么以注釋為最高優(yōu)先級(jí)。

以函數(shù)ob_list_handlers為例:

/**
 * @return array<int, string>
 * @refcount 1
 */
function ob_list_handlers(): array {}

返回值是array,所以默認(rèn)的refcount應(yīng)該是N,但由于設(shè)置了注釋@refcount 1,所以返回值的引用計(jì)數(shù)被替換成1。

這些邏輯我能看懂,但設(shè)置返回值引用計(jì)數(shù)的目的是什么?我還是一頭霧水

我接著往下排查,發(fā)現(xiàn)通過(guò)返回值的引用計(jì)數(shù),在生成func_info的時(shí)候,會(huì)有些不同。如果返回值引用計(jì)數(shù)為1或N,則會(huì)用對(duì)應(yīng)的宏去初始化func_info結(jié)構(gòu)體。如果是0,則不進(jìn)入初始化列表。

以上的代碼邏輯依然可以在gen_stub.php中找到,1393行,getOptimizerInfo

public function getOptimizerInfo(): ?string {
if ($this->isMethod()) {
    return null;
}

if ($this->alias !== null) {
    return null;
}

if ($this->return->refcount !== ReturnInfo::REFCOUNT_1 && $this->return->phpDocType === null) {
    return null;
}

$type = $this->return->phpDocType ?? $this->return->type;
if ($type === null) {
    return null;
}

return "\tF" . $this->return->refcount . "("" . $this->name->__toString() . "", " . $type->toOptimizerTypeMask() . "),\n";
    }

獲取函數(shù)原型的refcount,生成諸如F1()FN()的代碼,生成的頭文件位置在Zend/Optimizer/zend_func_infos.h

static const func_info_t func_infos[] = {
    F1("zend_version", MAY_BE_STRING),
    FN("func_get_args", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_ANY),
    F1("get_class_vars", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF),
    F1("get_class_methods", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING),
    F1("get_included_files", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING),
    FN("set_error_handler", MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_OBJECT|MAY_BE_NULL),
    FN("set_exception_handler", MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_OBJECT|MAY_BE_NULL),
    F1("get_declared_classes", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING),
    F1("get_declared_traits", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING),
    F1("get_declared_interfaces", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING),
    F1("get_defined_functions", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ARRAY),
    F1("get_defined_vars", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF),
    F1("get_resource_type", MAY_BE_STRING),
    F1("get_loaded_extensions", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING),
    F1("get_defined_constants", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY),
    F1("debug_backtrace", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_ARRAY),
    F1("get_extension_funcs", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_FALSE),
    F1("gc_status", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_FALSE|MAY_BE_ARRAY_OF_TRUE),
    F1("bcadd", MAY_BE_STRING),
    F1("bcsub", MAY_BE_STRING),
    F1("bcmul", MAY_BE_STRING),
    F1("bcdiv", MAY_BE_STRING),
    F1("bcmod", MAY_BE_STRING),
    F1("bcpowmod", MAY_BE_STRING),
    F1("bcpow", MAY_BE_STRING),
    F1("bcsqrt", MAY_BE_STRING),
    FN("bzopen", MAY_BE_RESOURCE|MAY_BE_FALSE),
    F1("bzerror", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING),
    F1("cal_from_jd", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_ARRAY_OF_NULL),
    F1("cal_info", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_ARRAY_OF_ARRAY),
    F1("curl_copy_handle", MAY_BE_OBJECT|MAY_BE_FALSE),
    //...
};

再去看看F1FN的宏定義。

typedef struct _func_info_t {
    const char *name;
    unsigned    name_len;
    uint32_t    info;
    info_func_t info_func;
} func_info_t;

#define F0(name, info) \
    {name, sizeof(name)-1, (info), NULL}
#define F1(name, info) \
    {name, sizeof(name)-1, (MAY_BE_RC1 | (info)), NULL}
#define FN(name, info) \
    {name, sizeof(name)-1, (MAY_BE_RC1 | MAY_BE_RCN | (info)), NULL}
#define FC(name, callback) \
    {name, sizeof(name)-1, 0, callback}

僅僅是設(shè)置了不同的type maskF1設(shè)置了MAY_BE_RC1FN設(shè)置了MAY_BE_RCN | MAY_BE_RC1

依然一頭霧水,但是通過(guò)目錄名,我依稀能猜出這跟性能優(yōu)化有關(guān),跟JIT有關(guān)系。我決定繼續(xù)追查下去,看看這些初始化后的結(jié)構(gòu)體在哪里使用過(guò)。

我們很清楚,設(shè)置位信息用|,那判斷有沒(méi)有設(shè)置肯定用&,全局搜索& MAY_BE_RCN,再看看哪些代碼跟優(yōu)化有關(guān),定位到了如下代碼,在zend_jit.c的530行:

#ifdef ZEND_JIT_USE_RC_INFERENCE
    /* Refcount may be increased by RETURN opcode */
    if ((info & MAY_BE_RC1) && !(info & MAY_BE_RCN)) {
for (j = 0; j < ssa->cfg.blocks_count; j++) {
    if ((ssa->cfg.blocks[j].flags & ZEND_BB_REACHABLE) &&
ssa->cfg.blocks[j].len > 0) {
const zend_op *opline = op_array->opcodes + ssa->cfg.blocks[j].start + ssa->cfg.blocks[j].len - 1;

if (opline->opcode == ZEND_RETURN) {
    if (opline->op1_type == IS_CV && opline->op1.var == EX_NUM_TO_VAR(var)) {
info |= MAY_BE_RCN;
break;
    }
}
    }
}
    }
#endif

如果返回值的引用計(jì)數(shù)是1,而不是N的時(shí)候,并且開(kāi)啟了返回值引用計(jì)數(shù)推導(dǎo)功能,就走這段代碼。這段代碼又涉及到所謂SSA,靜態(tài)單賦值的編譯器設(shè)計(jì)方式。

在編譯器設(shè)計(jì)中,靜態(tài)單一賦值形式(通常縮寫(xiě)為SSA形式或簡(jiǎn)稱SSA)是中間表示(IR)的屬性,它要求每個(gè)變量只分配一次,并且每個(gè)變量在使用之前定義。原始IR中的現(xiàn)有變量被拆分為版本,在教科書(shū)中,新變量通常由原始名稱用下標(biāo)表示,以便每次定義都有自己的版本。在SSA形式中,use-def鏈?zhǔn)秋@式的,每個(gè)包含一個(gè)元素。

所以上面的代碼就是判斷SSA的cfg(control flow graph控制流圖)的塊是不是可達(dá)的,如果可達(dá),執(zhí)行條件中的代碼。

還是不太通透,雖然能推斷出設(shè)置refcount跟優(yōu)化有關(guān),跟靜態(tài)單一賦值有關(guān),但在寫(xiě)擴(kuò)展的時(shí)候,什么時(shí)候該用@refcount 1,還是不太清楚。

 總結(jié)

到此這篇關(guān)于php源碼中refcount疑問(wèn)的文章就介紹到這了,更多相關(guān)php源碼中refcount內(nèi)容請(qǐng)搜索以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持!

標(biāo)簽: PHP
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
日本欧美在线| 91综合视频| 激情六月综合| 国产乱码午夜在线视频| 精品视频一区二区三区四区五区| 国产精品videossex久久发布| 国产精区一区二区| 奇米色欧美一区二区三区| 久久久久午夜电影| 亚洲精品2区| 亚洲综合色婷婷在线观看| 中文字幕日韩高清在线| 日韩精品欧美精品| 国产精品久久久一区二区| 国产视频一区二| 精品欧美视频| 香蕉成人av| 香蕉久久精品| 国产精品女主播一区二区三区| 蜜臀久久久99精品久久久久久| 亚洲天堂日韩在线| 国产精品一站二站| 美女精品视频在线| 国产在线|日韩| 国产精品视区| 日韩av中文在线观看| 久久这里只有| 中文在线资源| 欧美午夜不卡影院在线观看完整版免费| 亚洲免费中文| 国产情侣一区| 日韩精品中文字幕第1页| 国产精品a久久久久| 中文在线资源| 国产精品美女久久久浪潮软件| 亚洲va久久久噜噜噜久久| 国产精品久久| 亚洲黄色免费av| 99pao成人国产永久免费视频| 日韩中文字幕| 丁香婷婷久久| 日韩视频在线一区二区三区| 日本精品在线播放| 精品视频一区二区三区在线观看| 神马午夜久久| 亚洲18在线| 国产91欧美| 亚洲制服少妇| 精品久久久久久久| 在线亚洲免费| 国产精品国码视频| 久久国产免费| 在线一区二区三区视频| 久久精品一区二区国产| 九色精品91| 国产精品白丝一区二区三区| 激情欧美丁香| 国产精品激情| 亚洲综合电影一区二区三区| 麻豆一区二区三| 老鸭窝毛片一区二区三区| 久久精品一本| 日韩中文字幕麻豆| 国产第一亚洲| 日韩精品社区| 国产一在线精品一区在线观看| 日韩精品电影一区亚洲| 国产成人久久精品一区二区三区| 欧美在线综合| 日韩不卡一区| 日韩在线视频一区二区三区| zzzwww在线看片免费| 日韩精品免费观看视频| 91看片一区| 国产日韩欧美一区| 国产精品亚洲成在人线| 最新亚洲激情| 超碰成人av| 人人爱人人干婷婷丁香亚洲| 91久久亚洲| 国产精选在线| 国产精品一级| 在线一区视频| 亚洲一级少妇| 麻豆国产一区| 午夜久久av| 欧美另类专区| 播放一区二区| 国产成人精品一区二区免费看京 | 国产伦精品一区二区三区在线播放| 图片区亚洲欧美小说区| 国产欧美欧美| 中文字幕中文字幕精品| 日韩高清成人| 精品久久视频| 欧美在线91| 蜜臀av一区二区在线免费观看| 日韩中文在线电影| 久久中文字幕一区二区| 欧美日韩黄网站| 亚洲人成在线影院| 狠狠爱成人网| 亚洲高清影视| 亚洲天堂久久| 精品日韩视频| 色综合五月天| 久久99蜜桃| 国产区精品区| 久久国产婷婷国产香蕉| 亚州av一区| 在线观看视频免费一区二区三区| 五月天综合网站| 999久久久亚洲| 日本蜜桃在线观看视频| 国产aa精品| 国产成人免费| 91视频久久| 麻豆国产在线| sm久久捆绑调教精品一区| 国产伊人久久| 三上亚洲一区二区| 国产一区二区三区探花| 欧美黄色精品| 国产精品15p| 久久中文在线| 国产va免费精品观看精品视频| 久久亚洲资源中文字| 麻豆一区二区99久久久久| 国产精品流白浆在线观看| 美女精品视频在线| 国产一区二区亚洲| 日韩精品第一区| 99国产精品一区二区| 久久精品国产68国产精品亚洲| 99成人超碰| 亚洲免费黄色| 视频一区二区三区中文字幕| 中文字幕免费一区二区| 久久精品99国产精品日本| 欧美激情福利| 婷婷综合一区| 国产精品一在线观看| 精品黄色一级片| 91麻豆国产自产在线观看亚洲| 日韩欧美一区免费| 免费观看久久av| 国产videos久久| 国产麻豆久久| 国产美女精品| 日韩国产成人精品| 久久久国产精品入口麻豆| 国产精品毛片久久| 一区二区小说| 亚洲人成高清| 国产乱论精品| 亚洲黄色网址| 国产精品日韩| 久久激情av| 日韩国产在线| 亚洲综合日本| 欧美精品成人| 日韩成人综合| 亚洲在线成人| 国产精品一区高清| 日韩欧美一区二区三区在线视频| 亚洲大片在线| 日韩精品一区第一页| 欧美色综合网| 亚洲精品在线影院| 男人的天堂亚洲一区| 国产毛片精品| 91精品久久久久久久久久不卡| 美女精品在线| 美女精品视频在线| 黄色成人在线网址| 国产精品入口久久| 亚洲福利国产| 69堂精品视频在线播放| 波多野结衣久久精品| 热久久国产精品| 成人在线免费观看网站| 亚洲电影在线一区二区三区| 国产欧美一区二区三区米奇| 88xx成人免费观看视频库| 亚洲精品美女| 精品少妇一区| 午夜在线精品| 国产一区二区精品久| 六月婷婷一区| 日韩1区2区| 亚洲免费资源| 国产精品精品国产一区二区| 男女男精品网站| 激情久久一区二区| 亚洲欧洲专区| 久久国产亚洲精品| 欧美一区精品| 日韩视频中文| 夜夜嗨网站十八久久| 高潮久久久久久久久久久久久久|