Commit graph

2640 commits

Author SHA1 Message Date
Dmitry Stogov
c3f23642da ws 2019-11-12 10:51:55 +03:00
Tyson Andre
937fa6d9e2 Optimize is_scalar($x) into a TYPE_CHECK opcode
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
2019-11-12 10:17:10 +03:00
Nikita Popov
999e32b65a Implement union types
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.
2019-11-08 15:15:48 +01:00
Nikita Popov
ac4e0f0852 Make zend_type a 2-field struct
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.
2019-11-08 15:15:48 +01:00
Nikita Popov
e710862f8c Add compile warning for "confusable" types
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.
2019-11-07 15:05:08 +01:00
Nikita Popov
aef8836110 Don't check $this existence in object opcodes
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.
2019-10-30 09:30:13 +01:00
Nikita Popov
5c24f8042d Promote "Cannot use parent" to fatal error 2019-10-15 11:46:48 +02:00
Dmitry Stogov
d37f5da75e typo and cleanup 2019-10-09 17:58:35 +03:00
Dmitry Stogov
f6f32f2cf0 SAMRT BRANCH improvement.
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.
2019-10-09 13:48:39 +03:00
Nikita Popov
a32f130f94 Merge branch 'PHP-7.4' 2019-10-08 17:34:25 +02:00
Nikita Popov
bea832cbf6 Don't check type of simple parameter default values
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.
2019-10-08 17:29:41 +02:00
Nikita Popov
cffa81e438 Merge branch 'PHP-7.4' 2019-10-08 15:52:18 +02:00
Dmitry Stogov
56ae3f6c4a Added "const" qualifier 2019-10-08 16:50:04 +03:00
Nikita Popov
9004102b99 Fixed bug #78648 2019-10-08 15:39:22 +02:00
Nikita Popov
5050507282 Merge branch 'PHP-7.4' 2019-10-04 22:47:10 +02:00
Nikita Popov
b078ae6c01 Merge branch 'PHP-7.3' into PHP-7.4 2019-10-04 22:46:53 +02:00
Nikita Popov
239e2dda64 Make sure T_ERROR is returned for all lexer exceptions
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.
2019-10-04 22:42:14 +02:00
Nikita Popov
11d139625f Merge branch 'PHP-7.4' 2019-10-04 10:39:32 +02:00
Nikita Popov
9659562cb5 Fix use-after-free with delayed interned memoized const operand
We should addref CONST operands during memoization, as they might
be destroyed by later compilation, e.g. through interning.
2019-10-04 10:38:11 +02:00
Nikita Popov
c10cd739a7 Merge branch 'PHP-7.4' 2019-10-04 10:12:16 +02:00
Nikita Popov
f26b60a583 Fix crash when unpacking into array literal with string keys 2019-10-04 10:11:30 +02:00
Dmitry Stogov
de3c1eb85e Move obvious optimization patterns from pass1 directly to compiler 2019-10-03 14:57:20 +03:00
Nikita Popov
d882795d78 Merge branch 'PHP-7.4' 2019-10-02 12:08:12 +02:00
Nikita Popov
171d6c3ca7 Merge branch 'PHP-7.3' into PHP-7.4 2019-10-02 12:07:33 +02:00
Nikita Popov
3c42471ef8 Merge branch 'PHP-7.2' into PHP-7.3 2019-10-02 12:07:19 +02:00
Nikita Popov
a5d3620d93 Fix segfault with __COMPILER_HALT_OFFSET__ and trailing {}
Fixes OSS-Fuzz #17895.
2019-10-02 12:07:15 +02:00
Nikita Popov
8145da0d82 Remove unused zend_del_literal() function 2019-09-27 23:58:48 +02:00
Nikita Popov
a66c60cce3 Throw Error when writing property of non-object
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.
2019-09-27 10:11:47 +02:00
Dmitry Stogov
6e226c188c Change ZEND_RECV and ZEND_RECV_VARIADIC to use extended_value for cache slot (instead of op2), to be consistent with ZEND_RECV_INIT. 2019-09-23 22:28:56 +03:00
Nikita Popov
3012d006ff Don't set nullability flag for parameters without type
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.
2019-09-23 16:39:52 +02:00
Nikita Popov
5dcbc65a53 Canonicalize typed prop/param default value errors
Use shared logic to determine what values are valid, and a single
error message format.
2019-09-23 16:20:26 +02:00
Nikita Popov
b7745d6eeb Check for nullable void type earlier 2019-09-23 15:59:47 +02:00
Nikita Popov
9e8ba7891e Change representation of zend_type from type code to MAY_BE_* mask
This switches zend_type from storing a single IS_* type code to
storing a MAY_BE_* type mask. Right now most code still assumes
that there is only a single type in the mask (or two together
with MAY_BE_NULL). But this will make it a lot simpler to introduce
union types.

An additional advantage (and why I'm doing this separately), is
that a number of special cases no longer need to be handled
separately: We can do a single mask & (1 << type) check to handle
all simple types, booleans (true|false) and null.
2019-09-23 15:31:35 +02:00
Nikita Popov
b6d138fba1 Merge branch 'PHP-7.4' 2019-09-13 18:23:47 +02:00
Nikita Popov
4226c8247f Fix use-after-free in assign-ref compilation
zend_emit_op_data may reallocate the op_array, so the assignment
of the RETURNS_FUNCTION flag may happen on an outdated opline.

Restructure the code a bit to set the flag before calling
zend_emit_op_data().
2019-09-13 18:22:14 +02:00
Dmitry Stogov
8a673e9380 Merge branch 'PHP-7.4'
* PHP-7.4:
  Fixed incorrect usage of QM_ASSIGN instruction
2019-09-13 12:13:25 +03:00
Dmitry Stogov
e45a757bc2 Fixed incorrect usage of QM_ASSIGN instruction 2019-09-13 12:08:59 +03:00
Nikita Popov
f61f122b9a Merge branch 'PHP-7.4' 2019-09-12 16:41:45 +02:00
Nikita Popov
4b9ebd837b Allow throwing exception while loading parent class
This is a fix for symfony/symfony#32995.

The behavior is:

* Throwing exception when loading parent/interface is allowed
  (and we will also throw one if the class is simply not found).
* If this happens, the bucket key for the class is reset, so
  it's possibly to try registering the same class again.
* However, if the class has already been used due to a variance
  obligation, the exception is upgraded to a fatal error, as we
  cannot safely unregister the class stub anymore.
2019-09-12 16:41:18 +02:00
Nikita Popov
a09da43888 Merge branch 'PHP-7.4' 2019-09-11 17:05:07 +02:00
Nikita Popov
d88b212ea6 Improve "already declared" error message
If this error is missing because the rtd_key was renamed to lcname,
fetch the class based on lcname and use the class type and cased
name from there.
2019-09-11 17:04:13 +02:00
Nikita Popov
e530a89c00 Merge branch 'PHP-7.4' 2019-09-06 11:33:36 +02:00
Nikita Popov
e81751ceac Fixed bug #78502
We need to make sure that the function is fully compiled before we
calculate the stack size. There already was a check for directly
recursive calls, but the same issue exists with indirectly recursive
calls.

I'm using DONE_PASS_TWO as the indication that the function is
fully compiled.
2019-09-06 11:33:28 +02:00
Dmitry Stogov
a5597312e4 Fixed performance degradation caused by arg_info of internal function 2019-09-02 12:11:18 +03:00
Nikita Popov
4e4cc9b480 Merge branch 'PHP-7.4' 2019-08-23 17:23:31 +02:00
Nikita Popov
d1157cbce1 Relax closure $this unbinding deprecation
Only deprecate unbinding of $this from a closure if $this is
syntactically used within the closure.

This is desired to support Laravel's macro system, see laravel/framework#29482.

This should still allow us to implement the performance improvements
we're interested in for PHP 8, without breaking existing use-cases.
2019-08-23 17:21:23 +02:00
Nikita Popov
f0d4c48c7e Merge branch 'PHP-7.4' 2019-08-12 17:18:14 +02:00
Nikita Popov
b6f1b61f8f Merge branch 'PHP-7.3' into PHP-7.4 2019-08-12 17:17:42 +02:00
Nikita Popov
4cd563d07e Merge branch 'PHP-7.2' into PHP-7.3 2019-08-12 17:17:30 +02:00
Nikita Popov
f3fdf570b3 Intern alias old_name early
This is likely going to end up interned lateron at some point
when the new_name is referenced somewhere. However, it may be
that there are some uses that do not get interned before that.
In this case we will intern a string that already have zval
users, without updating the refcounted flag on those zvals.

In particular this can happen with something like [Foo::class],
where Foo is an imported symbol. The string it resolves to won't
get interned right away, but may be interned later.

    use Foo as Bar;
    $x = [Bar::class];
    var_dump(Bar::X);
    debug_zval_dump($x); // Will show negative refcount
    class Foo {
        const X = 1;
    }

However, this doesn't really fix the root cause, there are probably
other situations where something similar can occur.
2019-08-12 17:12:28 +02:00