RFC: https://wiki.php.net/rfc/partial_function_application_v2
For FCCs, the parser generates a normal function call AST node, the but argument
list is a ZEND_AST_CALLABLE_CONVERT / zend_ast_fcc node.
We extend this for PFAs so that zend_ast_fcc can represent arguments.
* Support PFA syntax in grammar
* Update zend_ast_fcc so that arguments can be represented
* Support serialization of zend_ast_fcc arguments in SHM / file cache
* Introduce zend_ast_arg_list_add(): Same as zend_ast_list_add(), but wraps the
list in a ZEND_AST_CALLABLE_CONVERT when adding any placeholder argument.
Technically the arg list wrapping is not required, but it results in simpler
code later as it will be very convenient in the compiler (determines whether a
function calls is a PFA/FCC), and for PFA-in-const-expr support. It also allows
to unify FCCs and PFAs in the grammar.
Closes GH-20717.
Strings loaded from the file cache can not have a CE cache, because their cache
slot is invalid. Remove the IS_STR_CLASS_NAME_MAP_PTR flag from these strings.
We can also avoid updating the str flags in SERIALIZE_STR(), since the same
updates must also be done in UNSERIALIZE_STR().
This was already done for interned strings, but not for non-interned ones.
Fixes GH-20329
Closes GH-20337
The offset becomes stale if the environment changes. We're currently relying on
other factors in the environment staying constant, e.g. send types. But this
seems to be the worst offender.
Partially addresses GH-17733
Closes GH-20328
The motivation for this is that types should be considered immutable.
The only times this is not valid is during compilation, optimizations (opcache), or destruction.
Therefore the "normal" type foreach macros are marked to take const arguments and we add mutable version that say so in the name.
Thus add various const qualifiers to communicate intent.
Given that the `ZEND_AST_OP_ARRAY` type already needed special handling in
various places, it makes sense to give it its own struct to avoid some of the
casts. As a side benefit, it is a little smaller than the `zend_ast_zval`
struct.
* zend_compile: Do not traverse children of ZEND_AST_CLOSURE in zend_compile_const_expr()
* Add assertions verifying that zend_ast_decl AST nodes are not treated as regular zend_ast nodes
These are either undefined or defined (to value 1):
- __DragonFly__
- __FreeBSD__
- HAS_MCAST_EXT
- HAVE_GETCWD
- HAVE_GETWD
- HAVE_GLIBC_ICONV
- HAVE_JIT
- HAVE_LCHOWN
- HAVE_NL_LANGINFO
- HAVE_RL_CALLBACK_READ_CHAR
- HAVE_RL_ON_NEW_LINE
- HAVE_SQL_EXTENDED_FETCH
- HAVE_UTIME
Follow up of GH-5526 (-Wundef)
to opcache filecache. Usually, when a class is being loaded, a dependency
tracking is performed after the call to zend_file_cache_script_store.
But sometimes, when opcache cache is empty and there are many simultaneous
outstanding requests for compilation, some classes do have their
inheritance_cache initialized before the call to zend_file_cache_script_store,
and in that case this pointer is serialized as-is. And when such a class
is loaded from opcache filecache this pointer also loaded as-is, and now
it points to some random location in memory. This causes segfaults occuring
when traversing inheritance_cache of such classes.
We need to reset inheritance_cache pointer of zend_class_entry
upon serialization. This should have been done anyway since it is a sensible
strategy to sanitize any memory pointer upon serialization (either by calling
SERIALIZE_x macros or setting to NULL or any other deterministic value).
The buffer may contain uninitialized bytes, like padding, zval.value for
IS_TRUE, IS_NULL, etc. and other unused fields. The checksum calculation loops
over all bytes and thus will trigger uninitialized reads in MSAN. It doesn't
matter too much, as the bytes in the file will still match the checksum.
This feature has been broken at least since the tracing JIT and inheritance
cache have been introduced. The attempted fix (GH-10798) was too complex. We
have thus decided to remove this feature for now.
Closes GH-11832
* ext/opcache/ZendAccelerator: make check_persistent_script_access() static
* ext/opcache/ZendAccelerator: convert "int" to "bool"
* ext/opcache/zend_file_cache: convert "int" to "bool"
* ext/opcache: use true/false for zend_persistent_script.corrupted
* ext/opcache/ZendAccelerator: move duplicate code to zend_accel_discard_script()
* ext/opcache/ZendAccelerator: convert accel_deactivate_now() to function
Simplify the #iddef ZEND_WIN32.
* ext/opcache/zend_file_cache: simplify iovec initializer
* ext/opcache/zend_file_cache: add local zend_string* variables
Eliminates lots of redundant casts and avoids reloading the variable
from RAM into registers.
* ext/opcache/zend_file_cache: use ZSTR_VAL()
* ext/opcache/zend_file_cache: move code to zend_file_cache_script_write()
This eliminates duplicate error handling code.
While JMPZNZ can avoid execution of a separate JMP opcode in some
cases, it also prevents smart branch optimization, so creating
JMPZNZ may actually have a negative effect. It also adds additional
complexity for optimizations.
Drop JMPZNZ in favor of JMPZ+JMP or JMPNZ+JMP.
Closes GH-7857.
Previously, code such as subclasses of SplFixedArray would check for method
overrides when instantiating the objects.
This optimization was mentioned as a followup to GH-6552
- for packed arrays we store just an array of zvals without keys.
- the elements of packed array are accessible throuf as ht->arPacked[i]
instead of ht->arData[i]
- in addition to general ZEND_HASH_FOREACH_* macros, we introduced similar
familied for packed (ZEND_HASH_PACKED_FORECH_*) and real hashes
(ZEND_HASH_MAP_FOREACH_*)
- introduced an additional family of macros to access elements of array
(packed or real hashes) ZEND_ARRAY_ELEMET_SIZE, ZEND_ARRAY_ELEMET_EX,
ZEND_ARRAY_ELEMET, ZEND_ARRAY_NEXT_ELEMENT, ZEND_ARRAY_PREV_ELEMENT
- zend_hash_minmax() prototype was changed to compare only values
Because of smaller data set, this patch may show performance improvement
on some apps and benchmarks that use packed arrays. (~1% on PHP-Parser)
TODO:
- sapi/phpdbg needs special support for packed arrays (WATCH_ON_BUCKET).
- zend_hash_sort_ex() may require converting packed arrays to hash.
It's possible for delayed early binding opcodes to get optimized
away if they are "unreachable". However, we still need to attempt
early binding for them. (In some cases we also corrupt the early
binding list outright during optimization, which is how I got here.)
Fix this by storing information about delayed early binding
independently of DECLARE_CLASS_DELAYED opcodes, so early binding is
performed even after the opcode has been dropped.
The IS_UNSERIALIZED check here does not work if the string is
interned (serialized with file_cache_only=0) but unserialization
happens with file_cache_only=1. In this case the unserializde
string will be in the str area after mem, which is not included
in the script size, and which is also not accessible at this
point without threading through more information. Work around
the problem by checking for the serialized representation instead.