Skip to content

Commit a3ffe26

Browse files
committed
Deploying to gh-pages from @ 0434204 🚀
1 parent 2073f99 commit a3ffe26

File tree

4 files changed

+72
-21
lines changed

4 files changed

+72
-21
lines changed

_sources/php7/internal_types/functions/callables.rst.txt

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,19 @@ Let detail the various FCC fields:
8686
.. warning:: Prior to PHP 7.3.0 there existed an ``initialized`` field. Now an FCC is considered initialized when
8787
``function_handler`` is set to a non-null pointer.
8888

89+
.. note:: As of PHP 8.3.0, the FCC holds a ``closure`` field and a dedicated API to handle storing userland callables.
90+
This new API is described below.
91+
8992
The *only* case where an FCC will be uninitialized is if the function is a trampoline, i.e. when the method
9093
of a class does not exist but is handled by the magic methods ``__call()``/``__callStatic()``.
9194
This is because a trampoline is freed by ZPP as it is a newly allocated ``zend_function`` struct with the
9295
op array copied, and is freed when called. To retrieve it manually use ``zend_is_callable_ex()``.
9396

9497
.. warning:: It is not sufficient to just store the FCC to be able to call a user function at a later stage.
95-
If the callable zval from the FCI is an object (because it has an ``__invoke`` method, is a ``Closure``,
96-
or a trampoline) then a reference to the ``zend_object`` must also be stored, the refcount incremented,
97-
and released as needed. Moreover, if the callable is a trampoline the ``function_handler`` must be copied
98-
to be persisted between calls (see how SPL implements the storage of autoloading functions).
98+
If the callable zval from the FCI is an object (because it has an ``__invoke`` method, is a ``Closure``,
99+
or a trampoline) then a reference to the ``zend_object`` must also be stored, the refcount incremented,
100+
and released as needed. Moreover, if the callable is a trampoline the ``function_handler`` must be copied
101+
to be persisted between calls (see how SPL implements the storage of autoloading functions).
99102

100103
.. note:: To determine that two user functions are equal comparing the ``function_handler``, ``object``,
101104
``called_scope``, ``calling_scope``, and the pointer to the ``zend_object`` for closures is generally sufficient.
@@ -108,10 +111,6 @@ op array copied, and is freed when called. To retrieve it manually use ``zend_is
108111
Moreover, if a reference to the closure is kept, this must be called *prior* to freeing the closure,
109112
as the trampoline will partially refer to a ``zend_function *`` entry in the closure CE.
110113

111-
..
112-
This API is still being worked on and won't be usable for a year
113-
note:: As of PHP 8.3.0, the FCC holds a ``closure`` field and a dedicated API to handle storing userland callables.
114-
115114
Zend Engine API for callables
116115
-----------------------------
117116

@@ -120,23 +119,18 @@ We will describe the various APIs needed to deal with callables in PHP.
120119

121120
First of all, to check if an FCI is initialized use the ``ZEND_FCI_INITIALIZED(fci)`` macro.
122121

123-
.. And, as of PHP 8.3.0, the ``ZEND_FCC_INITIALIZED(fcc)`` macro to check if an FCC is initialized.
124-
125122
If you have a correctly initialized and set up FCI/FCC pair for a callable you can call it directly by using the
126123
``zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache)`` function.
127124

128125
.. warning:: The ``zend_fcall_info_arg*()`` and ``zend_fcall_info_call()`` APIs should not be used.
129126
The ``zval *args`` parameter does *not* set the ``params`` field of the FCI directly.
130-
Instead it expect it to be a PHP array (IS_ARRAY zval) containing positional arguments, which will be reallocated
131-
into a new C array. As the ``named_params`` field accepts positional arguments, it is generally better to simply
132-
assign the HashTable pointer of this argument to this field.
127+
Instead it expect it to be a PHP array (``IS_ARRAY`` zval) containing positional arguments,
128+
which will be reallocated into a new C array.
129+
As the ``named_params`` field accepts positional arguments, it is generally better to simply
130+
assign the ``HashTable`` pointer of this argument to this field.
133131
Moreover, as arguments to a userland call are predetermined and stack allocated it is better to assign the
134132
``params`` and ``param_count`` fields directly.
135133

136-
..
137-
note:: As of PHP 8.3.0, the ``zend_call_function_with_return_value(*fci, *fcc, zval *retval)`` function has
138-
been added to replace the usage of ``zend_fcall_info_call(fci, fcc, retval, NULL)``.
139-
140134
In the more likely case where you just have a callable zval, you have the choice of a couple different options
141135
depending on the use case.
142136

@@ -176,3 +170,30 @@ functions::
176170
And specific parameter number variations for the latter.
177171

178172
.. note:: If you want to call a method on an object if it exists use the ``zend_call_method_if_exists()`` function.
173+
174+
New FCI/FCC API in PHP 8.3.0
175+
----------------------------
176+
177+
PHP 8.3.0 added some new APIs to improve the handling and storage of FCCs and userland callables.
178+
This was achieved by adding the ``closure`` field to the FCC.
179+
180+
First of all a new ``ZEND_FCC_INITIALIZED(fcc)`` macro to check if an FCC is initialized was added,
181+
this is helper similar to the ``ZEND_FCI_INITIALIZED(fci)`` macro.
182+
183+
The ``zend_fcc_addref()`` and ``zend_fcc_dup()`` functions will do all the necessary reference increments
184+
to safely store an FCC in an internal object.
185+
The ``zend_fcc_equals()`` function, can be used if two FCCs are equal or not, which also supports trampolines.
186+
The ``zend_fcc_dtor()`` function must be used when releasing an FCC that was copied for internal storage.
187+
188+
If an internal object stores an FCC the ``get_gc`` object handler must be defined,
189+
and add it to the GC buffer via ``zend_get_gc_buffer_add_fcc()``.
190+
191+
The ``zend_get_callable_zval_from_fcc()`` function will create a callable zval that can be returned to userland.
192+
193+
When calling a stored FCC the
194+
``void zend_call_known_fcc(zend_fcall_info_cache *fcc, zval *retval_ptr, uint32_t param_count, zval *params, HashTable *named_params)``
195+
should be used, as it will duplicate the op array of a trampoline.
196+
The remaining parameters will be used to construct the FCI.
197+
198+
.. note:: The ``zend_call_function_with_return_value(*fci, *fcc, zval *retval)`` function was also added in PHP 8.3.0
199+
to replace the usage of ``zend_fcall_info_call(fci, fcc, retval, NULL)``.

php7/internal_types/functions.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ <h1>Functions<a class="headerlink" href="#functions" title="Link to this heading
4848
<li class="toctree-l2"><a class="reference internal" href="functions/callables.html#structure-of-zend-fcall-info">Structure of <code class="docutils literal notranslate"><span class="pre">zend_fcall_info</span></code></a></li>
4949
<li class="toctree-l2"><a class="reference internal" href="functions/callables.html#structure-of-zend-fcall-info-cache">Structure of <code class="docutils literal notranslate"><span class="pre">zend_fcall_info_cache</span></code></a></li>
5050
<li class="toctree-l2"><a class="reference internal" href="functions/callables.html#zend-engine-api-for-callables">Zend Engine API for callables</a></li>
51+
<li class="toctree-l2"><a class="reference internal" href="functions/callables.html#new-fci-fcc-api-in-php-8-3-0">New FCI/FCC API in PHP 8.3.0</a></li>
5152
</ul>
5253
</li>
5354
</ul>

php7/internal_types/functions/callables.html

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,11 @@ <h2>Structure of <code class="docutils literal notranslate"><span class="pre">ze
121121
<p>Prior to PHP 7.3.0 there existed an <code class="docutils literal notranslate"><span class="pre">initialized</span></code> field. Now an FCC is considered initialized when
122122
<code class="docutils literal notranslate"><span class="pre">function_handler</span></code> is set to a non-null pointer.</p>
123123
</div>
124+
<div class="admonition note">
125+
<p class="admonition-title">Note</p>
126+
<p>As of PHP 8.3.0, the FCC holds a <code class="docutils literal notranslate"><span class="pre">closure</span></code> field and a dedicated API to handle storing userland callables.
127+
This new API is described below.</p>
128+
</div>
124129
<p>The <em>only</em> case where an FCC will be uninitialized is if the function is a trampoline, i.e. when the method
125130
of a class does not exist but is handled by the magic methods <code class="docutils literal notranslate"><span class="pre">__call()</span></code>/<code class="docutils literal notranslate"><span class="pre">__callStatic()</span></code>.
126131
This is because a trampoline is freed by ZPP as it is a newly allocated <code class="docutils literal notranslate"><span class="pre">zend_function</span></code> struct with the
@@ -160,9 +165,10 @@ <h2>Zend Engine API for callables<a class="headerlink" href="#zend-engine-api-fo
160165
<p class="admonition-title">Warning</p>
161166
<p>The <code class="docutils literal notranslate"><span class="pre">zend_fcall_info_arg*()</span></code> and <code class="docutils literal notranslate"><span class="pre">zend_fcall_info_call()</span></code> APIs should not be used.
162167
The <code class="docutils literal notranslate"><span class="pre">zval</span> <span class="pre">*args</span></code> parameter does <em>not</em> set the <code class="docutils literal notranslate"><span class="pre">params</span></code> field of the FCI directly.
163-
Instead it expect it to be a PHP array (IS_ARRAY zval) containing positional arguments, which will be reallocated
164-
into a new C array. As the <code class="docutils literal notranslate"><span class="pre">named_params</span></code> field accepts positional arguments, it is generally better to simply
165-
assign the HashTable pointer of this argument to this field.
168+
Instead it expect it to be a PHP array (<code class="docutils literal notranslate"><span class="pre">IS_ARRAY</span></code> zval) containing positional arguments,
169+
which will be reallocated into a new C array.
170+
As the <code class="docutils literal notranslate"><span class="pre">named_params</span></code> field accepts positional arguments, it is generally better to simply
171+
assign the <code class="docutils literal notranslate"><span class="pre">HashTable</span></code> pointer of this argument to this field.
166172
Moreover, as arguments to a userland call are predetermined and stack allocated it is better to assign the
167173
<code class="docutils literal notranslate"><span class="pre">params</span></code> and <code class="docutils literal notranslate"><span class="pre">param_count</span></code> fields directly.</p>
168174
</div>
@@ -207,6 +213,29 @@ <h2>Zend Engine API for callables<a class="headerlink" href="#zend-engine-api-fo
207213
<p>If you want to call a method on an object if it exists use the <code class="docutils literal notranslate"><span class="pre">zend_call_method_if_exists()</span></code> function.</p>
208214
</div>
209215
</section>
216+
<section id="new-fci-fcc-api-in-php-8-3-0">
217+
<h2>New FCI/FCC API in PHP 8.3.0<a class="headerlink" href="#new-fci-fcc-api-in-php-8-3-0" title="Link to this heading"></a></h2>
218+
<p>PHP 8.3.0 added some new APIs to improve the handling and storage of FCCs and userland callables.
219+
This was achieved by adding the <code class="docutils literal notranslate"><span class="pre">closure</span></code> field to the FCC.</p>
220+
<p>First of all a new <code class="docutils literal notranslate"><span class="pre">ZEND_FCC_INITIALIZED(fcc)</span></code> macro to check if an FCC is initialized was added,
221+
this is helper similar to the <code class="docutils literal notranslate"><span class="pre">ZEND_FCI_INITIALIZED(fci)</span></code> macro.</p>
222+
<p>The <code class="docutils literal notranslate"><span class="pre">zend_fcc_addref()</span></code> and <code class="docutils literal notranslate"><span class="pre">zend_fcc_dup()</span></code> functions will do all the necessary reference increments
223+
to safely store an FCC in an internal object.
224+
The <code class="docutils literal notranslate"><span class="pre">zend_fcc_equals()</span></code> function, can be used if two FCCs are equal or not, which also supports trampolines.
225+
The <code class="docutils literal notranslate"><span class="pre">zend_fcc_dtor()</span></code> function must be used when releasing an FCC that was copied for internal storage.</p>
226+
<p>If an internal object stores an FCC the <code class="docutils literal notranslate"><span class="pre">get_gc</span></code> object handler must be defined,
227+
and add it to the GC buffer via <code class="docutils literal notranslate"><span class="pre">zend_get_gc_buffer_add_fcc()</span></code>.</p>
228+
<p>The <code class="docutils literal notranslate"><span class="pre">zend_get_callable_zval_from_fcc()</span></code> function will create a callable zval that can be returned to userland.</p>
229+
<p>When calling a stored FCC the
230+
<code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">zend_call_known_fcc(zend_fcall_info_cache</span> <span class="pre">*fcc,</span> <span class="pre">zval</span> <span class="pre">*retval_ptr,</span> <span class="pre">uint32_t</span> <span class="pre">param_count,</span> <span class="pre">zval</span> <span class="pre">*params,</span> <span class="pre">HashTable</span> <span class="pre">*named_params)</span></code>
231+
should be used, as it will duplicate the op array of a trampoline.
232+
The remaining parameters will be used to construct the FCI.</p>
233+
<div class="admonition note">
234+
<p class="admonition-title">Note</p>
235+
<p>The <code class="docutils literal notranslate"><span class="pre">zend_call_function_with_return_value(*fci,</span> <span class="pre">*fcc,</span> <span class="pre">zval</span> <span class="pre">*retval)</span></code> function was also added in PHP 8.3.0
236+
to replace the usage of <code class="docutils literal notranslate"><span class="pre">zend_fcall_info_call(fci,</span> <span class="pre">fcc,</span> <span class="pre">retval,</span> <span class="pre">NULL)</span></code>.</p>
237+
</div>
238+
</section>
210239
</section>
211240

212241

searchindex.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)