Zero-cons SLOT-VALUE / SLOT-BOUNDP via the class location table - #1810
Open
dg1sbg wants to merge 1 commit into
Open
Zero-cons SLOT-VALUE / SLOT-BOUNDP via the class location table#1810dg1sbg wants to merge 1 commit into
dg1sbg wants to merge 1 commit into
Conversation
dg1sbg
force-pushed
the
pr/slot-value-zero-cons
branch
from
July 31, 2026 17:02
704789b to
1a44d75
Compare
slot-value/(setf slot-value)/slot-boundp went through the metaobject slot-definition readers (%find-slot's slot-definition-name + slot-value-using-class's slot-definition-location) -- un-optimized STANDARD-READER-METHODs on bootstrap MOP classes that cons ~96 B each (192 B/call). Route the standard case through the class's existing LOCATION-TABLE (name->location, rack slot 17 on STD-CLASS) for 0-cons access. Fast path is gated on %INSTANCE-FAST-TABLE: taken only for a CURRENT standard instance (core:instancep + instance stamp = class STAMP-FOR-INSTANCES, rack slot 18). An OBSOLETE instance (redefined class), a built-in/unfinalized class, or *OPTIMIZE-SLOT-VALUE* nil (custom slot-value-using-class) falls back to the full MOP dispatch, whose SLOT-VALUE-USING-CLASS discrimination runs the stamp check + UPDATE-INSTANCE. Reading the rack slots directly avoids the CLASS-LOCATION-TABLE reader (itself a consing metaobject reader).
dg1sbg
force-pushed
the
pr/slot-value-zero-cons
branch
from
August 13, 2026 16:35
1a44d75 to
2174fc1
Compare
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.
Removes the allocation from the standard
SLOT-VALUE/(SETF SLOT-VALUE)/SLOT-BOUNDPpath.The problem
The generic path reaches the slot through
%FIND-SLOTand the standardSLOT-VALUE-USING-CLASSmethod, both of which call the metaobject readersSLOT-DEFINITION-NAMEandSLOT-DEFINITION-LOCATION. Those are un-optimizedSTANDARD-READER-METHODs on bootstrap MOP classes, and each one allocates. For code that touches slots in a loop that is pure garbage.The change
When the receiver is a current standard instance, the name→location lookup goes straight through the class's
LOCATION-TABLEinstead of the metaobject readers, and the value is fetched withSTANDARD-LOCATION-ACCESS. The old bodies are factored out unchanged into%SLOT-VALUE-GENERIC,%SETF-SLOT-VALUE-GENERICand%SLOT-BOUNDP-GENERIC, which the fast path falls back to.The fast path is taken only when
%INSTANCE-FAST-TABLEreturns a table, which requires both:CORE:INSTANCE-STAMPequals the class'sSTAMP-FOR-INSTANCES.The second condition is the important one. An obsolete instance must not use the fast path — the generic
SLOT-VALUE-USING-CLASSdispatch is what runs the stamp check andUPDATE-INSTANCE, and skipping it would read a stale rack, silently returning wrong values for a redefined class.SLOT-MAKUNBOUNDis deliberately left on the generic path.Verification
Beyond the suite, the stamp guard was probed directly, since it is the one thing that would fail silently:
The obsolete instance is correctly refused and falls through to the generic path.
Also checked by hand: reads, writes,
SLOT-BOUNDPon bound and unbound slots,SLOT-MAKUNBOUND,SLOT-MISSING,SLOT-UNBOUND, non-instance fallback, and that binding the escape hatch toNILstill yields correct results.macOS arm64, native build, LLVM 22.1.8:
boehmboehmprecise(clean build from scratch)The four expected failures (
SBCL-CROSS-COMPILE-4,INCLUDE-LEVEL-2B,INCLUDE-LEVEL-3,TYPES-CLASSES-10) are pre-existing and unrelated; the count differs between variants only becauseboehmprecisealso runs the variant-specific snapshot tests.The
boehmpreciseresult matters for this change specifically: the fast path reads raw rack slots viaCORE:RACK-REFand hands back slot locations, so if anything there were invisible to the precise scanner it would show up under precise stack scanning and nowhere else. The stamp-guard probe above was re-run underboehmprecisewith identical results.For disclosure, both runs were made from a tree that also carried #1809 on top of
main;slot-value.lispthere is byte-identical to the commit in this PR, and #1809 touches no CLOS code.Points I'd like a maintainer's view on
The rack indices are duplicated, not derived.
+CLASS-LOCATION-TABLE-RACK-INDEX+(17) and+STAMP-FOR-INSTANCES-RACK-INDEX+(18) restate the:locationvalues declared inhierarchy.lisp. They are correct today and those:locations are explicit rather than positional, so this is a two-place edit rather than an implicit ordering dependency — but nothing enforces the correspondence, and if it ever drifts every standard instance in the image reads the wrong rack cell silently. A compile-time assertion tying the constants to the slot definitions would cost nothing; happy to add one if you want it.*OPTIMIZE-SLOT-VALUE*is not exported. It is described as the escape hatch for programs that define a customSLOT-VALUE-USING-CLASSand want it honoured, but reaching it requiresCLOS::. Should it be exported, or is internal-only intended?No benchmark is included. The motivation is allocation, and the mechanism is clear from the diff, but this PR does not ship a measurement. Say the word and I'll add one.