语言运行时编译器JIT编译解释器内存管理【免费下载链接】v8The official mirror of the V8 Git repository项目地址https://gitcode.com/gh_mirrors/v81/v8点击查看免费下载V8 是 Google 开发的 JavaScript 引擎其自动内存管理依赖一套高度复杂的垃圾回收GC系统。本文以 docs/heap/garbage-collection.md 为主线结合 docs/heap/marking-and-sweeping.md、docs/heap/compaction.md、docs/heap/heap-overview.md 以及 src/heap/WRITE_BARRIER.md 等仓库文档系统讲解 V8 的分代式 GC 架构年轻代Young Generation的 Scavenger 与 Minor Mark-Sweep老年代Old Generation的 Mark-Sweep-Compact以及支撑这一切的写屏障Write Barrier与并发/并行回收机制。读完本文你将理解 V8 堆的空间划分、两次 GC 的核心算法流程、--minor-ms等关键命令行参数的含义并能从源码层面追踪每个机制的实现位置。分代假说GC 设计的理论基石V8 的 GC 是分代收集器generational collector它将堆按对象存活时间划分为不同代generation。这一设计的理论依据是分代假说Generational Hypothesis绝大多数对象在分配后不久就会死亡most objects die young。基于这一假说V8 采用年轻代频繁快速回收、老年代低频深度回收的策略从而在整体上压缩 GC 停顿时间pause time。存活下来的对象会被**提升promote/tenure**到更老的代具体内存布局可参考 docs/heap/heap-overview.mdV8 堆被划分为 New Space年轻对象采用 Cheney 复制算法、Old Space幸存对象、Read-Only Space共享不可变对象、Large Object Space大于一页的对象、Code Space可执行指令以及开启 Sandbox 后的 Trusted Space 等。年轻代新对象的诞生地与快速回收年轻代Young Generation存放新分配的对象。它通常很小几 MB 到几十 MB设计目标就是快速收集。ScavengerMinor GC半空间复制回收器年轻代的默认收集器是Scavenger采用半空间semi-space设计实现位于 src/heap/scavenger.h 与 src/heap/scavenger.cc。其回收周期Scavenge cycle如下年轻代被划分为两半To-Space与From-Space。新对象在 To-Space 中分配。当 To-Space 被填满时一次 Scavenge 周期开始。周期开始时To-Space 与 From-Space 的角色互换原先存放新对象的空间变成From-Space空的空间变成To-Space。Scavenger 从 From-Space 追踪存活对象并复制到 To-Space若对象已存活过上一轮周期则提升到老年代。由于这是复制式收集器copying collector对象在复制过程中自然紧凑排列年轻代不会产生碎片fragmentation。Minor Mark-SweepMinor MS默认不开启的替代收集器Minor Mark-SweepMinor MS是 V8 中另一个年轻代收集器通过--minor-ms标志启用DEFINE_EXPERIMENTAL_FEATURE(minor_ms, perform young generation mark sweep GCs)见 src/flags/flag-definitions.h。与 Scavenger 的复制策略不同Minor MS 采用标记-清扫mark-sweep方式目标在特定工作负载下避免复制对象的开销、降低内存碎片。标记Marking从根集合roots与记录集remembered sets如OLD_TO_NEW出发标记可达对象支持并发concurrent与并行parallel标记。非移动Non-Moving与 Scavenger 不同Minor MS 通常不移动对象。整页提升Page Promotion当某一页存活率很高时Minor MS 不是逐个复制对象而是将整个页直接提升到老年代只需更新元数据无需拷贝对象。清扫Sweeping未被提升的页被清扫回收死对象占用的内存清扫也可并发执行。实现文件src/heap/minor-mark-sweep.cc 与 src/heap/minor-mark-sweep.h。从源码结构看MinorMarkSweepCollectorsrc/heap/minor-mark-sweep.h封装了CollectGarbage()、StartMarking()、Sweep()等完整流程并维护MarkingWorklists、EphemeronRememberedSet、PretenuringFeedbackMap等状态说明 Minor MS 与 Major GC 共享了大量标记基础设施。与 Minor MS 配套的还有一系列可调参数见 src/flags/flag-definitions.h参数默认值含义minor_ms_page_promotion_threshold50页上存活字节的最小百分比达到则启用 MinorMS 中的快速整页提升minor_ms_page_promotion_max_lab_threshold30页中 LAB线性分配区占页的最大百分比超过则不考虑整页提升minor_ms_max_page_age4页的最大年龄超过后强制提升到老年代concurrent_minor_ms_markingtrue是否并发执行年轻代标记minor_ms_min_new_space_capacity_for_concurrent_marking_mb8非 DEBUG/ 0DEBUG启用年轻代并发标记所需的最小 New Space 容量MBminor_ms_concurrent_marking_trigger90Minor MS 并发标记触发点占当前 New Space 容量的百分比minor_ms_min_lab_size_kb0覆盖 Minor MS 下 New Space 分配的最小 LAB 大小KB此外minor_ms还与page_promotion存在蕴含关系DEFINE_IMPLICATION(minor_ms, page_promotion)见 src/flags/flag-definitions.h即开启 Minor MS 会自动开启整页提升sticky_mark_bits同样蕴含minor_mssrc/flags/flag-definitions.h。在cppgc_young_generation开启时也会自动启用minor_mssrc/flags/flag-definitions.h。老年代长期存活对象的归宿在年轻代存活了若干轮 Scavenge 周期的对象会被提升tenured到老年代Old Generation。该空间大得多存放生命周期长的对象。Mark-Sweep-CompactMajor GC老年代由Mark-Sweep-Compact收集器回收这是一个复杂得多的过程分为三个阶段标记Marking收集器从根栈、全局对象等出发遍历对象图将所有可达对象标记为存活。V8 使用增量标记Incremental Marking与并发标记Concurrent Marking让大部分标记工作在主 JS 线程运行的同时完成从而最小化停顿时间。清扫Sweeping收集器扫描堆将死对象未标记占用的内存加入空闲链表free list供后续分配复用清扫同样可以并发执行。压缩Compaction随着时间推移老年代会产生碎片。收集器会选择性地压缩某些页——将存活对象移动到一起并更新指针以制造大块连续空闲空间。上述三阶段的实现细节在 docs/heap/marking-and-sweeping.md 中有深入讲解标记位图Marking Bitmap定义于 src/heap/marking.h堆中每一页都关联一个标记位图位映射到带标记的对象地址并发置位时使用原子操作。三色标记中黑色已处理对象位图为1且不在 worklist 中。MarkingVisitorsrc/heap/marking-visitor.h从 worklist 弹出灰色对象利用BodyDescriptor迭代其指针对每个未标记的目标在位图中标记并推入 worklist使其变为灰色。并发标记的 Worklist 与工作窃取MarkingWorklist使用线程局部段segment避免同步开销段满后发布到全局池其他线程无活可干时可窃取段。On-Hold Worklist并发标记时后台线程遇到主线程正在 LAB 中分配的对象会跳过bail out将其推入 On-Hold Worklist避免数据竞争该列表在主线程安全的时机如 safepoint 处 LAB 被冲刷处理或合并回共享 worklist。注意cppgcV8 的 C 垃圾回收器中对应概念叫 Bailout Worklist。对象布局变更与字符串转换主线程在后台线程扫描期间改变对象布局如字段从 tagged 转为 untagged或转换字符串可能引发崩溃V8 使用ObjectLockGuard对象锁保证独占访问其他复杂转换则通过操作顺序与内存屏障同步。清扫器Sweepersrc/heap/sweeper.cc遍历老年代页识别连续死对象区间用Filler对象填充并加入空间的空闲链表。压缩Compaction的实现管线关于第三阶段docs/heap/compaction.md 给出了完整的压缩管线实现在 src/heap/mark-compact.cc识别撤离候选页Evacuation CandidatesCollectEvacuationCandidates计算碎片阈值空闲空间超过阈值的页成为候选。为限制停顿时间V8 限制总撤离字节数max_evacuated_bytes并按存活字节升序即空闲空间最多的页优先排序选择使每移动一字节回收的空间最大化。ComputeEvacuationHeuristics依据模式ReduceMemory、OptimizeForMemoryUsage 或常规延迟敏感模式确定目标碎片率与最大撤离字节数常规模式下还可能基于 trace 的压缩速度自适应调整阈值。并行撤离Parallel Evacuation对象移动并行执行。部分 New Space 页或受栈扫描限制时通过整页提升直接更新元数据完成晋升需要压缩的页则逐个将存活对象复制到非候选页新分配的空间。转发地址Forwarding Addresses对象移动后原对象的 map word 被覆写为指向新位置的转发地址forwarding address这是更新旧指针的关键。指针更新Pointer UpdatingUpdatePointersAfterEvacuation扫描所有根栈、句柄等与记录集以更新跨对象引用涉及OLD_TO_NEW、OLD_TO_SHARED、OLD_TO_OLD、TRUSTED_TO_CODE、TRUSTED_TO_TRUSTED、TRUSTED_TO_SHARED_TRUSTED等各类记录集。压缩成本高昂涉及拷贝对象与更新指针因此 V8 只在碎片严重的页上执行。另外启用 V8 Sandbox 时外部指针表external pointer tablesyoung、old、cpp_heap也会在标记阶段开始时StartMarking按需压缩。写屏障分代回收与增量标记的基石为了在不扫描整个堆的前提下支持分代 GC 与增量标记V8 引入了写屏障Write Barrier。写屏障是编译器为host.field value这类堆存储操作生成的代码用于告知 GC 对象图的变化。其详细规范见 src/heap/WRITE_BARRIER.md主要承担三个职责分代屏障Generational BarrierOld-to-New将老年代指向年轻代的引用记录进记录集OLD_TO_NEW使 Scavenger 无需扫描整个老年代即可找到存活的年轻对象。该屏障始终启用。标记屏障Marking Barrier防止增量/并发标记期间出现黑指向白black-to-white引用。若黑色已追踪对象被更新为指向白色未追踪对象标记屏障会确保目标对象被标记或推入 worklist。撤离屏障Evacuation BarrierOld-to-Old当目标对象位于撤离候选页上时记录老年代对象之间的引用以便压缩后更新指针。何时可以消除写屏障写屏障有性能开销V8 在安全时会消除它WriteBarrier::IsRequired()是是否需要屏障的权威判断见 src/heap/WRITE_BARRIER.mdSmi 或只读对象Smi or Read-Only存储 Smi 或指向只读对象的指针永远不会产生对 GC 有意义的引用无需屏障。初始化存储Initializing Stores向最近分配的年轻对象在可能的 GC 点之前写入字段无需屏障。这在三种屏障下都安全host 本身年轻无需记录 old-to-newhost 年轻无需追踪 old-to-old 槽位年轻代内部引用在原子 GC 停顿期间通过扫描年轻代发现代价低标记屏障方面并发标记会对位于当前 New Space LAB 中的对象跳过追踪并推入 on-hold 队列使其保持灰色grey而非黑色因此不会出现黑指向白。出于严谨源码强调写屏障只能通过各层的正规瓶颈bottleneck省略例如使用SKIP_WRITE_BARRIER会在 DEBUG 构建中触发写屏障校验src/heap/WRITE_BARRIER.md。写屏障的四级实现路径从源码看写屏障按最快到最慢拆分为四段实现见 src/heap/WRITE_BARRIER.md快速路径fast/inline检查 host 对象所在页头是否设置了POINTERS_FROM_HERE_ARE_INTERESTING标志未设置则正常继续执行。Turbofan 在kArchAtomicStoreWithWriteBarrier指令中实现Maglev 在StoreTaggedFieldWithWriteBarrier节点中实现Sparkplug 通过MacroAssembler::RecordWrite实现C 侧则是CombinedWriteBarrierInternalsrc/heap/heap-write-barrier-inl.h。延迟路径deferred/out-of-line检查 value 对象所在页头是否设置了POINTERS_TO_HERE_ARE_INTERESTING是则调用慢路径 builtin。Sparkplug 是唯一不将该检查放到 out-of-line 代码中、而是直接内联发射的编译器。共享慢路径shared slow path所有编译器与调用点共享。分代屏障将槽位记录进 old-to-new 槽位集增量/并发标记期间还标记 value 对象并可能将指向撤离候选的槽位记录进 old-to-old 记录集。实现于 src/builtins/builtins-internal-gen.cc 的 CSA 代码与RecordWriteXXXbuiltins。C 慢路径向槽位集插入可能需要malloc()内存因此 builtin 可能调用 C 函数Heap::InsertIntoRememberedSetFromCodesrc/heap/heap.cc。值得注意的是CSA 与解释器没有自己的屏障而是复用 Turbofan 的写屏障。另外启用 Sandbox 时V8 还需要针对指向 Trusted Space 的间接指针屏障indirect pointer barrier它仅在 64 位架构实现、仅用于 CSA/汇编器编写的 builtins且只在增量标记期间激活Turbofan 对应指令为kArchStoreIndirectWithWriteBarrier。并发与并行 GC低延迟的工程支柱为达成低延迟目标V8 大量利用后台线程并行Parallel主线程与工作线程同时执行 GC 工作例如 Parallel Scavenge。并发Concurrent工作线程在主线程运行 JavaScript 的同时执行 GC 工作例如 Concurrent Marking 与 Concurrent Sweeping。这一区分在 docs/heap/garbage-collection.md 中有明确说明并在 Minor MS 与 Major GC 的源码实现中均有体现如concurrent_minor_ms_marking标志、MarkingWorklist的工作窃取、Sweeper 的并行清扫等。总结V8 的垃圾回收是一套分代式、多策略并存的系统年轻代默认由半空间复制的 Scavenger 回收也可切换为--minor-ms的非移动标记-清扫方案老年代由 Mark-Sweep-Compact 处理通过标记位图、增量/并发标记、空闲链表清扫与选择性压缩控制停顿与碎片写屏障则以四级代码路径支撑分代记录、增量标记与压缩后的指针更新。本文相关的核心文档与源码入口包括 docs/heap/garbage-collection.md、docs/heap/marking-and-sweeping.md、docs/heap/compaction.md、docs/heap/heap-overview.md、src/heap/WRITE_BARRIER.md、src/heap/scavenger.cc、src/heap/minor-mark-sweep.cc 与 src/heap/mark-compact.cc读者可沿这些路径继续深入。赞分享语言运行时编译器JIT编译解释器内存管理【免费下载链接】v8The official mirror of the V8 Git repository项目地址https://gitcode.com/gh_mirrors/v81/v8点击查看免费下载相关推荐如何让CSS视口单位vw、vh、vmin在IE5.5中生效vminpoly快速入门完整指南如何让CSS视口单位vw、vh、vmin在IE5.5中生效vminpoly快速入门完整指南 vminpoly 是一款轻量级的 CSS 视口单位 polyfil语言运行时编译器JIT编译解释器内存管理Julia 垃圾回收器GC内部原理深度解析Mark-Sweep、分代收集与并发清扫Julia 垃圾回收器GC内部原理深度解析Mark Sweep、分代收集与并发清扫 导读 本文基于 Julia 官方开发者文档 doc/src/devdo编程语言编译器语言运行时标准库JIT编译安全与伦理考量使用Nemotron-3-Nano-Omni-30B-A3B-Reasoning-NVFP4的最佳实践安全与伦理考量使用Nemotron 3 Nano Omni 30B A3B Reasoning NVFP4的最佳实践 Nemotron 3 Nano Omni人工智能大模型基础模型多模态推理模型上一篇Hyperf框架快速入门指南构建高性能HTTP服务下一篇MailKit入门指南邮件处理库的安装与构建创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考