翻译一篇SpiderMonkey GC的文章
前言
这篇文章包含了对SpiderMonkey中Rooted<T>, Handle<T>的解释。
翻译自 https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/GC_Rooting_Guide
原文中GC thing pointer不知如何翻译,故在此引用原文。
下面是原文的翻译。
简介
这篇文章解释了如何与SpiderMonkey GC协同工作。由于SpiderMonkey的自动GC,所以熟练掌握GC中的每一个易错点是至关重要的。而SpiderMonkey中的rooting接口,就是为了简化这些工作的。
什么是GC thing pointer
GC thing是SpiderMonkey中被自动内存管理着的对象,主要包括以下几种:
JS::Value
JSObject*
JSString*
JSScript*
jsid
要注意,虽然JS::Value和jsid不是指针,但它们内部可能包含指向其他对象的指针,所以它们也算是GC thing pointer。
如果你使用了这些对象中的任意一种,那么你就要遵循这篇文章所介绍的规范。如果你不遵守,那么你的程序就可能出错(可能会引用已经被释放的变量)。
栈上的GC thing
JS::Rooted<T>
所有存储在栈上的GC thing *,包括局部变量和函数形参,都必须使用JSRooted<T>来包装。
从程序员角度来说,JS::Rooted<T>对象使用起来就像一个原始指针一样。JS::Rooted<T>构造函数只接受一个JSContext*和一个初始值。
引擎里已经有一些简化书写的typedef:
typedef JS::Rooted<JS::Value> JS:RootedValue;
typedef JS::Rooted<JS::JSObject*> JS:RootedJSObject;
typedef JS::Rooted<JS::JSString*> JS:RootedJSString;
typedef JS::Rooted<JS::JSScript*> JS:RootedJSScript;
typedef JS::Rooted<JS::jsid> JS:RootedId;
例如,你不能这样写:
JSObject* localObj = JS_GetObjectOfSomeSort(cx);
而应该写成这样:
JS::RootedObject localObj(cx, JS_GetObjectOfSomeSort(cx));
有时候你可能会忘记写JSRootedObject这样的形式,但不要担心,SpiderMonkey已经考虑到了这一点,就是下面要介绍的JSHandle<T>。
JS::Handle<T>
所有作为函数形参的GC thing pointer,都必须被包装成JS::Handle<T>的形式。
JS::Handle<T>是JS::Rooted<T>的一种引用形式。你不能手动创建一个JS::Handle<T>,所有的JS::Handle<T>都是由JS::Rooted<T>隐式转换来的。
由于只有JS::Rooted<T>会转换到JS::Handle<T>,而原始指针并不会,这样当你在函数参数里使用了原始指针而不是JS::Rooted<T>的时候,编译器就可以检测出来。
JS::Handle<T>的行为像一个真正的引用一样,不可能改变引用的指向。
同样,JS::Handle<T>也有一些typedef.
下面是错误的做法:
JSObject* someFunction(JSContext *cx, JSObject* obj) {
// ...
}
下面是正确的做法:
JSObject* someFunction(JSContext *cx, JS::HandleObject obj) {
// ...
}
但是,你不能对一个输出参数用JS::Handle<T>,下面描述如何做。
JS::MutableHandle<T>
所有作为输出参数而使用的GC thing pointer,都必须使用JS::MutableHandle<T>。
JS::MutableHandle<T>也是JS::Rooted<T>的一种引用,但是不像JS::Handle<T>,它可能会修改JS::Rooted<T>的内部结构。所有的JS::MutableHandle<T>除了下面2点之外,就和JS::Handle一样:
1.具有一个set(T& t)方法
2.必须从JS:Rooted<T>手动创建。
下面是错误的例子:
bool maybeGetValue(JSContext *cx, JS::Value* valueOut) {
// ...
if (!wasError)
*valueOut = resultValue;
return wasError;
}
void otherFunction(JSContext *cx) {
JS::Value value;
bool success = maybeGetValue(cx, &value);
// ...
}
下面是正确的例子
bool maybeGetValue(JSContext *cx, JS::MutableHandleValue valueOut) {
// ...
if (!wasError)
valueOut.set(resultValue);
return wasError;
}
void otherFunction(JSContext *cx) {
JS::RootedValue value(cx);
bool success = maybeGetValue(cx, &value);
// ...
}
返回值
令人惊讶的是,返回一个原始指针是安全的!但是要注意,一旦得到了一个原始指针,就一定要用JS::Rooted<T>去包装它。
AutoRooters
GC thing pointer在使用前应该尽可能地被JS::Rooted<T>包装。但是有些情况下,不可能使用JS::Rooted<T>或担心使用了JS::Rooted<T>而产生的性能问题,这时可以使用AutoRooter。
typedef JS::Value[] AutoArrayRooter
typedef js::Vector<JS::Value> AutoValueVector
typedef js::Vector<jsid> AutoIdVector
typedef js::Vector<JSObject*> AutoObjectVector
typedef js::Vector<JSScript*> AutoScriptVector
如果上面的这些typedef不能满足你的要求,请自己继承JS::CustomAutoRooter类,并重写virtual trace()方法。
堆上的GC thing pointer
在堆上的GC thing pointer必须使用JS::Heap<T>,除非你已经使用了JS_Add<T>Root()或者JS::PersistentRooted,但除非必要,请不要使用这两种方法。但是JS::Heap<T>* 需要你自己管理。
JS::Heap<T>的构造函数不需要JSContext*,可以传一个初始值,也可以不传。像上面的其他模板类一样,它的行为也像原始指针。
有时候你创建了一个结构,它既包括堆上的GC thing pointer也包括栈上的GC thing pointer,这个情况无解,请重构你的程序。
对于JS::Heap<T>,暂时没有typedef。
错误的做法:
struct HeapStruct
{
JSObject* mSomeObject;
JS::Value mSomeValue;
};
正确的做法:
struct HeapStruct
{
JS::Heap<JSObject*> mSomeObject;
JS::Heap<JS::Value> mSomeValue;
};
总结
对栈上的局部变量,使用JS::Rooted<T>
对函数参数,使用JS::Handle<T>
对函数的输出参数,使用JS::MutableHandle<T>
使用从JS::Rooted<T>到JS::Handle<T>的隐式转换
使用从&JS::Rooted<T>到JS::MutableHandle<T>的显式转换
函数返回值可以是原始指针
对于集合,使用JS::Rooted<T>或AutoRooter
对于堆上的数据,使用JS::Heap<T>。但是Heap<T>本身需要你自己管理。
别在堆上使用JS::Rooted<T>, JS::Handle<T>和JS::MutableHandle<T>
函数参数别使用JS::Rooted<T>,使用JS::Handle<T>或JS::MutableHandle<T>
JS::PersistentRooted<T>会使变量常驻内存,直到程序结束。
翻译一篇SpiderMonkey GC的文章的更多相关文章
- 翻译一篇关于jedis的文章
翻译 自 http://www.baeldung.com/jedis-java-redis-client-libraryIntro to Jedis – the Java Redis Client L ...
- 翻译一篇文章:It's Difficult to Grow a Test Developer(成为测试开发工程师的艰辛)
翻译一篇文章:It's Difficult to Grow a Test Developer(成为测试开发工程师的艰辛) 以下文章是送给来poptest学习测试开发工程师的学员们,很多人想测试工程 ...
- Expo大作战(三十一)--expo sdk api之Payments(expo中的支付),翻译这篇文章傻逼了,完全不符合国内用户,我只负责翻译大家可以略过!
简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...
- 一篇RPO漏洞挖掘文章翻译加深理解。
这是我第一次尝试翻译一篇漏洞挖掘文章,翻译它也是为了加深理解它.这是一篇很有意思的漏洞挖掘文章. 前几天在看fd的博客,偶然看到了这篇文章,虽然有点老了.但是思路真的牛皮.我决定花费时间和精力研究它们 ...
- (转)干货|这篇TensorFlow实例教程文章告诉你GANs为何引爆机器学习?(附源码)
干货|这篇TensorFlow实例教程文章告诉你GANs为何引爆机器学习?(附源码) 该博客来源自:https://mp.weixin.qq.com/s?__biz=MzA4NzE1NzYyMw==& ...
- 《转载-两篇很好的文章整合》Android中自定义控件
两篇很好的文章,有相互借鉴的地方,整合到一起收藏 分别转载自:http://blog.csdn.net/xu_fu/article/details/7829721 http://www.cnblogs ...
- 给B公司的一些建议(又一篇烂尾的文章)
感慨:太多太多的悲伤故事,发生在自己身上,发生在自己的身边.因此,为了避免总是走"弯路",走"错误"的道路,最近一直在完善自己的理论模型. 烂尾说明:本文是一篇 ...
- 小鹏汽车技术中台实践 :微服务篇 InfoQ 今天 以下文章来源于InfoQ Pro
小鹏汽车技术中台实践 :微服务篇 InfoQ 今天 以下文章来源于InfoQ Pro
- 翻译一篇英文文章,主要是给自己看的——在ASP.NET Core Web Api中如何刷新token
原文地址 :https://www.blinkingcaret.com/2018/05/30/refresh-tokens-in-asp-net-core-web-api/ 先申明,本人英语太菜,每次 ...
随机推荐
- hdu5392 Infoplane in Tina Town(LCM)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud Infoplane in Tina Town Time Limit: 14000/ ...
- VS2012 编写C++程序的时候DOS窗口一闪而过解决办法。
在我每次通过VS2012 运行C++程序的时候,DOS窗口在显示结果的时候都是一闪而过.这样让人没法观察输出的结果.经试验找到了一较好的解决办法: 首先包含头文件"stdlib.h" ...
- 如何在webstrom中配置eslint和less
webstrom 帮助文档(英文版) 1.在webstrom中使用ESLint规范代码格式: JSHint 可以帮助检测你的 JavaScript 代码中的错误和潜在的问题,而 eslint是一个 J ...
- Linux下*.tar.gz文件解压缩命令 find 命令
1.压缩命令: 命令格式:tar -zcvf 压缩文件名.tar.gz 被压缩文件名 可先切换到当前目录下.压缩文件名和被压缩文件名都可加入路径. 2.解压缩命令: 命令格式:tar -z ...
- 文成小盆友python-num6 -反射 ,常用模块
本次主要内容: 内容补充 python中的反射 常用模块 一,内容补充: 利用上次说到的递归的方法来实现阶乘. 说明:利用函数递归的方法来实现阶乘如: 1*2*3*4*5*6*7 代码实现如下: de ...
- centos6 安装 lamp
首先更新一下yum -y update 安装Apache yum install httpd httpd-devel 安装完成后,用/etc/init.d/httpd start 启动apache 设 ...
- IOS 如何选择delegate、notification、KVO?
IOS 如何选择delegate.notification.KVO? 博客分类: IOS 前面分别讲了delegate.notification和KVO的实现原理,以及实际使用步骤,我们心中不禁有 ...
- 【转】sublime text 2 中文乱码解决办法
sublime text 2是一款非常优秀的跨平台文本及源代码编辑器,本人非常喜欢,但是不支持GB2312和GBK编码在某些时候比较麻烦.可以通过向sublime text 中添加编码类型转换包(比如 ...
- Unity3D中的工具类
1.时间:Unity提供了Time类,这个类主要用来获取当前的系统时间. Time.time:从游戏开始后开始计时,表示截止目前共运行的游戏时间. Time.deltaTime:获取Update()方 ...
- 利用好CSS,实现Qt控件美化
一.CSS概念 级联样式表 (CSS) 包含应用于网页中的元素的样式规则.CSS 样式定义元素的显示方式以及元素在页中的放置位置.可以创建一个通用规则,只要 Web 浏览器遇到一个元素实例,或遇到一个 ...