ghc 的 FUN_1_0、FUN_0_1 等闭包类型是什么意思?
What do ghc's FUN_1_0, FUN_0_1, etc closure types mean?
FUN_1_0
、THUNK_1_0
等闭包类型经常出现在堆配置文件中,但没有在任何地方记录。 ghc-heap
中未记录的类型对应于 these constants, and there are some further clues in Layout.hs
但仍然不清楚这些是什么意思。
This answer 建议 FUN_1_0
和 FUN_2_0
对应于一个或两个参数的函数,但这似乎是错误的(因为没有 FUN_3_0
例如)
各种 FUN_
和 THUNK_
类型是什么意思?
变体 FUN_m_n
和 THUNK_m_n
只是 FUN
和 THUNK
的特例,旨在加速垃圾收集。 (CONSTR
也有一组类似的 CONSTR_m_n
特例。)
一个FUN
堆对象是一个函数闭包。 THUNK
堆对象是表达式的暂停计算。两种类型的对象都可能包含 payload 的几个 word-sized 字段,为函数体或 thunk 表达式中的任何自由变量提供封闭值。 CONSTR
表示饱和构造函数,其有效负载包括其字段的值。 Making a Fast Curry 论文对此有一些有用的背景。
在任何这些闭包类型的有效负载中,其中一些字段可能是指针(指向装箱的值),有些可能是 non-pointers(未装箱的值直接出现在闭包中)。垃圾收集器在遍历堆时,需要跟随指针,忽略non-pointers。对于所有 FUN
s、THUNK
s 和 CONSTR
s(无论是特殊情况 _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,它会退回到一般的 FUN
或 THUNK
位图方案。您可以在 rts/sm/Scav.c
函数 scavenge_block
中看到该算法的工作原理,它是实际以不同方式处理变体的少数代码之一。
FUN_1_0
、THUNK_1_0
等闭包类型经常出现在堆配置文件中,但没有在任何地方记录。 ghc-heap
中未记录的类型对应于 these constants, and there are some further clues in Layout.hs
但仍然不清楚这些是什么意思。
This answer 建议 FUN_1_0
和 FUN_2_0
对应于一个或两个参数的函数,但这似乎是错误的(因为没有 FUN_3_0
例如)
各种 FUN_
和 THUNK_
类型是什么意思?
变体 FUN_m_n
和 THUNK_m_n
只是 FUN
和 THUNK
的特例,旨在加速垃圾收集。 (CONSTR
也有一组类似的 CONSTR_m_n
特例。)
一个FUN
堆对象是一个函数闭包。 THUNK
堆对象是表达式的暂停计算。两种类型的对象都可能包含 payload 的几个 word-sized 字段,为函数体或 thunk 表达式中的任何自由变量提供封闭值。 CONSTR
表示饱和构造函数,其有效负载包括其字段的值。 Making a Fast Curry 论文对此有一些有用的背景。
在任何这些闭包类型的有效负载中,其中一些字段可能是指针(指向装箱的值),有些可能是 non-pointers(未装箱的值直接出现在闭包中)。垃圾收集器在遍历堆时,需要跟随指针,忽略non-pointers。对于所有 FUN
s、THUNK
s 和 CONSTR
s(无论是特殊情况 _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,它会退回到一般的 FUN
或 THUNK
位图方案。您可以在 rts/sm/Scav.c
函数 scavenge_block
中看到该算法的工作原理,它是实际以不同方式处理变体的少数代码之一。