feat(observer): allow zend_extension registration for low level function#678
Merged
ptondereau merged 1 commit intomasterfrom Apr 15, 2026
Merged
feat(observer): allow zend_extension registration for low level function#678ptondereau merged 1 commit intomasterfrom
ptondereau merged 1 commit intomasterfrom
Conversation
ptondereau
commented
Feb 13, 2026
Coverage Report for CI Build 24467964023Coverage decreased (-0.2%) to 65.895%Details
Uncovered Changes
Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
5026489 to
6c49878
Compare
|
| Branch | feat/zend-extension |
| Testbed | PHP 8.4.19 (cli) (built: Mar 13 2026 01:28:58) (NTS) |
⚠️ WARNING: Truncated view!The full continuous benchmarking report exceeds the maximum length allowed on this platform.
🐰 View full continuous benchmarking report in Bencher
⚠️ WARNING: No Threshold found!Without a Threshold, no Alerts will ever be generated.
Add `ModuleBuilder::zend_extension(factory)` returning a `ZendExtensionBuilder` with `hook_statements()`, `hook_fcalls()`, and `hook_op_array_compile()` opt-ins. Only opted-in hooks are wired to PHP and only their matching ZEND_COMPILE_* flags are set, so unused hooks cost nothing at compile time. Compiler flags are also re-asserted in `on_activate` for ZTS worker threads. Internal wiring now goes through `CompilerGlobals::get_mut()` and a pub(crate) `zend::register_extension()` helper rather than raw ffi from the feature module.
6c49878 to
480e5d9
Compare
|
| Branch | feat/zend-extension |
| Testbed | PHP 8.4.20 (cli) (built: Apr 11 2026 00:52:25) (NTS) |
⚠️ WARNING: Truncated view!The full continuous benchmarking report exceeds the maximum length allowed on this platform.
🐰 View full continuous benchmarking report in Bencher
⚠️ WARNING: No Threshold found!Without a Threshold, no Alerts will ever be generated.
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.
Description
Closes the API gap for building
zend_extension-style profilers (APM, coverage tools, line-level timers) on top of ext-php-rs. Until now the crate only exposed the Observer API (function-call level). This PR adds dual registration so a single extension can also hook the engine's compile-time and per-statement callbacks.What you get
module .zend_extension(|| MyProfiler::new()) .hook_statements() .hook_fcalls() .finish()The handler trait carries all hooks with default no-op implementations; the builder decides which ones the engine will actually call. Enabling a hook also flips the matching PHP compiler flag so the right opcodes get emitted.
Why the opt-in
hook_statements()andhook_fcalls()tell the PHP engine to emit extra opcodes in every compiled script (ZEND_EXT_STMT,ZEND_EXT_FCALL_BEGIN/END). Paying that tax by default would slow every PHP script, even when your profiler doesn't need the data. The builder makes the trade-off explicit.hook_op_array_compile()has no compile-time cost because its flag is already set by PHP's defaults; it only controls whether the dispatcher is registered.ZTS
Flags are re-asserted in
on_activate, which is per-request-per-thread, so worker threads created after MINIT still get them. Scripts pre-compiled by opcache before a thread's first activation may miss hooks; load the extension viazend_extension=...inphp.iniif you need 100% coverage there.Docs
Guide section at
guide/src/advanced/observer.md#zend-extension-handlerrewritten. Example atexamples/zend_extension.rsupdated. All trait methods renamed toon_*prefix for consistency with sibling observers.Checklist
zend_extension_handler(factory)API shipped only on this unmerged branch, no release notes or published docs referenced it.)