zend_runtime_jit() prevents concurrent compilation with
zend_shared_alloc_lock(), but this doesn't prevent blocked threads from
trying to compile the function again after they acquire the lock.
In the case of GH-19889, one of the function entries is compiled with
zend_jit_handler(), which fails when the op handler has already been replaced by
a JIT'ed handler.
Fix by marking compiled functions with a new flag ZEND_FUNC_JITED, and
skipping compilation of marked functions. The same fix is applied to
zend_jit_hot_func().
Fixes GH-19889
Closes GH-19971
If an exception _and_ a warning (or deprecation) is emitted, then the
result is destroyed twice. Use an `else if` to prevent this.
This is tested via zend_test because the deprecation that triggered the
original reproducer may disappear in the future.
Closes GH-19793.
Range analysis may fail to converge (the process hangs) when the transfer
function zend_inference_calc_range produces a smaller range.
Fix by ensuring that the widening operator zend_inference_widening_meet
allows only widening. This matches the inference rules in figure 13 of the
paper.
Fixes GH-19679
Closes GH-19683
* Emit EXT_STMT after each pipe stage, and attach the TMP var that holds the intermediary result
* Add ZEND_EXT_STMT to keeps_op1_alive as per review
* Fix leak with EXT_STMT when pipe result is unused
Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
On some systems, like Alpine, the thread stack size is small by default.
The last step of SSA construction involves variable renaming that is
recursive, and also makes copies of their version of the renamed
variables on the stack. This combination causes a stack overflow during
compilation on Alpine. Triggerable for example with very long match
statements.
A stop-gap solution would be to use heap allocated arrays for the
renamed variable list, but that would only delay the error as increasing
the number of match arms increases the depth of the dominator tree, and
will eventually run into the same issue.
This patch transforms the algorithm into an iterative one.
There are two states stored in a worklist stack: positive numbers
indicate that the block still needs to undergo variable renaming.
Negative numbers indicate that the block and its dominated children are
already renamed. Because 0 is also a valid block number, we bias the
block numbers by adding 1.
To restore to the right variant when backtracking the "recursive" step,
we index into an array pointing to the different variable renaming
variants.
Closes GH-19083.
Reuse the helper zend_foreach_op_array() that we move to the
zend_optimizer.h header to be usable in opcache.
Note that applying this to other op_array loops is not easy because they either:
- start from EG(persistent_classes_count)
- or only apply to classes
- When building with bundled libgd, it has support for BMP
- When building with external libgd, at least 2.1.0 is required, which
has BMP support.
- The HAVE_GD_PNG moved to PHP_GD_PNG Autoconf macro as it is always
required when building with bundled libgd.
When the array functions perform their operation in-place, the
`@refcount 1` annotation is wrong and causes a failure under
`ZEND_VERIFY_FUNC_INFO`.
The test file tests all functions that have the in-place optimization,
even those that didn't have the refcount annotation, just to prevent
future regressions.
Closes GH-18929.
* Move glob to main/ from win32/
In preparation to make the Win32 reimplementation the standard
cross-platform one. Currently, it doesn't do that and just passes
through the original glob implementation. We could consider also having
an option to use the standard glob for systems that have a sufficient
one.
* Enable building with win32 glob on non-windows
Kind of broken. We're namespacing the function and struct, but not yet
the GLOB_* defines. There are a lot of places callers check if i.e.
NOMATCH is defined that would likely become redundant.
Currently it also has php_glob and #defines glob php_glob (etc.) - I
suspect doing the opposite and changing the callers would make more
sense, just doing MVP to geet it to build (even if it fails tests).
* Massive first pass at conversion to internal glob
Have not tested yet. the big things are:
- Should be invisible to userland PHP code.
- A lot of :%s/GLOB_/PHP_GLOB_/g; the diff can be noisy as a result,
especially in comments.
- Prefixes everything with PHP_ to avoid conflicts with system glob in
case it gets included transitively.
- A lot of weird shared definitions that were sprawled out to other
headers are now included in php_glob.h.
- A lot of (but not yet all cases) of HAVE_GLOB are removed, since we
can always fall back to php_glob.
- Using the system glob is not wired up yet; it'll need more shim
ifdefs for each flag type than just glob_t/glob/globfree defs.
* Fix inclusion of GLOB_ONLYDIR
This is a GNU extension, but we don't need to implement it, as the GNU
implementation is flawed enough that callers have to manually filter it
anyways; just provide a stub definition for the constant.
We could consideer implementing this properly later. For now, fixes the
basic glob constant tests.
* Remove HAVE_GLOBs
We now always have a glob implementation that works. HAVE_GLOB should
only be used to check if we have a system implementation, for if we
decide to wrap the system implementation instead.
* We don't need to care about being POSIXly correct for internal glob
* Check for reallocarray
Ideally temporary until GH-17433.
* Forgot to move this file from win32/ to main/
* Check for issetugid (BSD function)
* Allow using the system glob with --enable-system-glob
* Style fix after removing ifdef
* Remove empty case for system glob
The trait handling for property hooks in preloading did not exist, we
add a check to skip trait clones and we add the necessary code to update
the op arrays.
Closes GH-18586.
* Optimizer: Optimize `IS_IDENTICAL` with true/false/null to `TYPE_CHECK`
This optimization is already happening in the compiler for explicit `===`
expressions, but not for `match()`, which also compiles to `IS_IDENTICAL`.
* Optimizer: Optimize `T = BOOL(X) + TYPE_CHECK(T, true)` to just `BOOL`
Resolvesphp/php-src#18411
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.
If there's a try-finally where the try_op starts on a basic block with a
single JMP, and the JMP optimization causes that basic block to become
unreachable, then we update try_op.
In this case, there is no catch_op, so try_op is erroneously set to 0,
we should instead set it to `b->start`.
Closes GH-18110.
in_array() calls are compiled to frameless calls. Adjust the
optimization appropriately. Luckily, frameless opcodes simplify the
optimization quite a bit.
Fixes GH-18050
Closes GH-18066
This avoids repeated lookups in the function table for the same
function name.
Although this optimization is observable, i.e. defining a function via
an include in between 2 JMP_FRAMELESS for the same function, this cannot
be relied on already as far as I know if the optimizer runs.
Replaces GH-15730 as that PR became stale.
But instead of introducing a new helper, reuse
smart_str_append_escaped(), this also removes the dependency on
ext/standard.
Closes GH-15730.
Closes GH-17277.
op1 of ZEND_MATCH_ERROR, which refers to the match expression, is not freed by
MATCH_ERROR itself. Instead, it is freed by ZEND_HANDLE_EXCEPTION. For normal
control flow, a FREE is placed at the end of the match expression.
Since FREE may appear after MATCH_ERROR in the opcode sequence, we need to
correctly handle op1 of MATCH_ERROR as alive.
Fixes GH-17106
Closes GH-17108