add the extension api - #58
Merged
Merged
Conversation
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.
Third-party extensions, written in C against
include/zphp_extension.h, can now register functions, classes with native methods and constants, interfaces, exception classes, global constants, ini defaults, and resource types with destructors. The same source builds as a shared library (zphp --extension=PATH, orZPHP_EXTENSION_DIR) or gets compiled into zphp (zig build -Dextension=path.c). Values cross the boundary as opaque handles, and the API is a table of function pointers handed to the extension's entry point, so extensions never link against zphp symbols and the runtime's internals can keep changing. An ABI version in the descriptor rejects mismatches at load time, as do duplicate names, conflicts with builtins, a missing entry point, and a failing module init.A PHP call reaches an extension through the ordinary native table and a resolved trampoline. With 2M calls each in ReleaseFast, a builtin
abs()takes 210ms, an extension function 227ms, and a PHP function 68ms; the trampoline is about 8ns per call.Extensions get module, worker, and request lifecycle hooks plus a request-local and a worker-local data slot per VM. Resources are destroyed on unset, scope exit, exception unwinding, request end, and process exit.
tests/extensions/runbuilds the demo extension withzig cc, checks every API path and every rejection, driveszphp servefor request isolation and resource cleanup over repeated requests, and withSTATIC=1builds a zphp with the demo compiled in and runs the same script. A newextensionsCI job runs both.Two fixes came out of the serve tests. Every served request saw
DateTime::ATOMas an empty string and enum cases such asRoundingMode::HalfEvenas null, because the per-request reset cleared the constants of builtin classes as well as user classes; builtin classes now keep their state across resets, and the serve test asserts it. And the per-VM extension state lives on the heap-allocated inline cache rather than on the VM struct: adding three fields toVMshifted field offsets and cost 36% on the closures micro and 22% on loops in a paired run, which moving them undid.Paired micros against main (
make bench-compare --micro, min of 7 interleaved runs, ms):Closes #23.