Update gen_stubs.php to generate C enums from internal enums, when the stub is annotated with @generate-c-enums. Enum values can be compared to the result of zend_enum_fetch_case_id(zend_object*).
The generated enums are added to separate files named {$extensionName}_decl.h, so that it's possible to include these from anywhere. _arginfo.h files would generate warnings if we tried to include them in a compilation unit that doesn't call the register_{$class} functions, for instance.
Introduce Z_PARAM_ENUM().
* Make ZEND_AST_CONST_ENUM_INIT a 4-children node
* Store enum case id in ZEND_AST_CONST_ENUM_INIT
* Store enum case id in instance
* Expose enum case_id internally
* Generate C enum for internal enums
* Introduce Z_PARAM_ENUM()
* Port extensions
* Reduce code bloat in arginfo by using specialised string releases
Comparing this patch to master (c7da728574),
with a plain configure command without any options:
```
text data bss dec hex filename
20683738 1592400 137712 22413850 156021a sapi/cli/php
20688522 1592400 137712 22418634 15614ca sapi/cli/php_old
```
We see a minor reduction of 0.023% in code size.
* Also use true for the other initialization line
* Also use specialized code for consts
Instead of
* adding a zval on the stack
* initializing it
* copying the value to the attribute
Just initialize the value directly in the zend_attribute_arg
Have each of the specialized methods for registering a constant return a
pointer to the registered constant the same way that the generic
`zend_register_constant()` function does, and use those in the generated
arginfo files to avoid needing to search for a constant that was just
registered in order to add attributes to it.
Only covers constants declared via stub files, others will be handled
separately in a later commit.
Does not include the intl extension, since that had some errors relating to the
cpp code; that extension will be updated separately.
`/./` matches all characters but newlines, so if `random_bytes`
generates a string with newlines in it, the resulting string is not
empty. Fix this by adding the `s` modifier.
On x86-64 with GCC 14.2.1:
zim_Random_Randomizer_getBytes goes from 514 to 418 bytes
zim_Random_Randomizer_getBytesFromString goes from 750 to 676 bytes
PHP Internals Book says:
> The ZVAL_DUP macro is similar to ZVAL_COPY, but will duplicate arrays, rather
> than just incrementing their refcount. If you are using this macro, you are
> almost certainly doing something very wrong.
Replace this by an explicit call to `zend_array_dup()`, as done in
`php_array_diff()`. Besides being more explicit in what is happening, this
likely also results in better assembly.
To match other capitalized strings like `ZEND_STR_UNKNOWN_CAPITALIZED` and
`ZEND_STR_ARRAY_CAPITALIZED`. Since this known string was only added in PHP
8.4, no backwards compatibility alias is needed.
When a class (or enum) has no methods, rather than using an array that only
contains `ZEND_FE_END`, use `NULL` for the functions. The implementation of
class registration for internal classes, `do_register_internal_class()` in
zend_API.c, already skips classes where the functions are `NULL`. By removing
these unneeded arrays, we can reduce the size of the header files, while also
removing an unneeded call to zend_register_functions() for each internal class
with no extra methods.
Currently, internal classes are registered with the following code:
INIT_CLASS_ENTRY(ce, "InternalClass", class_InternalClass_methods);
class_entry = zend_register_internal_class_ex(&ce, NULL);
class_entry->ce_flags |= ...;
This has worked well so far, except if InternalClass is readonly. It is because some inheritance checks are run by zend_register_internal_class_ex before ZEND_ACC_READONLY_CLASS is added to ce_flags.
The issue is fixed by adding a zend_register_internal_class_with_flags() zend API function that stubs can use from now on. This function makes sure to add the flags before running any checks. Since the new API is not available in lower PHP versions, gen_stub.php has to keep support for the existing API for PHP 8.3 and below.
To fix part of GH-15381.
gcc nor clang provides a constant to distinguish illumos and solaris
not the system provides a kernel version stamp like the BSD.
thus, we simply check the symbol and remaing purposely conservative in
the existing logic, using it only for solaris to avoid unexpected
breakages for other systems. would need a different fix for higher
branches.
Close GH-15390
This patch greatly improves the performance for the common case of using a
64-bit engine and requesting a length that is a multiple of 8.
It does so by providing a fast path that will just `memcpy()` (which will be
optimized out) the returned uint64_t directly into the output buffer,
byteswapping it for big endian architectures.
The existing byte-wise copying logic was mostly left alone. It only received an
optimization of the shifting and masking that was previously applied to
`Randomizer::getBytesFromString()` in 1fc2ddc996.
Co-authored-by: Saki Takamachi <saki@php.net>
Using compound literals is conforming to C99 (and up), but not with any
C++ standard. Since the code is in a public header, it might be used
by C++ extensions. Unfortunately, we cannot even used designated
initializers, because these are a C++20 feature, so we stick with
classic C/C++ code.
Closes GH-15100.
The zend_object.properties HashTable needs to be built just in time by calling
rebuild_object_properties() on the object before accessing it. Normally this is
done automatically in zend_std_get_properties(), but we do it manually in a few
places.
In this change I introduce an inline variant of zend_std_build_properties(), and
refactor these places to use it instead of calling rebuild_object_properties()
manually.
rebuild_object_properties() renamed as rebuild_object_properties_internal(), to
enforce usage of zend_std_get_properties() or zend_std_build_properties_ex().
Closes GH-14996