Skip to content

feat: table struct specialization with spec function pointers#221

Merged
esrrhs merged 17 commits into
masterfrom
feat/table-struct-spec
Jun 28, 2026
Merged

feat: table struct specialization with spec function pointers#221
esrrhs merged 17 commits into
masterfrom
feat/table-struct-spec

Conversation

@esrrhs

@esrrhs esrrhs commented Jun 27, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add table struct specialization for tables with known field shapes (all kObject fields)
  • Embed get/set function pointers into VarTable for transparent fast-path access
  • Generated spec functions check key against known fields, fall back to hash on miss
  • FlGetTableStrId/FlSetTableStrId/FlGetTable/FlSetTable all dispatch through spec
  • FlSpecPtr/FlSpecGet macros for direct compile-time-known access in CGen

Design

VarTable gains spec_get and spec_set function pointers. When a table is created with only named fields ({x=10, y=20}), SET_TABLE_SPEC allocates 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_spec validates the optimization.

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-commenter

codecov-commenter commented Jun 27, 2026

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 92.17391% with 27 lines in your changes missing coverage. Please review.
✅ Project coverage is 96.65%. Comparing base (f830c95) to head (e6f0c71).

Files with missing lines Patch % Lines
src/compile/c_gen.cpp 77.58% 26 Missing ⚠️
src/compile/type_inferencer.cpp 98.94% 1 Missing ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

esrrhs added 16 commits June 27, 2026 21:21
- 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.
@esrrhs esrrhs merged commit ce26b64 into master Jun 28, 2026
7 checks passed
@esrrhs esrrhs deleted the feat/table-struct-spec branch June 28, 2026 12:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants