ghc 的 FUN_1_0、FUN_0_1 等闭包类型是什么意思?

What do ghc's FUN_1_0, FUN_0_1, etc closure types mean?

FUN_1_0THUNK_1_0 等闭包类型经常出现在堆配置文件中,但没有在任何地方记录。 ghc-heap 中未记录的类型对应于 these constants, and there are some further clues in Layout.hs 但仍然不清楚这些是什么意思。

This answer 建议 FUN_1_0FUN_2_0 对应于一个或两个参数的函数,但这似乎是错误的(因为没有 FUN_3_0 例如)

各种 FUN_THUNK_ 类型是什么意思?

变体 FUN_m_nTHUNK_m_n 只是 FUNTHUNK 的特例,旨在加速垃圾收集。 (CONSTR 也有一组类似的 CONSTR_m_n 特例。)

一个FUN堆对象是一个函数闭包。 THUNK 堆对象是表达式的暂停计算。两种类型的对象都可能包含 payload 的几个 word-sized 字段,为函数体或 thunk 表达式中的任何自由变量提供封闭值。 CONSTR 表示饱和构造函数,其有效负载包括其字段的值。 Making a Fast Curry 论文对此有一些有用的背景。

在任何这些闭包类型的有效负载中,其中一些字段可能是指针(指向装箱的值),有些可能是 non-pointers(未装箱的值直接出现在闭包中)。垃圾收集器在遍历堆时,需要跟随指针,忽略non-pointers。对于所有 FUNs、THUNKs 和 CONSTRs(无论是特殊情况 _m_n 类型还是一般情况),它们的信息 tables 都有一个位图指定有效载荷中有多少字段以及哪些字段包含指针。但是,垃圾收集器重定向到信息 table 并处理位图是有代价的。

为了加速垃圾收集,一些特殊情况定义了不同的闭包类型,如FUN_m_n等,其中m是指针字段的数量,n 是 non-pointer 字段的数量。对于变体 _0_1_1_0_2_0_0_2,垃圾收集器可以立即确定字段总数和所有字段都是指针的事实(等等应遵循)或 non-pointers(因此应跳过),而不重定向到信息 table 位图。对于 _1_1 变体,存在歧义,因为不清楚指针和 non-pointer 出现在有效负载中的顺序,因此选择了指针-然后-non-pointer 的顺序。如果闭包有一个 non-pointer-then-pointer,它会退回到一般的 FUNTHUNK 位图方案。您可以在 rts/sm/Scav.c 函数 scavenge_block 中看到该算法的工作原理,它是实际以不同方式处理变体的少数代码之一。