Skip to content

Activation Records

:material-circle-edit-outline: 约 465 个字 :material-clock-time-two-outline: 预计阅读时间 2 分钟

函数被调用是就会产生一个对应的 activation,活跃的 activation 对应一个 activation record (sometimes called a frame),位于 control stack

Stack Frames

栈由高地址向低地址增长

sp 寄存器存栈顶地址,fp 指向 caller 帧头

image-20250407103100580

image-20250407105020967

  • 寄存器存:
    • 部分函数参数
    • 返回地址
    • 函数返回值
    • 部分本地变量
  • 栈存:
    • 额外的函数参数
    • 体积过大的变量
    • 通过引用传的变量,或者这个变量有被取地址
    • 有些语言允许函数内定义函数,内部函数访问外部函数参数时得存栈上
    • 数组

嵌套函数变量访问问题

对于嵌套函数,内部函数可能需要访问外部函数的变量,即访问外部函数的栈帧

有三个解决方案

如果 f 是 g 内部的嵌套函数,那么调用 f 时需要把 g 最近一次的 activation record 的地址传递给 f 作为 Static Links,也就是说 Static Links 是一个指向外部函数栈帧的指针

如此内部函数就能通过 Static Links 访问外部函数栈帧

image-20250407142651646

Display

给每一个函数标记静态嵌套深度,然后设置一个全局数组 Display,以嵌套深度为 index 存储该深度函数的最近一次调用的栈帧地址

Lambda Lifting

编译时直接看调用的函数会用到哪些外部变量,直接当参数传进去

Higher-Order Functions

我们之前讨论的都是基于栈帧的存储方法,使用栈帧有个要求是:函数退出后需要释放其内部的所有信息(包括内部函数的栈帧)

但是这样就不支持高阶函数了,高阶函数将函数作为返回值

image-20250407144234836

调用 f(3) 后,传入的 3 不应该被销毁