This was doing a plain copy of JMPZNZ, even though it encodes
offsets relative to the opline. As such, the offsets would be
relative to target, while they should be relative to opline.
Fix this by recomputing them.
Fixes oss-fuzz #39295.
This ensures that code directly before the loop var free is
separated out (and will generally be eliminated as unreachable).
This fixes some assumptions we have that unreachable loop var free
blocks start with the loop var free.
Fixes oss-fuzz #39395.
We can't remove a trivial phi of the form x = phi(x), because we
don't have a replacement value. We could drop the whole block
though. SCCP would normally do this, but in this particular case
we only determine non-reachability based on type information.
Fixes oss-fuzz #39316.
If we're removing a predecessor because it already exists during
replacement, we should also drop pi nodes for that predecessor.
Fixes oss-fuzz #39276.
Latest linux kernel use large number (12 bits for major device, 20
bits for minor device). Current code only supports previous standard
(5 chars), which means 8 bits for major and 8 bits for minor device.
It will fail if device number is out of that range. So this patch
increases device number read from /proc/self/maps file.
Closes GH-7512.
We were not inferring anything for the ASSIGN_STATIC_PROP_REF
result type at all, leaving it as an empty type. In the test
case this results in a live range being incorrectly eliminated,
but this could break in all kinds of other ways as well..
This was leaking memory for pre-inc/dec of a refcounted typed
property if the result was not used.
The code to do this was unnecessarily complicated, we can base
this on the zend_jit_inc/dec_typed_prop() helper and copy to the
result afterwards.
We have an invariant that an array value type is set if and only
if an array key type is set, which is violated for the case of
undef values for always invalid keys.
While technically legal, this may cause unexpected situations
(in this example, setting an FE_FREE operand to constant null)
and is suboptimal anyway. It's better to preserve the vacuous type
and drop it later (though we currently don't implement this).
This can happen in degenerate cases where we know that the
SWITCH_STRING argument is not refcounted. We should be treating it
in the same way as SWITCH_LONG here.
The mod_by_zero and negative_shift helper may also be used by
ASSIGN_OP, in which case there is not necessarily a result operand.
If the stars aligned just right, this used to clobber other parts
of the call frame.
For these two helpers, check whether the result_type is TMP/VAR
before setting to UNDEF:
This can occur on opcache OOM conditions, where the function/class
names are not interned and the script does not get cached. In
that case the functions/classes get transferred from the persistent
script to the global tables, without incrementing the key refcount.
To mirror that, we should also not try to free the keys when freeing
the persistent script. For this by setting the number of elements
to zero, which will free only the hashtable structure itself.
The evaluation of the initializer may throw. This could be refined
by checking whether the initializer is a constant AST. For now
just fix the miscompile.
We should report the undefined variable here and convert it to
null. Passing on undef is particularly insidious here, because
a write_dimension handler may insert it into a hash table
(observed with WeakMap).
PHP JIT supports three configurations: HYRBID, CALL with global register
variables feature(CALL+GRV for short), and CALL+noGRV.
CALL+GRV mode can be built with the following commands:
```
php Zend/zend_vm_gen.php --with-vm-kind=CALL
./buildconf -f; ./configure; make
```
About 230 test cases failed for tracing JIT under CALL+GRV mode on both
x86 and arm64 machines.
For CALL+GRV mode, the condition to determine whether the execution of
an oparray is finished, is "opline == NULL". See function execute_ex()
around line "if (UNEXPECTED(!OPLINE)) {".
However, such cleanup operation is missing for the JIT wrapper
zend_jit_trace_counter_helper(), and the trace_halt stub function.
Tests:
1. test cases: all .phpt test cases under "Zend/tests/ tests/
ext/opcache/tests/jit/".
2. both JIT/x86 and JIT/arm64: function JIT, tracing JIT and tracing JIT
with "--repeat 3"
3. execution modes: NTS/ZTS, HYBRID/CALL+GRV/CALL+noGRV
In my local test, these test cases passed under all JIT configrations.
We'd have usually converted it into a PRE_INC if there is no use,
but that's not guaranteed. If there is no use at this point, make
sure we don't try to use the sentinel value.
zend_jit_long_math_helper() implicitly assumes that the operands
MAY_BE_LONG (but can also have additional types). It will normally
only be called if this is guaranteed. However, for compound
array/object assignment ops this was not check. Generalize the
existing check for assign_op to apply to these as well.
Of course, we could also make the code support this correctly,
but I don't think it makes sense to JIT these if the type we're
specializing for is not present.
Closes GH-7481.