Also generate a fatal error if a collision occurs in zend_compile.
This is not perfect, because collisions might still be introduced
via opcache, if one file is included multiple times during a request,
invalidate in the meantime and recompiled by different processes.
This still needs to be addressed, but this patch fixes the much
more common case of collisions occuring when opcache is not used.
Fixes bug #78903.
We need to make sure that trait methods with static variables
allocate a separate MAP slot for the static variables pointer,
rather than working in-place.
I wasn't able to create a simple reproducer for this. General approach
is the same as for anonymous classes: If the key is already used, reuse
the old definition.
During preloading, check that all classes that have been included
as part of the preload script itself (rather than through opcache_compile_file)
can actually be preloaded, i.e. satisfy Windows restrictions, have
resolved initializers and resolved property types. When resolving
initializers and property types, also autoload additional classes.
Because of this, the resolution runs in a loop.
When we change back the bucket key on a class linking failure,
make sure to reload the bucket pointer, as the class table may
have been reallocated in the meantime.
Also remove a bogus bucket key change in anon class registration:
We don't actually rename the class in this case anymore, the RTD
key is already the final name.
The "return" in the for loop should have been a break on the switch,
otherwise the result is just ignored... but because it prevents
evaluation of the other operand, it also violates the invariant that
everything has been constant evaluated, resulting in an assertion
failure.
The for loop isn't correct in any case though, because it's not legal
to determine the result based on just the second operand, as the
first one may have a side-effect that cannot be optimized away.
Optimizations such as specializations for is_resource were first added in
dfb4f6b38d9efedafab7d2d98b9333715561256
I don't see any mention of is_scalar (and optimizing it) in the commit history,
or in prior PRs on github, or searching for is_scalar in externals.io
According to RFC: https://wiki.php.net/rfc/union_types_v2
The type representation now makes use of both the pointer payload
and the type mask at the same time. Additionall, zend_type_list is
introduced as a new kind of pointer payload, which is used to store
multiple class types. Each of the class types is a tagged pointer,
which may be either a class name or class entry. The latter is only
used for typed properties, while arguments/returns will instead use
cache slots. A type list can contain a mix of both names and CEs at
the same time, as not all classes may be resolvable.
One thing this is missing is support for union types in arginfo
and stubs, which I want to handle separately.
I've also dropped the special object code from the JIT implementation
for now -- I plan to add this back in a different form at a later time.
For now I did not want to include non-trivial JIT changes together
with large functional changes.
Another possible piece of follow-up work is to implement "iterable"
as an internal alias for "array|Traversable". I believe this will
eliminate quite a few special-cases that had to be implemented.
Closes GH-4838.
We now store the pointer payload and the type mask separately. This
is in preparation for union types, where we will be using both at
the same time.
To avoid increasing the size of arginfo structures, the
pass_by_reference and is_variadic fields are now stored as part of
the type_mask (8-bit are reserved for custom use).
Different types of pointer payloads are distinguished based on bits
in the type_mask.
We have a number of "types" like integer which are not actually
supported as builtin types -- instead they are silently interpreted
as class types.
I've seen this cause confusion a few types already. This change adds
a warning in this case. In the unlikely case that someone legitimately
wants to type against an integer class, the warning can be suppressed
by writing \integer or "use integer", or using Integer (this warning
will only trigger for lowercase spellings).
Closes GH-4815.
We are now guaranteed that $this always exists inside methods, as
well as insides closures (if they use $this at all).
This removes checks for $this existence from the individual object
opcodes. Instead ZEND_FETCH_THIS is used in the cases where $this
is not guaranteed to exist, which is mainly the pseudo-main scope.
Closes GH-3822.
Avoid need of insertion NOP opcoes between unrelated SMART BRANCH instruction and following JMPZ/JMPNZ.
Now instead of checking the opcode of following instruction, the same information is encoded into SMART BRANH result_type.
After fixing the int->double coercion case, this is already verified
at compile-time, so there is no need to redo this type check on
every call.
Only perform the type check every time for the case of AST default
values.
This originally manifested as a leak in oss-fuzz #18000. The following
is a reduced test case:
<?php
[
5 => 1,
"foo" > 1,
" " => "" == 0
];
<<<BAR
$x
BAR;
Because this particular error condition did not return T_ERROR,
EG(exception) was set while performing binary operation constant
evaluation, which checks exceptions for cast failures.
Instead of adding this indirect test case, I'm adding an assertion
that the lexer has to return T_ERROR if EG(exception) is set.
This removes object auto-vivification support.
This also means that we can remove the corresponding special
handling for typed properites: We no longer need to check that a
property is convertible to stdClass if such a conversion might
take place indirectly due to a nested property write.
Additionally OBJ_W style operations now no longer modify the
object operand, and as such we no longer need to treat op1 as a
def in SSA form.
The next step would be to actually compile the whole LHS of OBJ_W
operations in R rather than W mode, but that causes issues with
SimpleXML, whose object handlers depend on the current compilation
structure.
Part of https://wiki.php.net/rfc/engine_warnings.
Use value 0 instead. To compensate we check in ReflectionParameter
allowsNull() whether the type is set at all: If it isn't, it always
allows null.
This removes a discrepancy between internal&userland functions:
For userland functions allowsNull() on untyped parameters returned
true, but for internal functions it returned false.