Memory management 如何在编译时实现引用计数器?

Memory management 如何在编译时实现引用计数器?,memory-management,garbage-collection,compiler-construction,static-analysis,reference-counting,Memory Management,Garbage Collection,Compiler Construction,Static Analysis,Reference Counting,下面是一组组合的函数调用(我试图使其复杂化,但可能很容易) 您通常如何计算变量的活跃度,以及在何处插入引用计数指令 这是我的尝试 从顶部功能开始main。它从两个参数开始。假设没有发生复制。它将实际的可变值传递给do\u foo 然后我们有x。X拥有a和b。然后我们看到yy设置为x,因此将上一个x链接到此x。通过r,我们再也看不到x,所以也许它可以被释放。。。。从do_bar本身来看,我们基本上知道p和q不能在此范围内进行垃圾收集 基本上,我不知道如何开始实现一个算法来实现ARC(理想情况下是编

下面是一组组合的函数调用(我试图使其复杂化,但可能很容易)

您通常如何计算变量的活跃度,以及在何处插入引用计数指令

这是我的尝试

从顶部功能开始
main
。它从两个参数开始。假设没有发生复制。它将实际的可变值传递给
do\u foo

然后我们有
x
。X拥有a和b。然后我们看到
y
y
设置为
x
,因此将上一个x链接到此
x
。通过
r
,我们再也看不到
x
,所以也许它可以被释放。。。。从
do_bar
本身来看,我们基本上知道
p
q
不能在此范围内进行垃圾收集

基本上,我不知道如何开始实现一个算法来实现ARC(理想情况下是编译时引用计数,但运行时现在也可以开始了)


我如何开始实现这样一个算法。我已经搜索了关于这个主题的每一篇论文,但没有找到算法。

以下规则应该适用于您的语言

  • 声明变量时,增加其refcount
  • 当变量超出范围时,减少其refcount
  • 将变量引用指定给变量时,调整变量的引用计数:
    • 增加正在分配引用的变量的引用计数
    • 减少变量的引用计数,该变量的引用以前位于分配给的变量中(如果该变量不为null)
  • 当包含对变量的非空引用的变量超出范围时,请减少其引用的变量的refcount
  • 注:

    • 如果您的语言允许在数据结构中使用对变量类型的引用,“静态”变量等等,那么关于ve的规则需要扩展。。。以明显的方式
    • 优化编译器可能能够消除某些refcount增量和减量

    编译时引用计数:

  • 真的没有这样的事。引用计数在运行时完成。在编译时这样做没有意义
  • 您可能正在讨论分析代码以确定运行时引用计数是否可以优化或完全消除。
    • 我在上面提到了前者。这实际上是一种窥视孔优化
    • 后者需要检查对变量的引用是否可以转义;i、 e.变量超出范围后是否可以使用。(试着在谷歌上搜索“转义分析”。这有点类似于编译器可以通过“转义分析”来决定是否可以在堆栈而不是堆中分配对象。)

  • 非常有帮助,谢谢!对我来说,最困难的部分之一是,我如何详细知道“变量何时超出范围”?我提到“编译时引用计数”,因为这里提到了它,您会注意到该页面在短语“编译时引用计数”周围加了引号。我认为这意味着>>they@LancePollard只是不要混淆可达性和范围。一个变量可能比它被声明为关闭的范围更早变得不可访问。
    function main(arg1, arg2) {
      do_foo(arg1, arg2)
    }
    
    function do_foo(a, b) {
      let x = a + b
      let y = x * a
      let z = x * b
      let p = y + z
      let q = x + z
      let r = do_bar(&p)
      let s = do_bar(&q)
    }
    
    function do_bar(&p, &q) {
      *p += 1
      *q += 3
      let r = &p * &q
      let s = &p + &q
      let v = do_baz(&r, &s)
      return &v
    }
    
    function do_baz(&a, &b) {
      return *a + *b
    }
    
    function main(arg1, arg2) {
      let x = do_foo(arg1, arg2)
      free(arg1)
      free(arg2)
      free(x)
    }
    
    function do_foo(a, b) {
      let x = a + b
      let y = x * a
      let z = x * b
      let p = y + z
      free(y)
      let q = x + z
      free(x)
      free(z)
      let r = do_bar(&p)
      let s = do_bar(&q)
      return r + s
    }
    
    function do_bar(&p, &q) {
      *p += 1
      *q += 3
      let r = &p * &q
      let s = &p + &q
      let v = do_baz(&r, &s)
      free(r)
      free(s)
      return &v
    }
    
    function do_baz(&a, &b) {
      return *a + *b
    }