feat: table struct specialization with spec function pointers#221
Merged
Conversation
Add table struct specialization optimization for tables with known field shapes. The optimization embeds get/set function pointers into VarTable that transparently handle fast-path access to specialized fields. Key changes: - VarTable gains spec_get/spec_set function pointers - SET_TABLE_SPEC macro allocates spec struct and registers function pointers - Generated spec get/set functions check key against known fields, fall back to hash table on miss - FlGetTableStrId/FlSetTableStrId dispatch through spec functions - FlGetTable/FlSetTable also dispatch for VAR_STRING/VAR_STRINGID keys - CompileTableconstructor generates spec typedef + get/set functions - FlSpecPtr/FlSpecGet macros for direct compile-time-known access
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #221 +/- ##
==========================================
- Coverage 96.76% 96.65% -0.12%
==========================================
Files 67 67
Lines 14151 14488 +337
==========================================
+ Hits 13693 14003 +310
- Misses 458 485 +27 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
- Add spec_field_names_ map to track which fields are in each spec struct - IsSpecField() check before using FlSpecPtr/FlSpecGet fast paths - Prevents generating spec access for non-spec fields (e.g. t["y"] when y is not in spec) - Added 10 test cases: single field, write-then-read, pairs iteration, dynamic key access, function parameter, multiple tables, nested tables, three fields, dynamic write+read fallback
- Split test_table_struct_spec.lua into 10 separate test files: test_spec_basic, test_spec_single_field, test_spec_write_multi, test_spec_pairs, test_spec_dynamic_key, test_spec_func_param, test_spec_multi_tables, test_spec_nested, test_spec_dynamic_write, test_global_table_spec - Each test file has a single focused test case - Added test_global_table_spec to verify global constant tables are specialized - Added IsSpecField check to prevent FlSpecPtr/FlSpecGet for non-spec fields - Fixed FAKELUA_SET_TABLE spec path to only trigger for known spec fields
- Convert if-else chain to switch-case with all SyntaxTreeType values
- Unhandled types grouped at bottom with return (no-op)
- ThrowFakeluaException on unhandled type after switch
- Fix test_spec_nested assertion: inner table {v=5} is also specialized
Runtime VAR_STRING keys have different VarString pointers than compile-time const string IDs, so str_id comparison alone fails. memcmp fallback handles this case correctly.
…rite Removing dual-write breaks pairs iteration and table dump because hash is empty. Need to implement spec_iter function pointer first to iterate spec fields, then hash fields. Current dual-write is temporary until iter is implemented.
- VarTable gains spec_keys/spec_vals/spec_count for iteration support - GET_TABLE_ENTRY iterates spec fields first, then hash - VarTable::Get checks spec fields before hash - VarTable::Size returns count_ + spec_count - VarToVi iterates spec then hash for table dump - spec_keys/spec_vals allocated via FakeluaAlloc (const during init) - No more dual-write: spec fields only in spec struct + spec_keys/spec_vals
…Table - spec_get/spec_set now accept CVar k (not int64_t str_id) - FlGetTable/FlSetTable/FlGetTableStrId/FlSetTableStrId call spec functions internally - Generated code uses standard FlGetTable/FlSetTable, no FlSpecPtr/FlSpecGet macros - spec_get handles VAR_STRINGID (fast str_id compare) and VAR_STRING (memcmp) separately - Removed FlSpecPtr/FlSpecGet macros - spec optimization is now fully transparent
Generated code now much cleaner: - SET_TABLE_SPEC handles table + spec + keys/vals allocation - No separate CVar* declarations or FakeluaAlloc calls in function body - Standard FlSetTableStrId/FlGetTableStrId for all read/write
… in generated code - spec_get/spec_set signature: (VarTable*, CVar k, bool *finish) - Hit: set *finish=true, return value - Miss: set *finish=false, caller falls back to hash - FlGetTableStrId/FlSetTableStrId check finish flag, fallback if needed - No Raw functions needed in spec code path
…ain functions Raw functions were only used as fallback paths. Now inlined directly into FlGetTableStrId/FlSetTableStrId after spec miss check. Cleaner code with no extra function layers.
…d_xxx Each specialized table now has its own FlGetTableStrId_xxx and FlSetTableStrId_xxx functions, making the naming consistent with the standard table access functions they specialize.
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
Design
VarTable gains
spec_getandspec_setfunction pointers. When a table is created with only named fields ({x=10, y=20}),SET_TABLE_SPECallocates a typed spec struct and registers generated get/set functions. These functions compare incoming keys (both str_id pointer and content-based) against known fields — hit returns from spec directly, miss falls back to hash table.External code calling normal table interfaces (FlGetTableStrId etc.) automatically benefits. Code that knows the spec type at compile time can use FlSpecPtr/FlSpecGet for even faster access without function pointer indirection.
Test
All 726 tests pass. New test
jitter.table_struct_specvalidates the optimization.