Skip to content

Fix interface table hash-multiplier selection, and grow the multiplier pool#11335

Merged
riknoll merged 3 commits into
microsoft:masterfrom
humanapp:eanders/iface-hash-multiplier-fix
May 29, 2026
Merged

Fix interface table hash-multiplier selection, and grow the multiplier pool#11335
riknoll merged 3 commits into
microsoft:masterfrom
humanapp:eanders/iface-hash-multiplier-fix

Conversation

@humanapp
Copy link
Copy Markdown
Contributor

Hey guys it's eanders! I have a compiler bugfix + an optimization here for your consideration. It is very safe.

Summary

Interface dispatch table packing is done using a pow2 algorithm. computeHashMultiplier (in pxtcompiler/emitter/hexfile.ts) sizes each class's dispatch table by searching for the smallest power-of-two for which some candidate hash multiplier can place all of the class's members within 3 vtLookups probes. A comparison bug was causing a failing multiplier to be treated as better than a succeeding one, which made the search needlessly double many tables to the next power of two, leading to large voids in the resulting hex file.

This PR contains two commits:

  1. Fix the selection comparison so only successful placements are considered.
  2. Enlarge the candidate multiplier pool, and move it into its own file.

The change is purely a size optimization, it does not alter program behavior. I've been testing on microcode -- a relatively large and complex app. On that build, it reduces the hex file size by ~7.6 KB.

The bug

The compiler picks a size for each class's dispatch table by trying every hash multiplier and keeping the best one. The bug made a failed multiplier look better than a successful one, so one failure erased the memory of a multiplier that had already worked. A table size was only kept if the very last multiplier tried happened to succeed, otherwise the table was needlessly doubled, even though an earlier one fit fine.

The fix

The fix was to simply ignore failures and remember only successes with a better fit than the last. Among multipliers that fully placed the class's members: keep the one with the fewest collisions, and accept the smallest size at which any succeeds.

Why this is safe

The format of the emitted table is preserved. It's the same packing algorithm, just a bit more efficient. The only difference is the choice of valid hash multiplier.

Second commit: Enlarge the prime pool

With the selection bug fix in place, adding more multiplier candidates increases the search space for finding a more optimal hash. This is how I found the bug, in fact. I was adding more primes to increase the search space, and it ended up inexplicably increasing the hex file size. Increasing the space made it more likely it would fail into table-doubling.

Measured impact

The microcode build I was testing with had 1023 interface members. Here are the resulting dispatch table utilization measurements:

state member count table slots utilization
baseline 1023 3234 32%
+ selection fix 1023 2426 42%
+ larger pool 1023 1882 54%

cc: @thomasjball

@humanapp
Copy link
Copy Markdown
Contributor Author

@microsoft-github-policy-service agree

@Jaqster
Copy link
Copy Markdown
Member

Jaqster commented May 28, 2026

Eric!!! So good to see you back in this repo! We miss you!

Copy link
Copy Markdown
Member

@riknoll riknoll left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!

@riknoll riknoll enabled auto-merge (squash) May 29, 2026 17:22
@riknoll riknoll merged commit a2eabbe into microsoft:master May 29, 2026
12 checks passed
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.

3 participants