当我在erlang中创建一个列表时,例如在erlang shell中:
1> [1, 2].
根据我的理解,在vm中,此列表将表示为单链表。
这个结构是如何由erlang运行时创建的?例如,它构造的是这样的:
我认为以下c和erlang代码是完成大部分工作的地方吗?
erl_term.h
包含一个宏make_list
,但我还没有找到实现...
答案 0 :(得分:4)
Erlang VM实现BEAM使用的技术可以追溯到60年代或70年代初的第一个Lisp实现。它有时被称为标记或类型指针。 (Tags)此技术不存储目标对象中的目标类型(在本例中列出CONS),而是指针本身或在通常为指针的位置保存标量值。它允许保存相当多的内存,特别是在动态类型语言中,如LISP或Erlang。 (过去当内存非常昂贵并且当CPU变得比内存快得多并且缓存未命中/命中决定了算法的速度时再次变得重要时,这很有趣。)作为一个缺点,它也会导致一些混乱的代码。处理列表构建的整个部分从line 216 of erl_term.h开始。你可以注意到有宏
#define _unchecked_make_list(x) ((Uint) COMPRESS_POINTER(x) + TAG_PRIMARY_LIST)
这是你正在寻找的宏。这是你的make_list
。这条线
_ET_DECLARE_CHECKED(Eterm,make_list,const Eterm*)
在使用ET_DEBUG
进行编译时,会对其进行检查。 (请参阅more details。)宏make_list
#define make_list(x) _ET_APPLY(make_list,(x))
只会调用已检查或未经检查版本的make_list
。真正构建列表的宏是
#define CONS(hp, car, cdr) \
(CAR(hp)=(car), CDR(hp)=(cdr), make_list(hp))
#define CAR(x) ((x)[0])
#define CDR(x) ((x)[1])
列表单元格结构只是堆上的两个连续Uint
值(hp
),其地址是压缩和标记(参见{ {1}})。我希望这个描述可以帮助你。