参考了 Java 中的对象模型 我决定把 XSharp 中的 数组(Array) 的模型设计为以下形式: [ 8 bytes ] object header as length of array [ 4 or 8 bytes ] pointer p to a sequential memory (for elements)
故对以下 XSharp 代码
1 | i64[] a = new i64[100] |
在 64 位系统上,我们将会在栈上分配 8 + 4 字节的内存,由于 align 的要求我们再加上 4 字节的 padding, 一共 16 字节,并为 100 个 i64 元素在堆上分配 100 * 8 字节的内存
而每次执行a[i]
这样的操作时,我们会对取 a 的地址 并加上 8,得到指向对应连续内存的指针 p , 再对 p + i _ sizeof(i64) 对应的地址指向读/写操作
对应到 LLVM 的 CodeGen,我们则需要定义形如StructType<i64,PointerTo<xxx>>
这样的类型, 并用getelementptr inbound和getelementptr指令获得某个元素的地址
这样设计的好处则是将长度 length 放到栈上,不需要在堆分配和取元素时进行额外的计算, 也不需要 align 来保证 cache friendly,同时也方便优化。
而相较于 C 语言风格的数组,我们的数组主体始终放在堆上,故内存的管理不够精细, 但经过了封装,其易用性更胜一筹,基于这些限制,其优化也更容易实现。