Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for user atoms and namecalls #48

Merged
merged 1 commit into from
Jan 17, 2024

Conversation

nurpax
Copy link
Contributor

@nurpax nurpax commented Jan 15, 2024

Add support for Luau's faster method invocation protocol that uses a concept called NAMECALL.

When Luau invokes a method with NAMECALL, it sets an interned string pointer into the Lua state struct which can then be quickly turned into either a string or a 16-bit index, for dispatching a user method quickly. This way method calls do not need to lookup methods from a Lua table nor is there any need to do any expensive string comparisons.

Expose some more Luau API to make the above possible. Also adds a couple of convenience functions like checkVector and typeError (used to implement checkVector, already in lua 5.4 backend).

setReadonly is something the Luau "conformance tests" were using so I added an API for it too. I think it freezing tables to be read-only enables some VM optimizations, but I'm not sure what exactly. It doesn't seem to affect the behavior of my tests in this patch.

The namecallatom is a little tricky to understand as I couldn't find good docs for it. But I think it's usage is fairly apparent from the namecall test.

I used the same types as in the underying API which means the atom pointers in toStringAtom and namecallAtom are *c_int. I guess that's required for the Zig->C calling convention but c_ints are not otherwise used in the API so feel a little out of place.

src/libluau.zig Outdated Show resolved Hide resolved
Copy link
Owner

@natecraddock natecraddock left a comment

Choose a reason for hiding this comment

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

The code looks good, but I still don't fully understand the use of user atoms and namecalls, so thank you for working on this 😂

src/libluau.zig Outdated Show resolved Hide resolved
src/libluau.zig Outdated Show resolved Hide resolved
Namecall is a mechanism in Luau to speed up method invocations.
The basic idea is that the VM can cache method names (strings)
to integer indices the first time it executes a method call.
At this point it calls the "user atom callback" with the string.
The user callback is responsible for mapping the method string
to a unique 16-bit index that's returned to the VM.

Next time the VM encounters the same string, it already knows
how to map the string to an index as, so it will reuse the user's
16-bit index.

The above is the mechanism for quickly resolving function name
strings to integers.  The other part of the API is using the
indices.  This part is the __namecall function that's attached
to a (userdata) object's metatable.  On a method call, the VM
knows that the userdata has a registered __namecall, and calls
that to dispatch to the actual user's native function to handle
the native method.  The namecall dispatch routine uses lua.namecallAtom()
to retrieve the method name/index, which is used to select which
actual native method is called.

It's not very simple but it should be fast as the VM doesn't
need to do a string->function hash table lookup on every
method invocation.

I'm not 100% sure of the details, but I suspect that the VM may
also patch the bytecode (or some internal representation of it)
directly with the namecall indices rather than looking them up
from some string hash table.
@nurpax
Copy link
Contributor Author

nurpax commented Jan 17, 2024

but I still don't fully understand the use of user atoms and namecalls

Heh, it is a little complicated. It took some reading and thinking for me to figure it out too. I tried to explain the concept in the (updated) commit message. I did a bit of educated guessing in that writing, but it's probably quite accurate. Hope it makes more sense now. The test case for "namecall" is probably the best document on how to use it.

@natecraddock natecraddock merged commit 31721fe into natecraddock:main Jan 17, 2024
3 checks passed
@nurpax nurpax deleted the namecallatom branch January 17, 2024 16:34
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