前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2021.5.6日报:修复mb v8 7.5的GC的bug

2021.5.6日报:修复mb v8 7.5的GC的bug

作者头像
龙泉寺扫地僧
发布2021-12-06 10:33:03
3120
发布2021-12-06 10:33:03
举报
文章被收录于专栏:盟主来了盟主来了

现在虽然把mb的v8版本升级到了7.5.但这玩意目前发现有个重大的小问题:https://element.eleme.cn/#/zh-CN/component/button这里面的按钮,过了几分钟就点不动了。

也就是没响应消息了。

调试了一番后,发现是如下这段代码就可以重现:

代码语言:javascript
复制
<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-05-06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档