聊一聊关于php源码中refcount的疑问
发布时间:2023-02-16 12:47:31 所属栏目:PHP 来源:互联网
导读:这篇文章主要给大家介绍了关于对php源码中refcount的相关疑问,文中通过实例代码介绍的非常详细,对大家的学习或工作具有一定的参考学习价值,需要的朋友可以参考下 在浏览PHP源码的时候,在众多的*.stub.php中,发现了这样的注释,@refcount 1。 通过翻看build
这篇文章主要给大家介绍了关于对php源码中refcount的相关疑问,文中通过实例代码介绍的非常详细,对大家的学习或工作具有一定的参考学习价值,需要的朋友可以参考下 在浏览PHP源码的时候,在众多的*.stub.php中,发现了这样的注释,@refcount 1。 通过翻看build/gen_stub.php源码,发现了在解析*.stub.php文件时,关于返回信息的代码。 <?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,也就是标量(基本数据类型,整型、浮点型、字符串等),那么refcount指定为0,否则为N。如果设置了注释,那么以注释为最高优先级。 以函数ob_list_handlers为例: /** * @return array<int, string> * @refcount 1 */ function ob_list_handlers(): array {} 返回值是array,所以默认的refcount应该是N,但由于设置了注释@refcount 1,所以返回值的引用计数被替换成1。 这些逻辑我能看懂,但设置返回值引用计数的目的是什么?我还是一头雾水 我接着往下排查,发现通过返回值的引用计数,在生成func_info的时候,会有些不同。如果返回值引用计数为1或N,则会用对应的宏去初始化func_info结构体。如果是0,则不进入初始化列表。 以上的代码逻辑依然可以在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"; } 获取函数原型的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), (编辑:莱芜站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |