加入收藏 | 设为首页 | 会员中心 | 我要投稿 莱芜站长网 (https://www.0634zz.com/)- 云连接、建站、智能边缘云、设备管理、大数据!
当前位置: 首页 > 编程开发 > PHP > 正文

聊一聊关于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),

(编辑:莱芜站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读