如何由erlang vm构建一个列表?

时间:2015-08-04 18:46:46

标签: erlang

当我在erlang中创建一个列表时,例如在erlang shell中:

1> [1, 2].

根据我的理解,在vm中,此列表将表示为单链表。

这个结构是如何由erlang运行时创建的?例如,它构造的是这样的:

  1. 在内存中创建一个结构来保存一个终止列表的列表
  2. 在内存中创建一个结构来保存项目'2',以及对空列表的引用。
  3. 在内存中创建一个结构来保存项目'1',以及对项目'2'的引用。
  4. 我认为以下c和erlang代码是完成大部分工作的地方吗?

    erl_term.h包含一个宏make_list,但我还没有找到实现...

1 个答案:

答案 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}})。我希望这个描述可以帮助你。