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(理想情况下是编译时引用计数,但运行时现在也可以开始了)
我如何开始实现这样一个算法。我已经搜索了关于这个主题的每一篇论文,但没有找到算法。以下规则应该适用于您的语言
- 增加正在分配引用的变量的引用计数
- 减少变量的引用计数,该变量的引用以前位于分配给的变量中(如果该变量不为null)
- 如果您的语言允许在数据结构中使用对变量类型的引用,“静态”变量等等,那么关于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
}