
Aptos MonoMove 运行时堆内存与垃圾回收设计全解两级内存管理、Bump 分配与 Cheney 复制式 GC【免费下载链接】aptos-coreAptos is a layer 1 blockchain built to support the widespread use of blockchain through better technology and user experience.项目地址: https://gitcode.com/GitHub_Trending/ap/aptos-core导读本文以 Aptos 仓库内 mono-move 运行时设计文档 为主线系统讲解 MonoMove 虚拟机在执行微指令micro-ops时的堆内存管理方案BlockSTM 模型下的块级block/ 交易级transaction两级内存架构、以Bump 分配 Cheney 复制式 GC为核心的单交易内存管理器、全局值global value跨交易共享与写隔离Copy-on-Write、以及 GC 安全所需的三条不变量与四种备选 GC 方案的对比取舍。读完本文你将掌握 MonoMove 如何把每条交易独立内存区 块级共享缓存落为可并行执行的现实理解frame_layout/safe_point_layouts双级指针槽扫描机制为何是常见路径零开销的关键并能结合仓库源码 runtime/src/heap/mod.rs 印证每一个设计结论。配套文档栈与调用约定见 stack_and_calling_convention.md堆上值布局见 value_representation.md全局存储读写设计见 global_storage_design.md。一、为什么需要专门的堆内存管理在 MonoMove 的扁平化执行模型中运行时的值value分为几类各有不同的内存需求局部变量与中间结果生命周期限于单条交易通常驻留在栈帧 slot 中向量vector动态增长必须上堆大型结构体 / 枚举超出栈 slot 的固定容量时需要堆分配全局值global values / resources来自链上存储或其它交易写入可能需要独立的内存区域。而类型types、代码code与全局上下文global context的内存则属于另一套体系由 loader 与全局上下文管理见 main design doc 与 loader/DESIGN.md不在本文范围。MonoMove 围绕BlockSTM 执行模型组织内存核心思想是块级Block Level管理整块block内所有交易共享的状态——即存储缓存storage cache并为每笔交易分配独立的内存子空间。交易级Transaction Level每笔交易获得一块专属内存区由自己的内存管理器负责。注设计文档原话为 TBD未来可能希望某些数据跨块存活——块级缓存有可能被保留而非丢弃供后续块复用尚未定论。这种两级分离的价值在于既能限制总内存用量每交易有界、每块有界又能支撑并行交易执行——交易间通过共享访问全局值进行协作而不是各自为政。二、块内存管理器Block Memory Manager块级内存管理器承担两项职责存储缓存Storage Cache缓存从存储层加载的资源块内所有交易共享。缓存内容是该资源在块开始时刻的状态快照。对于被高频访问的资源这能避免重复的存储读取与重复的 BCS 反序列化。交易内存分配Transaction Memory Allocation向各笔交易发放内存子空间。每笔交易拿到一块专属区域随后由交易级内存管理器自行管理。2.1 全局值如何跨交易共享执行期间产生的临时值局部变量、中间结果、新分配的 struct 与 vector天然是交易私有的但对全局值的写入必须对后续交易可见。文档给出了两条实现路线方案一冻结即完成Freeze-on-Finish交易结束后将其内存空间冻结并以只读方式暴露给后续交易。优点实现简单、不易出错为读者提供一致的视图。缺点粒度粗读写冲突被延迟检测。在源码中冻结堆已经具象化为FrozenHeap它把已冻结的会话堆包装起来不暴露任何 API持有者唯一能做的就是让堆保持存活——这正是其它交易对其做只读 pin 所需的全部能力见 runtime/src/heap/mod.rs。FrozenHeap实现了ReadPintrait与存储层懒加载使用的SharedArena只追加、永不移动、永不回收的共享竞技场一起构成了只读共享、指针永不过期的支撑类型。方案二并发数据结构Concurrent Data Structures在块级维护一个多版本数据结构为全局值提供并发共享访问。优点读写冲突即时检测。缺点复杂度高——需要在块级另设一个共享可变子空间类似存储缓存但可变可能向读者暴露不一致视图可能需要跨内存区拷贝数据与 GC 管理内存交互不良块级结构持有的引用在 GC 移动内存时必须被更新而 freeze-on-finish 下冻结区不受 GC 影响则无此问题。TODO原文档分析主网交易历史理解真实的读写模式以在两个方案之间做出取舍。2.2 每块内存上限Per-Block Memory Limits块级内存上限规定了节点在任意时刻为值所能占用的内存上界这对资源规划与防止 OOM 至关重要。为什么重要当前节点配置为了低延迟每块只容纳几十笔交易但面向吞吐量的基准测试可能让每块跑几百上千笔交易。假设默认上限为每交易 10 MB仅计算值不含代码与全局上下文数据1,000 笔交易 × 10 MB 10 GB 基准内存占用。这已经很高且多个因素会进一步推高内存内存冻结 重执行正在重执行的交易可能需要两份内存空间——一份冻结已完成的旧状态、一份活动投机执行的新状态垃圾回收复制式 GC 需要额外的 to-space收集期间内存占用实际翻倍。最坏情况下所有因素叠加峰值内存可达30–40 GB。典型使用远低于此但必须按对抗性场景做规划。此类限制今天尚可接受但随着 VM 执行速度提升未来希望在不明显牺牲延迟的前提下把更多交易放进一块这将成为可扩展性的隐忧。缓解手段原文档列举三项保守的初始分配每笔交易从小额起步、按需增长例如 1 MB → 4 MB → 10 MB。高频典型交易在默认分配内即可舒适完成高内存需求交易可以申请更多但可能需要预先声明或支付显著的内存费memory fees。硬性块级上限在块级设上限逼近上限时截断剩余交易。已有按块的气体上限per-block gas limit以类似方式工作。冻结时压缩Compact-on-freeze冻结交易内存空间时只保留全局值写入、丢弃临时值。这能显著缩小典型交易冻结区的占用但对最大化全局值写入的恶意交易效果有限。注意写集write-set生成本来就需要做这一步该扫描可能也是计量气体gas metering所必需的。三、交易内存管理器Transaction Memory Manager每笔交易在自己的子空间内拥有独立的内存管理器设计目标有二极速分配分配在热路径上必须是极低开销批量回收按批次回收内存而非逐个对象——既在交易结束时丢弃临时值也在 GC 运行期间如需。选定方案Bump 分配 使用直接指针direct pointers的 Cheney 复制式 GC。分配用 bump allocator撞针分配器保证速度堆满时运行复制式收集器Cheney 算法借助每个函数携带的frame_layout以及每个安全点携带的safe_point_layouts遍历调用栈找到根随后把所有可达对象广度优先复制进全新的 to-space并在原地修正所有指针。这样既保留了 bump 分配的速度又获得了交易中途回收内存的能力。3.1 源码印证Heap与分配路径运行时 runtime/src/heap/mod.rs 中Heap结构体由三部分组成pub struct Heap { buffer: MemoryRegion, // 后备内存每次 GC 换新 MemoryRegionto_space 成为新 buffer bump_ptr: *mut u8, // buffer 中下一个空闲字节返回给调用者的对象指针 bump_ptr OBJECT_HEADER_SIZE gc_count: usize, // GC 运行次数供测试/诊断 }内存来自 MemoryRegion一块按MAX_ALIGN对齐的、可零初始化new_zeroed适合先读后写的栈 slot或非初始化new_uninit要求先写后读debug 构建下用0xAA毒化以暴露违规的分配。OOM 通过handle_alloc_error中止。分配核心heap_alloc见 runtime/src/heap/mod.rs把total_size按MAX_ALIGN取整带溢出保护校验不超过MAX_SINGLE_ALLOCATION_SIZE当前绑定DEFAULT_HEAP_SIZE用整数地址比较判断bump_ptr size是否仍在缓冲区范围内避免形成越界裸指针的 UB然后零初始化、写对象头、返回数据区指针。单次分配上限MAX_SINGLE_ALLOCATION_SIZE DEFAULT_HEAP_SIZEruntime/src/heap/mod.rs而默认堆大小在 runtime/src/types.rs 中定义DEFAULT_HEAP_SIZE 10 * 1024 * 102410 MiB——与文档中默认每交易 10 MB的假设完全吻合。交易上下文通过 InterpreterOptions 暴露heap_size配置项默认值即DEFAULT_HEAP_SIZE目前是编译期常量未来可能改为每上下文可配置很可能由气体上限驱动。分配失败时采用先 GC 再重试策略alloc_or_gcruntime/src/heap/mod.rs在OutOfHeapMemory时运行一次gc_collect后重试仍失败则转为RuntimeError::OutOfHeapMemory。深度拷贝deep_copy_or_gc与 BCS 反序列化deserialize_or_gc走同样的GC 一次 重试模式其中反序列化对应从存储读取全局资源的热路径。其它分配入口还包括alloc_vec/alloc_vec_no_gc向量容量按元素数计长度字段默认 0、alloc_enum_no_gc按最宽变体分配并写 tag、alloc_captured_data闭包捕获区、realloc_vec向量扩容采用摊销倍增old_cap * 2与一次性大增长按required取大、grow_vec_ref通过 fat pointer 引用原地扩容并回写新指针。3.2 对象头Object Header与负偏移布局堆对象指针obj_ptr指向对象数据区的首字节其前的 8 字节存放[descriptor_id: u32 | size: u32]即偏移 -8 与 -4runtime/src/memory.rs。当MAX_ALIGN 8时分配器在数据区前预留OBJECT_HEADER_SIZE MAX_ALIGN字节使数据区起始保持MAX_ALIGN对齐descriptor_id size始终位于该预留的最后 8 字节紧邻数据区利于缓存局部性且负偏移在不同MAX_ALIGN下保持不变。GC 复制对象时gc_copy_objectruntime/src/heap/mod.rs把[header | payload]整块搬到 to-space并在 from-space 原对象数据区首 8 字节写转发指针forwarding pointer、把描述符字段改写为FORWARDED_MARKER——这是 Cheney 算法防重复复制的标准手法。3.3 全局值的读写与写隔离交易内存管理器还负责全局资源操作move_from、move_to、borrow_global等。配合 global_storage_design.md其机制是读取全局值值可能来自——块级存储缓存块开始时的基值或另一笔交易的写入/修改若采用并发共享。交易必须记录自己读过什么供后续校验BlockSTM 需要检测读写冲突。可能优化不只记录值还记录读约束例如检查过资源存在 vs 读取了实际内容以实现更细粒度的冲突检测。一个悬而未决的问题是读入是否需要把值拷贝进本地内存还是可以直接引用源地址——这取决于内存管理器设计与共享方案。修改全局值交易修改全局资源时执行**写时复制Copy-on-Write, CoW**进入自己的内存子空间。这使所有修改相互隔离从而支持交易中止或需要重执行时的回滚允许其它交易引用这些修改本地内存持有交易写入的权威版本。在 BlockSTM 中每笔交易的修改与MVHashMap集成——交易本地内存实际上成为多版本结构中的一个 slot取代现有的ArcValue方案。实现细节上交易把全局值读取缓存在working mapHashMap(AccountAddress, InternedType), Entry中Entry区分只读的ExternalHeap指向其它交易竞技场或块缓存只读零拷贝携带 Block-STM 版本号与写后的LocalHeapCoW 后的本地副本小资源走Inline优化直接拷贝字节。两个悬而未决的问题原文档CoW 时机应在borrow_global_mut时急切执行还是在真正写入时惰性执行惰性 CoW 避免多余拷贝但需要跟踪借用的引用来探测写入发生。GC 交互若 GC 在交易中途运行指向交易已修改值为共享而由块级结构持有的引用必须更新到移动后的地址。若采用 freeze-on-finish 则大概率无需担心——冻结内存不再参与后续 GC 运行。四、内存安全Memory Safety4.1 引用有效性Reference ValidityMove 字节码验证器对引用安全无悬垂引用、正确的借用语义提供静态保证但运行时检查仍可作为纵深防御抵御验证器 bug 或解释器错误。文档提出的候选运行时检查代际/世代计数器Epoch/generation counters每个分配的内存块携带世代号引用携带期望世代不匹配则访问失败——可捕获 use-after-free边界检查Bounds checking引用访问校验索引/偏移在界内。这些检查的成本需要与安全收益权衡实现成熟后可能在生产环境关闭。4.2 内存区域隔离Memory Region Isolation交易只应访问自己的本地内存区块级存储缓存只读基值其它交易的冻结内存若采用 freeze-on-finish 共享。违反即为解释器的严重 bug。这正是FrozenHeap设计的意义所在——冻结堆不暴露任何分配/改写 API从类型层面杜绝了越权访问。4.3 GC 安全三条不变量所有指针在 GC 移动内存后必须被更新漏掉一个指针就会产生悬垂引用。运行时安全模型建立在三条不变量上详见 runtime/AGENTS.md 与 gc_collect 的安全假设注释帧元数据完整性Frame metadata integrity——保存的fp/pc/func_ptr只由 call/return 写入用户微指令绝不触碰。GC 遍历调用栈时依赖META_SAVED_FP_OFFSET、META_SAVED_FUNC_PTR_OFFSET等固定偏移读取元数据。指针槽准确性Pointer-slot accuracy——Function::frame_layout以及在安全点匹配的safe_point_layouts条目必须精确匹配持有存活堆指针的槽位漏项 → GC 后悬垂指针多余项 → 非指针数据被当作指针UB。对象头完整性Object header integrity——descriptor_id与size位于固定负偏移obj_ptr - 8与obj_ptr - 4由分配器写入用户微指令只访问数据区≥ 0偏移永远够不到头部。此外执行前verify_program会校验帧访问边界、元数据重叠、跳转目标与描述符有效性runtime/AGENTS.md。4.4 辅助 GC 根RootPool栈帧是主要根集但某些场景需要在指针被存入帧布局描述的槽位之前就让它保持存活融合式多分配微指令如PackClosure先分配对象 A再分配对象 B——B 的分配可能触发 GC而 A 尚未链接进帧原生函数未来Rust 代码在可能触发 GC 的调用期间于局部变量中持有堆指针。RootPoolcore/src/root_pool.rs即为此设计的句柄表式根集调用者通过root_object(ptr)或root_reference(base, offset)取得一个RAII 句柄GC 除扫描调用栈外还扫描该池对象搬移时原地改写被 root 的指针句柄支持任意顺序 drop槽位经 free list 复用。机制上与 JNI local refs 或 V8LocalT同源。GC 阶段 1b 即执行extra_roots.relocate_each(|base| scanner.relocate(base))见 gc_collect。4.5 类型安全Type Safety扁平内存表示下值就是按类型信息解释的原始字节运行时须确保以正确的类型访问值。原文档将此列为 TBD内存管理器还能为此风险做什么五、GC 设计空间四种方案对比与最终取舍文档对四种内存管理方案做了系统比较。所有方案均假设 bump-allocated 堆 复制式收集或等价物。最终实现是方案 A 与方案 B 的混合体。5.1 方案 A直接指针 安全点栈图Direct Pointers Stack Maps at Safe Points帧槽直接保存原始堆指针。重编译器specializer在每个 GC 安全点分配点、调用返回点发射栈图stack map列出哪些帧偏移持有存活堆指针。GC 扫栈图找根再用对象描述符做传递式追踪Cheney 复制收集器。优点堆访问零开销直接指针、单次加载无过度保留只有真正存活的指针是根无每次写操作簿记。缺点重编译器必须在安全点做活跃性分析并发射栈图控制流汇合点的 maybe alive 问题、空初始化纪律等GC 搬移时必须重写栈上及堆内对象的每个指针fat pointer 基址也需重写跨 GC 触发调用持有裸指针的原生函数会得到悬垂指针。状态作为 AB 混合设计的一部分部分实现。5.2 方案 B直接指针 分区帧Direct Pointers Partitioned Frames与 A 相同但重编译器只标记哪些帧槽持有指针而非发射安全点栈图。两种做法连续分区指针区fp0..fpK、标量区fpK..end槽列表每函数一个Vecu32列出持指针的帧偏移。任选其一GC 扫描每帧被标记的指针槽即可——无需活跃性追踪。指针区中逻辑已死但尚未覆写的过期指针造成过度保留对象在槽被复用或帧弹出前一直存活。对生命周期极短短则毫秒级的区块链交易而言可忽略。优点与 A 相同的直接访问性能重编译器大幅简化——只需在帧布局中标记指针槽。缺点过期指针的过度保留短交易下影响很小GC 搬移时仍需重写全部指针栈 内部fat pointer 基址重写仍需处理原生函数 GC 安全仍未解决追踪内部堆引用仍需对象描述符。状态以 AB 混合形式实现细节见下。5.3 混合设计AB在源码中的落点frame_layoutsafe_point_layouts每个Functioncore/src/function.rs声明两级指针槽信息frame_layout: FrameLayoutInfo——任何 PC 处都恒为堆指针的帧偏移GC 在每个 PC 处都扫描方案 Bsafe_point_layouts: SortedSafePointEntries——仅特定安全点额外有效的指针偏移只有帧的当前 PC 命中安全点条目时才被扫描方案 A。在任意安全点GC 扫描二者的并集。安全点 分配类指令在其自身 PC与调用返回点call_pc 1。当zero_frame为 true 时运行时在执行 call 指令时把参数区之外param_sizes_sum..extended_frame_size的区域清零使指针槽以 null 起步——GC 看到的是空指针而非垃圾。safe_point_layouts按code_offset严格排序支持 O(log n) 二分查找SortedSafePointEntries::layout_at。GC 阶段 1a 的实现gc_collect与之精确对应栈顶帧扫frame_layout.heap_ptr_offsets 命中当前 PC 时的safe_point_layouts条目若栈顶是原生帧则扫其 ABI 参数指针槽栈顶以下的调用者帧只用frame_layout。该混合方案让常见情况保持简单——稳定指针槽走frame_layout无逐 PC 开销同时支持跨调用边界改变类型如共享的参数/返回区、不同被调方参数布局的槽位。specializer 可自由选用任一机制类型固定的槽用frame_layout类型随 PC 变化的槽用safe_point_layouts。5.4 方案 C句柄表 分区帧Handle Table Partitioned Frames堆指针换成句柄 ID——对象句柄表的索引表中存真实堆地址。帧布局分区句柄区 vs 标量区同方案 BGC 无需栈图即知哪些槽是句柄。GC 扫描句柄区找根句柄、经描述符传递追踪对象搬移只更新句柄表条目不必重写栈上及对象内每个指针。优点无栈图GC 搬移廉价只改表项fat pointer 变为(handle_id, offset)跨 GC 稳定、无需重写基址原生函数持有句柄 ID跨 GC 仍有效——解决了原生 GC 安全引用borrow自然成立——持有句柄 ID经表解引用。缺点每次堆访问多一次间接表查找 数据加载句柄表本身竞争缓存短交易下可能仍放得进 L1需要 free list 回收表槽指针区过期句柄过度保留同 B追踪内部堆引用仍需要对象描述符。状态未实现。5.5 方案 D句柄表 所有权树Handle Table Ownership Tree / Parent Pointers在 C 之上每个句柄表条目再存一个父字段所属容器的句柄 ID或 stack root 哨兵构成一棵镜像 Move线性所有权模型的树——每个值恰有一个所有者。GC 不扫帧、不追踪对象图而是重编译器在栈根死亡时发射Drop→ O(1) 置空父字段GC 遍历句柄表逐句柄向上追踪父链链到存活栈根 → 句柄存活链到 null/死亡父 → 不可达释放结果缓存在并行数组中每句柄每轮收集至多解析一次。重编译器必须上报每一次所有权变更Drop栈根死亡、Store入容器ObjStore/VecPushBack/VecStoreElem设置子句柄父、从容器移出ObjLoad/VecPopBack/VecLoadElem重新归属到接收栈槽、WriteRef/ReadRef可变引用写穿导致的所有权转移/重归属、Mov/Mov8栈槽间搬移句柄需重新归属。引用borrow不参与父树——它们持有句柄 ID 但非所有者Move 借用检查器保证所有者比所有借用长寿运行时信任该不变量。早期 PoC 的 GC 算法压缩式 bump 收集器① 遍历句柄表划分 active/inactive沿父链判定结果缓存摊还 O(1)/句柄迭代无递归② 回收 inactive 表槽进 free list③ 分配新内存区把每个 active 句柄的数据连续拷入并更新handle.mem_ptr——因所有访问都经句柄表其余无需任何重写④ 释放旧区。向量扩容同理bump 分配更大块、拷贝内容、更新单个表项。优点无栈扫描、无栈图、无帧分区要求GC 追踪不需要对象描述符父树取代描述符驱动图遍历无传递式对象图遍历O(1) Drop、延迟惰性收集原生 GC 安全。缺点每次句柄变更都有开销父指针更新需要句柄感知指令变体——重编译器必须在处处区分句柄类型运算与标量运算重编译器必须在每个值死亡点发射Drop——漏一个即泄漏GC 需遍历所有句柄存活 死亡做分区而追踪式收集器A/B/C只访问可达对象。状态当前 PoC 未实现早期独立 PoC 验证了核心算法。5.6 四种方案横向对比维度A直接 安全点栈图B直接 分区C句柄 分区D句柄 所有权树堆访问成本直接1 次加载直接1 次加载间接2 次加载间接2 次加载GC 根发现逐 PC 栈图扫描指针区扫描指针区父链无扫描GC 图遍历全量传递追踪同左同左父链行走迭代GC 搬移成本重写全部指针同左更新句柄表更新句柄表Drop不适用GC 回收不适用GC 回收不适用GC 回收O(1) 置空父过度保留无过期指针过期句柄无所有权精确Fat pointer GC重写基址同左稳定稳定原生 GC 安全不安全不安全安全安全每次变更开销无无无每次句柄操作更新父重编译器负担重轻轻中描述符需求需要需要需要不需要GC 复杂度中Cheney 栈图中Cheney中mark-sweep 句柄表低父链行走指令集复杂度低低低中句柄感知变体5.7 推荐结论为什么是 AB 混合对绝大多数区块链交易而言堆能舒适地装进预分配区域GC 从不触发。收集是安全网而非稳态机制同时我们也不关心 stop-the-world 暂停延迟。这彻底改变了权衡GC 算法成本几乎无关紧要——如果几乎不运行父链行走还是全图遍历都无所谓D 在 GC 复杂度上的优势权重很小。每次变更开销才是主导成本——D 的每次父指针更新无论 GC 是否触发都在热路径上付出而簿记几乎从不带来收益这是纯开销。过度保留不是问题——收集器几乎不运行B/C 的过期指针只是闲置到交易结束与被收集无异。在此假设下AB 混合是明确赢家热路径零开销重编译器负担最小——只有跨调用边界改变指针状态的槽位需要安全点条目稳定指针槽用更简单的frame_layout。其缺点过度保留、GC 期间指针重写要么有限要么是几乎不用付出的成本。纯方案 A处处栈图让重编译器在每个安全点做活跃性分析在常见情形下无收益纯方案 B无逐 PC 信息无法正确描述跨调用边界改变类型的槽位。混合方案兼得二者之长。方案 C仅在原生 GC 安全成为现实障碍时才值得考虑否则它用每次访问的句柄间接成本换取几乎不会兑现的 GC 收益。方案 D是最优雅的设计、GC 也最简单但在 GC 几乎不触发时每次变更的父更新是错误权衡——它优化了稀有情形收集牺牲了常见情形每次句柄操作。5.8 为什么需要 GC仅 Bump vs Bump 收集文档坦诚记录了团队的反复权衡。如果 GC 几乎不触发何不干脆只做 bump 分配、跑完交易、丢弃整个 arena交易能分配的内存量有硬上限——简单、快速对大多数交易数学上成立。但一直困扰团队的是纯 bump 下所有分配都是内存泄漏。挥之不去的情形是循环分配瞬时对象——每轮迭代的结果被消费但堆持续增长因为没有任何回收。程序在存活数据上完全在内存限额内做着合法工作却因无法复用死内存而死亡。更深层的担忧是承诺的代价若只发布 bump-only合约模式与内存上限将围绕那个天花板构建日后追加 GC 意味着把指针重定位改造成一个本未为此设计的运行时并引入新的故障模式——这是团队不愿签署的痛苦返工。最终没有争论的必要已有一个可用的复制收集器、对象描述符与指针重写——工程成本已经付过。方案 B 下常见路径本就是 bump 分配零开销收集器只是堆满时的安全网罕见。我们没有为 GC 付钱我们已经有它了——它是廉价保险换来处理高分配工作负载而不撞硬墙的能力以及不必担心未来工作负载形态的自由。六、如何继续深入仓库阅读路线若要进一步验证本文观点建议按以下路径阅读源码堆与 GC 核心实现runtime/src/heap/mod.rsHeap、heap_alloc、alloc_or_gc、gc_collect、RootScanner、gc_copy_object、gc_scan_object、realloc_vec、FrozenHeap/SharedArena对象头与内存原语runtime/src/memory.rsMemoryRegion、write_object_header、转发指针读写GC 根句柄表core/src/root_pool.rsRootPool、root_object/root_reference、RAII 句柄帧布局与安全点条目core/src/function.rsFunction::frame_layout、safe_point_layouts、zero_frame、extended_frame_size默认堆大小等常量runtime/src/types.rsDEFAULT_HEAP_SIZE 10 MiB解释器接线与上下文runtime/src/interpreter.rsInterpreterOptions::heap_size、InterpreterContext、堆冻结全局存储读写设计global_storage_design.mdworking map、ExternalHeap/LocalHeap/Inline、CoW 与回滚日志、Exists/BorrowGlobal/BorrowGlobalMut/MoveFrom/MoveTo微指令安全模型速览runtime/AGENTS.md三条不变量、verify_program、编码规范。如需在本地构建与测试该运行时可执行cargo check -p mono-move-runtime cargo test -p mono-move-runtime cargo test -p mono-move-runtime -- 测试名说明以上内容均以 heap_and_gc.md 为骨架结合仓库内对应实现与设计文档整理而成文档中标注的 TODO/TBD 项块级缓存跨块保留、读写模式分析、CoW 时机、GC 与共享内存交互、内存管理器的类型安全手段等仍属未决设计引用时请注意区分已实现与规划中。【免费下载链接】aptos-coreAptos is a layer 1 blockchain built to support the widespread use of blockchain through better technology and user experience.项目地址: https://gitcode.com/GitHub_Trending/ap/aptos-core创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考