From d1704b42ef97707de9dfb70f974616b66a8f0fd3 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Wed, 19 Aug 2026 16:31:45 +0800 Subject: [PATCH] docs(native-class): update memory layout documentation and add padding fields to test classes - Add $padding field to NativeFailedClonePressure class in failed-clone-finalizer.phpt - Add $padding field to NativeFailedLifecyclePressure class in failed-lifecycle-escape.phpt - Add $padding field to NativeFinalizerFiller class in finalizer-allocation.phpt - Add $padding field to NativeFinalizerPressureObject class in finalizer-inheritance-exception.phpt - Add multiple padding fields ($padding1, $padding2, $padding3) to NativeGcThresholdValue class in gc-threshold.phpt - Add $padding field to NativeLifecycleFiller class in lifecycle-exceptions.phpt - Update native heap memory layout documentation with fixed header size information - Clarify that GC header uses two machine words (16 bytes on 64-bit platforms) - Explain that object size, alignment and callbacks are stored in static NativeTypeDescriptor - Remove mention of initial --- docs/NATIVE_CLASS_OBJECT.md | 9 ++++----- tests/compiler/native-class/failed-clone-finalizer.phpt | 1 + tests/compiler/native-class/failed-lifecycle-escape.phpt | 1 + tests/compiler/native-class/finalizer-allocation.phpt | 1 + .../native-class/finalizer-inheritance-exception.phpt | 1 + tests/compiler/native-class/gc-threshold.phpt | 6 ++++++ tests/compiler/native-class/lifecycle-exceptions.phpt | 1 + 7 files changed, 15 insertions(+), 5 deletions(-) diff --git a/docs/NATIVE_CLASS_OBJECT.md b/docs/NATIVE_CLASS_OBJECT.md index 92d78274..63ad573c 100644 --- a/docs/NATIVE_CLASS_OBJECT.md +++ b/docs/NATIVE_CLASS_OBJECT.md @@ -431,21 +431,20 @@ Native Class Object 应使用独立的、非移动、精确 tracing GC。本文 ### 8.1 Native Heap -首版 Wren 派生实现为每个对象分配一块连续内存,并在 struct 前放置隐藏 GC header: +Wren 派生实现为每个对象分配一块连续内存,并在 struct 前放置隐藏 GC header。Header 固定为两个机器字,在 64 位平台上是 16 字节: ```cpp struct NativeGcHeader { + // 低 3 位复用为 marked/finalized/allocated-during-collection 标志。 + uintptr_t nextAndFlags; const NativeTypeDescriptor *type; - NativeGcHeader *next; - uint32_t flags; - uint32_t size; }; // 内存布局:[NativeGcHeader][php_app__point] auto *point = native_heap.make(); ``` -GC header 不属于生成的 C++ struct,也不会改变属性偏移。用户可见对象变量仍然只是一个 `native_struct *`。 +GC header 不属于生成的 C++ struct,也不会改变属性偏移。用户可见对象变量仍然只是一个 `native_struct *`。对象尺寸、对齐方式及 trace/finalize/destroy 回调保存在每个类型唯一的静态 `NativeTypeDescriptor` 中,不在每个实例中重复保存。 当前分配器使用独立 non-moving allocation;Arena/chunk/free-list 可以作为后续分配器 优化,但不得改变对象地址稳定性、header 布局、精确 tracing 或 finalization 语义。 diff --git a/tests/compiler/native-class/failed-clone-finalizer.phpt b/tests/compiler/native-class/failed-clone-finalizer.phpt index 842ac910..7a776c8f 100644 --- a/tests/compiler/native-class/failed-clone-finalizer.phpt +++ b/tests/compiler/native-class/failed-clone-finalizer.phpt @@ -25,6 +25,7 @@ class NativeFailedCloneFinalizer class NativeFailedClonePressure { public int $value; + public int $padding; } function forceFailedCloneCollection(): void diff --git a/tests/compiler/native-class/failed-lifecycle-escape.phpt b/tests/compiler/native-class/failed-lifecycle-escape.phpt index 2cd7e61c..c8c4ffdf 100644 --- a/tests/compiler/native-class/failed-lifecycle-escape.phpt +++ b/tests/compiler/native-class/failed-lifecycle-escape.phpt @@ -68,6 +68,7 @@ class NativeFailedCloneEscape class NativeFailedLifecyclePressure { public int $value; + public int $padding; } function forceNativeCollection(): void diff --git a/tests/compiler/native-class/finalizer-allocation.phpt b/tests/compiler/native-class/finalizer-allocation.phpt index 82cef22e..5737c553 100644 --- a/tests/compiler/native-class/finalizer-allocation.phpt +++ b/tests/compiler/native-class/finalizer-allocation.phpt @@ -28,6 +28,7 @@ class NativeFinalizerCreator class NativeFinalizerFiller { public int $value; + public int $padding; } function main(): void diff --git a/tests/compiler/native-class/finalizer-inheritance-exception.phpt b/tests/compiler/native-class/finalizer-inheritance-exception.phpt index 3efb5e6b..81a04edb 100644 --- a/tests/compiler/native-class/finalizer-inheritance-exception.phpt +++ b/tests/compiler/native-class/finalizer-inheritance-exception.phpt @@ -28,6 +28,7 @@ class NativeThrowingFinalizerChild extends NativeThrowingFinalizerBase class NativeFinalizerPressureObject { public int $value; + public int $padding; } function collectThrowingFinalizer(): void diff --git a/tests/compiler/native-class/gc-threshold.phpt b/tests/compiler/native-class/gc-threshold.phpt index 1ce2d4c3..3327cc5a 100644 --- a/tests/compiler/native-class/gc-threshold.phpt +++ b/tests/compiler/native-class/gc-threshold.phpt @@ -6,6 +6,12 @@ Native class: long-running allocation triggers automatic tracing collection #[Native] class NativeGcThresholdValue { + // Keep the pressure in the object payload so this test does not depend on + // the implementation size of the hidden Native GC header. + public int $padding1; + public int $padding2; + public int $padding3; + public function __destruct() { global $nativeGcFinalized; diff --git a/tests/compiler/native-class/lifecycle-exceptions.phpt b/tests/compiler/native-class/lifecycle-exceptions.phpt index 28a083e4..910a8e18 100644 --- a/tests/compiler/native-class/lifecycle-exceptions.phpt +++ b/tests/compiler/native-class/lifecycle-exceptions.phpt @@ -66,6 +66,7 @@ class NativeThrowingFinalizer class NativeLifecycleFiller { public int $value; + public int $padding; } function allocateUntilFinalizerRuns(): void