Erlang 虚拟机 BEAM 指令集之内存管理相关的指令
翻看 BEAM 虚拟机指令集的时候(在编译器源码目录下:lib/compiler/src/genop.tab),会发现有一些和内存分配/解除分配相关的指令,如下所示:
- allocate StackNeed Live
- allocate_heap StackNeed HeapNeed Live
- allocate_zero StackNeed Live
- allocate_heap_zero StackNeed HeapNeed Live
- test_heap HeapNeed Live
- init N
- deallocate N
上述列表中粗体是指令本身,后面跟着的是参数。粗看上去又是 allocate 又是 heap,好像 beam 在虚拟机指令就要处理内存管理。其实不是的。仔细看一下,每一条带 allocate 的指令后面都有一个 StackNeed 参数,原来 BEAM 虚拟机中所谓的内存分配都跟栈有关。我们先看一下Erlang进程里面堆和栈的关系:
堆和栈其实都在统一管理的堆里面,堆从低地址开始向上增长,栈从高地址开始向下增长。栈顶和堆顶碰到了就说明堆的空间不够用了。堆用于保存 Erlang 对象。和 C 语言一样,BEAM 的函数调用也会在栈里面设置栈帧,其中包括函数返回地址以及函数在求值过程中使用的临时数据。栈里面保存的只能是 Eterm,即要么是简单对象,要么是引用对象。对立面保存的是 Eterm 或对象本身。
下面以 allocate StackNeed Live 为例阐述。这条指令说明要在栈上分配 StackNeed 字的空间。那么这条指令后面的 Live 是什么意思呢?在 http://erlangonxen.org/more/beam#model 有一句解释
'Live' refers to the current number of registers that hold values still needed by the process.
表示当前进程所需的寄存器数?看了下面这个图就明白了:
除了堆栈之外,还有寄存器区域。堆栈是进程私有的数据结构,而寄存器组则是虚拟机(调度器)里面的共享数据。当虚拟机调度运行某个进程的时候,这个进程具有对寄存器组的完全访问权。但是当进程被调出的时候,寄存器组就归别人使用了(和 x86 机器不同,保存进程上下文的时候不保存寄存器信息,所以 Erlang 进程切换效率很高)。
上面的 Live 就是图中显示的 live 区域,也就是说,当前这个进程正在使用 live 个寄存器。那为什么分配栈内存的时候需要传入 live 参数呢?而且为什么前面几条分配指令都需要 live 参数呢?这是因为前面几条指令涉及到栈分配(前4条)和堆检查,这些操作都有可能会涉及到垃圾回收(假设分配了栈内存之后栈顶会碰到堆顶),而 Erlang 的垃圾回收需要扫描引用树,所以需要一个扫描的起点,即 rootset。那么根据上面图中对象之间的引用关系,栈中所有的项式和 live 个寄存器的项式都需要加入到 rootset 中。这就是这些和栈分配相关的指令都需要 live 参数的原因。
有了以上基础之后就好理解这些指令了。这些指令的意义总结如下:
- allocate StackNeed Live:将栈底指针向下挪 StackNeed+1 个字,多出的那个字保存CP(continuation pointer,即函数的返回地址)
- allocate_heap StackNeed HeapNeed Live:向栈底指针向下挪 StackNeed+1 个字(+1原因同上),还要保证堆中剩余 HeapNeed 个字的空闲空间
- allocate_zero StackNeed Live:同 allocate,但是新分配的栈空间填零(NIL)
- allocate_heap_zero StackNeed HeapNeed Live:allocate_heap和allocate_zero的合体
- test_heap HeapNeed Live:检查对空闲空间是否有 HeapNeed 个字,如不满足要垃圾回收。以上指令都有可能垃圾回收
- init N:栈中第 N 个字清零(NIL)
- deallocate N:将栈底指针向上挪 N+1 个字(释放栈)
Erlang 虚拟机 BEAM 指令集之内存管理相关的指令的更多相关文章
- 学习android内核 -- 内存管理相关
Android内存管理: 1.当应用程序关闭以后,后台对应的进程并没有真正的退出(处于休眠状态,一般不占用系统CPU的资源),这是为了下次再启动的时候能快速启动. 2.当系统内存不够时,AmS会主动根 ...
- node 内存管理相关
为什么在node中要担心node内存管理 使用JavaScript进行前端开发时几乎完全不需要关心内存管理问题,对于前端编程来说,V8限制的内存几乎不会出现用完的情况,v8在node中有着内存的限制( ...
- C内存管理相关内容--取自高质量C++&C编程指南
1.内存分配方式 内存分配方式有三种: (1)从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量. (2) 在栈上创建.在执行函数 ...
- heap corruption detected错误解决方法调试方法以及内存管理相关
1.heap corruption detected http://vopit.blog.51cto.com/2400931/645980 heap corruption detected:aft ...
- davlik虚拟机内存管理之一——内存分配
转载自http://www.miui.com/thread-74715-1-1.html dalvik虚拟机是Google在Android平台上的Java虚拟机的实现,内存管理是dalvik虚拟机中的 ...
- xcode 手动管理内存 的相关知识点总结
一.XCode4.2以后支持自动释放内存ARC xcode自4.2以后就支持自动释放内存了,但有时我们还是想手动管理内存,这如何处理呢. 很简单,想要取消自动释放,只要在 Build Setting ...
- JVM内存管理------JAVA语言的内存管理概述
引言 内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑.不过世界上不存在十全十美的好事,在带来了便利的同时,也因此引入了很多令人抓 ...
- JVM内存管理之JAVA语言的内存管理概述
引言 内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑.不过世界上不存在十全十美的好事,在带来了便利的同时,也因此引入了很多令人抓 ...
- Linux堆内存管理深入分析(上)
Linux堆内存管理深入分析(上半部) 作者:走位@阿里聚安全 0 前言 近年来,漏洞挖掘越来越火,各种漏洞挖掘.利用的分析文章层出不穷.从大方向来看,主要有基于栈溢出的漏洞利用和基于堆溢出的漏洞 ...
随机推荐
- #敏捷个人资料# 免费下载 《敏捷个人-认识自我,管理自我 v0.8.pdf》
快乐.高效.平衡,做一个爱学习.有目标.懂生活的影响者. 从今天开始至7月31日,点击http://t.cn/Rv3koHU 免费收到 1000多页的 <敏捷个人-认识自我,管理自我 v0.8. ...
- BABOK2主要概要输入输出图
- 将form表单元素转为实体对象 或集合 -ASP.NET C#
简介: 做WEBFROM开发的同学都知道后台接收参数非常麻烦 虽然MVC中可以将表单直接转为集实,但不支持表单转为 LIST<T>这种集合 单个对象的用法: 表单: <input n ...
- QCustomplot使用分享(三) 图
一.可以实现的图 相对于其他绘制图表的第三方库来说,QCustomPlot算是比较轻量的,不仅仅能实现功能,而且二次开发比较容易.下面我们来具体说下他可以实现那些图 QCPGraph:折线图,Line ...
- [ASP.NET]分析MVC5源码,并实现一个ASP.MVC
本节内容不是MVC入门教程,主要讲MVC原理,实现一个和ASP.NET MVC类似基本原理的项目. MVC原理是依赖于ASP.NET管道事件基础之上的.对于这块,可阅读上节内容 [ASP.NET]谈谈 ...
- struts.xml中出现Package struts2 extends undefined package struts-default解决办法
在struts.xml中出现extends undefined package struts-default,经过查阅资料原来是因为没有联网的缘故.这样解决:在myeclipse中关联本地的dtd文件 ...
- Sql Server来龙去脉系列之三 查询过程跟踪
我们在读写数据库文件时,当文件被读.写或者出现错误时,这些过程活动都会触发一些运行时事件.从一个用户角度来看,有些时候会关注这些事件,特别是我们调试.审核.服务维护.例如,当数据库错误出现.列数据被更 ...
- ActiveReports 报表应用教程 (3)---图表报表
ActiveReports 的图表控件支持绝大多数常用的二维和三维图表类型,包括XY图表和财务图表.通过使用图表控件的定制功能,如修改坐标轴.图注.图例等,用户可以创建任何其所需要的图表效果.用户还可 ...
- android 学习资料
Fragment 事件分发机制 事件分发机制2 NDK JNI ndk { moduleName "mymodule" ldLibs "log" stl &qu ...
- 程序设计模式 —— State 状态模式
我应该如何阅读? 本文将使用优雅的文字风格来告诉你什么是状态模式. 注意: 1.在阅读本文之前请保证你已经掌控了 面对对象的思想与 多态的基本概念,否则将难以理解. 2.本文实现将用C++实现,你不一 ...