feat(compiler): implement PackedArray reference semantics from semantics to C codegen - #82
Merged
Merged
Conversation
- Add terminal DIRECT_SLOT commit steps when mutating calls use a local snapshot - Preserve alias-published receiver behavior and gate writeback for supported local slots - Validate writable-route step shape and cover CFG, lowering, and runtime behavior
- Specify Variant-backed storage to match Godot's shared mutation semantics - Document ABI boundaries, iteration, conversions, operators, and property behavior - Define interpreter-based behavior goldens and phased implementation coverage
- Add a Godot interpreter and gdcc dual-run probe harness with golden comparisons - Track probe coverage and phase-based enablement, including compile-blocked cases - Record measured PackedArray behavior and update the implementation plan
- Add Variant-backed helpers for shared aliases and explicitly whitelisted conversions - Resolve packed-array internal getters per translation unit and fail fast on invalid use - Add Zig-gated runtime coverage for identity, conversion boundaries, and failure paths - Record Phase B implementation and validation results
- Store PackedArray values as shared Variant holders and route copies, casts, and destruction through the packed-reference helpers - Adapt builtin calls, operators, constructors, and ptrcall boundaries to the native packed-array ABI - Make packed-array iteration observe live mutations without caching element pointers - Add codegen and runtime coverage for identity, conversions, ABI isolation, and iteration - Record Phase C implementation and validation results
- Skip redundant snapshot and static-property commits for shared PackedArray values - Prevent mutating calls on engine-property copies from persisting, while retaining assignment and script-property writeback - Enable packed-array mutation through static properties and lambda captures - Cover all ten packed-array types and promote deferred interpreter comparison probes
- Stub and register `variant_new_nil` so iterator setup never destroys uninitialized Variant storage
- Require dual-run tests to match the full golden matrix and add an independent inventory check - Expand probes for control flow, return-value sharing, engine method boundaries, and PackedStringArray mutation - Add runtime and codegen coverage for call_func identity and ptrcall ABI boundaries - Align type, ownership, runtime, and backend documentation with the Variant-backed storage model
- Replace the phased plan with a maintained source of truth for implemented storage, ABI, ownership, and conversion contracts - Synchronize related compiler docs and code/test references with the finalized documentation - Keep the interpreter comparison goldens and coverage inventory aligned with the documented behavior
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Align Packed*Array storage and operation semantics with the Godot 4.5 interpreter's reference (shared-identity) semantics across frontend and backend, replacing the old by-value struct (COW) storage model with Variant-backed storage.
What changed
godot_Variant; identity flows throughgodot_new_Variant_with_Variant, and raw struct<->Variant crossing is restricted to the whitelisted helpers ininclude_451/gdcc/gdcc_packed_ref.h(PackedRefCNames).wrap_temp(PackedNativeAbiCallSupport); engine method ptrcall helpers materialize packed args into helper-owned slots and wrap packed returns;call_funcwrappers preserve identity while ptrcall wrappers intentionally isolate it.intrinsic/for_packed_array_iter.h,GdccForPackedArrayIterType) hold a sharing Variant holder and re-check live size per access — appended elements are visited, shrink/realloc stays safe.FrontendWritableTypeWritebackSupport,FrontendCfgGraphBuilder,FrontendLoweringBodyInsnPass).packed_ref_probes.gd, golden locked by Godot 4.5.2), Godot-independent coverage inventory anchor, fake-engine runtime smoke tests, codegen text anchors, and test_suite end-to-end resources (packed_call_func_identity.gd,packed_ref_full_usage.gd).doc/module_impl/backend/packed_array_implementation.md; synchronizedgdcc_c_backend.md,gdcc_low_ir.md,gdcc_type_system.md,gdcc_runtime_lib.md,gdcc_ownership_lifecycle_spec.md; code/test comments made self-contained and English-only.Why
godot_Packed*Arraystorage copied at the C++Vectorlayer and detached on first write, diverging from the interpreter: local aliases, parameter mutations, livefor-initeration, and Variant round-trips were not shared.Affected packages/files
src/main/java/gd/script/gdcc/backend/c/**(CGenHelper,PackedRefCNames,PackedNativeAbiCallSupport,CBuiltinBuilder,IndexStoreInsnGen,CBodyBuilder,CHrxIdentityCatalog, ...)src/main/java/gd/script/gdcc/frontend/**(writeback route support, CFG builder, lowering pass)src/main/c/codegen/include_451/gdcc/gdcc_packed_ref.h,intrinsic/for_packed_array_iter.h,template_451/entry.h.ftlsrc/test/resources/packed_ref_semantics/**,src/test/java/gd/script/gdcc/backend/c/build/packedref/**,src/test/test_suite/unit_test/**doc/module_impl/backend/packed_array_implementation.mdand the five compiler spec docsValidation
script/run-gradle-targeted-tests.sh --tests "PackedArrayReferenceSemanticsDualRunTest,PackedRefSemanticsGoldenInventoryTest,ProbeOutputTest,ProbeGoldenComparisonTest,CConstructInsnGenEngineTest,COperatorInsnGenTest,CConstructInsnGenTest,PackedRefStorageModelSmokeTest,BuiltinCastInsnGenTest,CPackUnpackVariantInsnGenTest,IndexStoreInsnGenTest,IndexStoreInsnGenEngineTest,GdccPackedRefRuntimeSmokeTest,CallMethodInsnGenTest,ExplicitCastSupportTest,CCodegenTest,FrontendLoweringBodyInsnPassTest"./gradlew clean build --no-daemon --info --console=plainResult:
BUILD SUCCESSFUL— 4644 tests, 0 failures (includes Godot 4.5.2 + Zig gated dual-run and integration suites; interpreter and compiled outputs match the full golden line-by-line).Risks / Notes
call_func(Variant ABI) and preserve identity; locked by runtime and codegen-anchor tests.variant_get_ptr_internal_getteris a semi-internal GDExtension API (also used by godot-cpp); guarded by init-time availability checks with fail-fast.Key behaviors covered (Optional)
+=rebinding,duplicate()independence, content equality and Dictionary key hashing, same-familyasCOW copy with fresh identity.StreamPeerBuffer.set/get_data_array), PackedStringArray mutation/equality.Diff stats (Optional)
Breaking changes (Optional)
poly.polygon.push_back(x)) no longer persist; the interpreter also discards them. Assignment routes on the same property still persist.godot_Packed*Arraytogodot_Variant(internal only; hot-reload fingerprints invalidate old connections fail-closed).Related docs (Optional)
doc/module_impl/backend/packed_array_implementation.mddoc/gdcc_c_backend.md,doc/gdcc_low_ir.md,doc/gdcc_type_system.md,doc/gdcc_runtime_lib.md,doc/gdcc_ownership_lifecycle_spec.md