Skip to content

Latest commit

 

History

History
143 lines (117 loc) · 6.54 KB

001-ETerm.md

File metadata and controls

143 lines (117 loc) · 6.54 KB

#

ETerm

Erts做为Erlang的执行时环境最重要的一件事情就是执行BEAM的OP代码。所有的代码都无法排除两个东西函数和数据,换句话说就是BIF和ETerm。

##内存编程模型

不同模型下的指针和int的区别	
默认编译器倾向LP32,LP64
Type	   ILP64   LP64   LLP64
int 	   64      32      32
long 	   64      64      32
pointer    64      64      64
long long  64      64      64

在不同的编译器上和不同的内存模型上指针和int的长度是不一定相同。Erts在编译的时候会通过多种探测手段确认编译器所使用的内存模型。

##内存分配模型 在x86或ARM处理器中,基本C数据类型通常并不存储于内存中的随机字节地址。 实际情况是,除char外,所有其他类型都有“对齐要求”: char可起始于任意字节地址,2字节的short必须从偶数字节地址开始,4字节的int或flot必须从能被4整除的地址开始,8字节的long和double必须从能被8整除的地址开始。无论signed(有符号)还是unsigned(无符号)都不受影响。x86和ARM上的基本C类型是“自对齐(self-aligned)”的。 关于指针,无论32位(4字节)还是64位(8字节)也都是自对齐的。简单的说就是内存分配的指针一定是偶数。

##ETerm ETerm是一个和指针的等长的无符号整数。它采用这个整数的二进制最后2位作为标签(tag)。 ETerm的标签主要有(掩码长度为2位,掩码0x3):

0x0 标签头 0x1 链表 0x2 装箱数据 0x3 立即数

标签头的Eterm表示
+---------------------------------------------------------------+
|      标签头                                                 0|0|
+---------------------------------------------------------------+
链表的Eterm表示
+---------------------------------------------------------------+
|      指针二进制表示除去最后2位                                 0|1|
+---------------------------------------------------------------+
装箱数据的Eterm表示
+---------------------------------------------------------------+
|      指针二进制表示除去最后2位                                 1|0|
+---------------------------------------------------------------+
立即数表示
+---------------------------------------------------------------+
|      立即数                                                 1|1|
+---------------------------------------------------------------+

这里面链表和装箱数据能正常用Eterm能正常表示和内存分配模型是非常相关的。在32bit上指针是以4字节对齐的,所以要能保证被4整除,所以在二进制表示下任何指针的最后两位一定是00。

###ETerm的立即数 ETerm将立即数又进一步的进行了分类,分为IMMD1和IMMD2这两类

IMMD1的标签有(掩码长度为4位,掩码0xF):

0x3 内部PID 0x7 内部Port 0xF 小整数 0xB IMMD2

PID的Eterm表示
+---------------------------------------------------------------+
|     PID                                                0|0|1|1|
+---------------------------------------------------------------+
Port的Eterm表示
+---------------------------------------------------------------+
|     Port                                               0|1|1|1|
+---------------------------------------------------------------+
小整数的Eterm表示
+---------------------------------------------------------------+
|     小整数                                              1|1|1|1|
+---------------------------------------------------------------+
IMMD2的Eterm表示
+---------------------------------------------------------------+
|     IMMD2                                              1|0|1|1|
+---------------------------------------------------------------+

IMMD2的标签有(掩码长度为6位,掩码0x3F):

0xB ATOM 0x1B catch 0x3B NIL

ATOM的Eterm表示
+---------------------------------------------------------------+
|     ATOM                                           0|0|1|0|1|1|
+---------------------------------------------------------------+
catch的Eterm表示
+---------------------------------------------------------------+
|     catch                                          0|1|1|0|1|1|
+---------------------------------------------------------------+
NIL的Eterm表示
+---------------------------------------------------------------+
|     小整数                                          1|1|1|0|1|1|
+---------------------------------------------------------------+

###ETerm的装箱数据和标签头

装箱数据单独使用是没有意义的,需要和标签头一起使用才具有意义。装箱数据的内容是一个指针这样完全和链表是重复的,但是意义不同的是装箱数据的指针指向的是一个标签头。而标签头又分成3部分,大小(24bit),标签(4bit),主标签(2bit,总为00),在一个标签头后面连续跟着n个ETerm。

+---------------------------------------------------------------+
|      指针二进制表示除去最后2位                                 1|0|
+---------------------------------------------------------------+
						   |
					      \|/            
+---------------------------------------------------------------+
|      n                                            |x|x|x|x|0|0|
+---------------------------------------------------------------+
+---------------------------------------------------------------+
|      ETerm 1                                                  |
+---------------------------------------------------------------+
                          .........
                          .........
+---------------------------------------------------------------+
|      ETerm n                                                  |
+---------------------------------------------------------------+

标签头的标签有(掩码长度为6位,掩码0x3F):

0x0 元组 0x4 Binary聚合 0x8 正大整数 0xC 负大整数 0x10 函数或Things 0x18 浮点数 0x1C 导出(export) 0x20 REFC_BINARY(暂时不知道是什么) 0x24 HEAP_BINARY或BINARIES(暂时不知道是什么) 0x28 SUB_BINARY(暂时不知道是什么) 0x2C 没有使用 0x30 外部PID 0x34 外部Port或Things 0x38 外部的Ref 0x3C MAP类型(R17引入)

其中0x10和0x34当标签头大小部分全部为0的时候分别表示函数和外部Port,当不为0的时候表示Erlang的Things。

参考文件 emulator/beam/sys.h emulator/beam/erl_term.h