标签:2021.5 mb blink var GC 版本 v8 messageChannel port1
现在虽然把mb的v8版本升级到了7.5.但这玩意目前发现有个重大的小问题:https://element.eleme.cn/#/zh-CN/component/button这里面的按钮,过了几分钟就点不动了。
也就是没响应消息了。
调试了一番后,发现是如下这段代码就可以重现:
<script>
var timerFunc;
//var port1;
function flushCallbacks () {
console.log("flushCallbacks");
}
function initTimer() {
var messageChannel = new MessageChannel;
var port2 = messageChannel.port2;
//port1 = messageChannel.port1;
messageChannel.port1.onmessage = flushCallbacks;
timerFunc = function() {
console.log("postMessage"); // weolar
port2.postMessage(1);
}
}
initTimer();
timerFunc();
</script>
在7.5v8中,会发现port1过不久就被析构了。
那为啥低版本v8不会呢?
对比了下新版本chromium,我看的是一头雾水。新版本chromium的gc比老版本复杂多了。貌似引入多代GC的概念。
只看到blink里有什么地方引用了这个port1..具体来说,是ThreadHeap::AdvanceMarking的marking_worklist_引用了。但这个marking_worklist_又是如何判断是否引入,我还没搞明白。
再看回老版本blink,终于发现了一点眉目。老版本blink,在MajorGCWrapperVisitor的VisitPersistentHandle,会遍历到这个port1.而这个遍历,是v8发起的,也是v8提到了变量。
整理了一下思路,大概搞明白了。v8对于这种native端的变量,会询问blink层。而blink层发现这玩意是个ActiveDOMObject对象,就会判断activeDOMObject->hasPendingActivity()。
老版本v8,我猜测是用m_isolate->SetObjectGroupId(*value, liveRootId());标识了这个对象在v8层不能被回收。然后到了gc的另外个阶段,也就是V8GCController::traceDOMWrappers这里面后,
v8会通知blink这个对象要做trace,也就是让blink不要回收。
而新版本v8,需要手动再调用tracer->RegisterEmbedderReference(tracedGlobal.Get());告诉v8.
我加上这个tracer->RegisterEmbedderReference(tracedGlobal.Get());后,貌似问题解决了。
标签:2021.5,mb,blink,var,GC,版本,v8,messageChannel,port1
来源: https://blog.csdn.net/weolar/article/details/116455304
本站声明:
1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。