Commit graph

2370 commits

Author SHA1 Message Date
Nikita Popov
53e9c36cd9 Add sanity check for type of read_property return value
If an internal class overrides read_property and declared property
types, make sure that the returned value matches the declared
type (in debug builds).
2021-03-16 10:42:47 +01:00
Dmitry Stogov
3d11743372 Inline "array" part of FE_FETCH_R handler into HYBRID VM 2021-03-11 22:33:01 +03:00
Dmitry Stogov
278d452a6a zend_verify_recv_arg_type_helper is not "cold". 2021-03-11 15:57:02 +03:00
Dmitry Stogov
9da66e6ad0 Optimized object conversion to array without rebulding properties HashTable 2021-03-01 22:37:37 +03:00
Nikita Popov
47a2e5c785 Reference dynamic functions through dynamic_defs
Currently, dynamically declared functions and closures are inserted
into the function table under a runtime definition key, and then later
possibly renamed. When opcache is not used and a file containing a
closure is repeatedly included, this leads to a very large memory leak,
as the no longer needed closure declarations will never be freed
(https://bugs.php.net/bug.php?id=76982).

With this patch, dynamic functions are instead stored in a
dynamic_func_defs member on the op_array, which opcodes reference
by index. When the parent op_array is destroyed, the dynamic_func_defs
it contains are also destroyed (unless they are stilled used elsewhere,
e.g. because they have been bound, or are used by a live closure). This
resolves the fundamental part of the leak, though doesn't completely
fix it yet due to some arena allocations.

The main non-obvious change here is to static variable handling:
We can't destroy static_variables_ptr in destroy_op_array, as e.g.
that would clear the static variables in a dynamic function when
the op_array containing it is destroyed. Static variable destruction
is separated out for this reason (we already do static variable
destruction separately for normal functions, so we only need to
handle main scripts).

Closes GH-5595.
2021-03-01 11:35:54 +01:00
Nikita Popov
6dd85f83f7 Fixed bug #80781
zend_find_array_dim_slow() may throw, make sure to handle this.
This backports the code we already use for this on PHP-8.0,
and also backports an exception check that makes this easier to
catch.
2021-02-22 09:36:43 +01:00
Nikita Popov
5d160e309e Fix static variable behavior with inheritance
When a method is inherited, the static variables will now always
use the initial values, rather than the values at the time of
inheritance. As such, behavior no longer depends on whether
inheritance happens before or after a method has been called.

This is implemented by always keeping static_variables as the
original values, and static_variables_ptr as the modified copy.

Closes GH-6705.
2021-02-18 11:18:19 +01:00
Nikita Popov
8b4ae72efb Fix unused variable warning 2021-02-16 14:24:58 +01:00
Dmitry Stogov
f8cf7152a9 Microoptimization of STRLEN and IN_ARRAY opcodes (based on https://github.com/php/php-src/pull/4981) 2021-02-16 14:11:47 +03:00
Tyson Andre
8ffc20ace6 Optimize Traversable unpacking in zend_vm_def.h
The C compiler sees that a dynamic function is being called, so it cannot infer
that iter->funcs has not changed.

This results in more assembly instructions and slightly more time to execute that code
path.

Unpacking traversables to arrays(`ZEND_ADD_ARRAY_UNPACK`),
starting foreach loops (`ZEND_FE_FETCH*`), etc. are affected.

```
<?php
/*
 * Before: 1.576 seconds
 * After:  1.474 seconds
 */
function example() {
    $start = hrtime(true);
    $it = new SplFixedArray(1000);
    $total = 0;
    for ($i = 0; $i < 100000; $i++) {
        $total += count([...$it]);
    }
    $end = hrtime(true);
    printf("Elapsed: %.6f\n", ($end - $start) / 1_000_000_000);
}
example();
```
2021-02-13 09:34:48 -05:00
Nikita Popov
b10416a652 Deprecate passing null to non-nullable arg of internal function
This deprecates passing null to non-nullable scale arguments of
internal functions, with the eventual goal of making the behavior
consistent with userland functions, where null is never accepted
for non-nullable arguments.

This change is expected to cause quite a lot of fallout. In most
cases, calling code should be adjusted to avoid passing null. In
some cases, PHP should be adjusted to make some function arguments
nullable. I have already fixed a number of functions before landing
this, but feel free to file a bug if you encounter a function that
doesn't accept null, but probably should. (The rule of thumb for
this to be applicable is that the function must have special behavior
for 0 or "", which is distinct from the natural behavior of the
parameter.)

RFC: https://wiki.php.net/rfc/deprecate_null_to_scalar_internal_arg

Closes GH-6475.
2021-02-11 21:46:13 +01:00
Dmitry Stogov
ef51648185 Use zend_type.ce_cache__ptr for caching class resulution during argument/result type checks 2021-02-10 18:00:00 +03:00
Dmitry Stogov
4b79dba932 Added Inheritance Cache.
This is a new transparent technology that eliminates overhead of PHP class inheritance.

PHP  classes are compiled and cached (by opcahce) separately, however their "linking" was done at run-time - on each request. The process of "linking" may involve a number of compatibility checks and borrowing methods/properties/constants form parent and traits. This takes significant time, but the result is the same on each request.

Inheritance Cache performs "linking" for unique set of all the depending classes (parent, interfaces, traits, property types, method types involved into compatibility checks) once and stores result in opcache shared memory. As a part of the this patch, I removed limitations for immutable classes (unresolved constants, typed properties and covariant type checks). So now all classes stored in opcache are "immutable". They may be lazily loaded into process memory, if necessary, but this usually occurs just once (on first linking).

The patch shows 8% improvement on Symphony "Hello World" app.
2021-02-09 22:53:57 +03:00
Nikita Popov
27cd7a11cb Add support for string keys in array unpacking
This adds support for:

    $array1 = ['a' => 1, 'b' => 2];
    $array2 = ['b' => 3, 'c' => 4];
    $array = [...$array1, ...$array2];
    // => ['a' => 1, 'b' => 3, 'c' => 4]

RFC: https://wiki.php.net/rfc/array_unpacking_string_keys

Closes GH-6584.
2021-02-09 10:04:27 +01:00
Dmitry Stogov
1d2fd57c99 Merge branch 'PHP-8.0'
* PHP-8.0:
  Allow observer handlers disabling optimization in RETURN opcode handler, that may cause loss value of returned local variable.
2021-01-26 19:25:50 +03:00
Dmitry Stogov
b529d02d24 Allow observer handlers disabling optimization in RETURN opcode handler, that may cause loss value of returned local variable. 2021-01-26 19:23:13 +03:00
Nikita Popov
b3189e7dad Merge branch 'PHP-8.0'
* PHP-8.0:
  Fix VAR return type verification
2021-01-26 15:18:04 +01:00
Nikita Popov
a2dcd44272 Fix VAR return type verification
We should also set retval_ref when de-indirecting. Otherwise the
retval_ref != retval_ptr comparison below may incorrect assume
that we're returning a reference.

I don't have a reliable reproducer for this issue, but it sometimes
appears in certain configurations in arrow_functions/007.phpt in
conjunction with other changes.
2021-01-26 15:15:18 +01:00
Nikita Popov
776726da03 Add missing resource key warning for unset()
It was present on other operations, including isset(), but was
missing for unset().
2021-01-26 12:51:02 +01:00
Nikita Popov
3e01f5afb1 Replace zend_bool uses with bool
We're starting to see a mix between uses of zend_bool and bool.
Replace all usages with the standard bool type everywhere.

Of course, zend_bool is retained as an alias.
2021-01-15 12:33:06 +01:00
Dmitry Stogov
9fc11762e5 PHP array cannot refer to EG(symbol_table) any more. Replace corresponding checks by ZEND_ASSERT(). 2021-01-11 18:26:01 +03:00
Nikita Popov
22793884b6 Remove some INDIRECT handling in VM 2021-01-06 12:46:31 +01:00
Nikita Popov
3c68f38fda Restrict allowed usages of $GLOBALS
This restricts allowed usage of $GLOBALS, with the effect that
plain PHP arrays can no longer contain INDIRECT elements.

RFC: https://wiki.php.net/rfc/restrict_globals_usage

Closes GH-6487.
2021-01-06 12:46:24 +01:00
Dmitry Stogov
841b00f641 Preallocate stack space for JIT in execute_ex() to eliminate JIT prologue/epilogue. 2020-11-30 17:56:08 +03:00
Sammy Kaye Powers
58d41b8c4f Provide unused retvals to observers
Make sure that the return value is available to observers, even if
it is not used by the caller.

Closes GH-6422.
2020-11-17 10:28:47 +01:00
Dmitry Stogov
855d8fa68f [Observer] Save opline before calling begin/end handlers 2020-11-11 13:06:55 +03:00
Nikita Popov
1748b8111e Fix handling of throwing undef var in verify return
If we have an undefined variable and null is not accepted by the
return type, we want to throw just the undef var error.

In this case this lead to an infinite loop, because we overwrite
the exception opline in SAVE_OPLINE and it does not get reset
when chaining into a previous exception. Add an assertiong to
catch this case earlier.
2020-10-13 11:43:43 +02:00
Nikita Popov
d953cd1862 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Avoid non-object in FE_FREE
2020-10-12 09:46:38 +02:00
Nikita Popov
304141e8f8 Avoid non-object in FE_FREE
Even if the properties HT is empty, make sure we still leave an
object in the FE_RESET result, so our type inference results
stay correct.
2020-10-12 09:45:52 +02:00
Nikita Popov
623bf39e9c Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fixed bug #80186
2020-10-09 17:02:20 +02:00
Nikita Popov
15443f8af4 Fixed bug #80186
Early exit in FE_RESET if get_properties() returns empty array,
as we cannot add HT iterators to zend_empty_array.
2020-10-09 16:56:08 +02:00
Dmitry Stogov
fd81e708bc Fixed incorrect behavior of observer API.
ZEND_HANDLE_EXCEPTION might call zend_observer_fcall_end() even if exception is cought by function. The fix moved zend_observer_fcall_end() into a right place and remove OBSERVER sepecialization for ZEND_HANDLE_EXCEPTION handler.
2020-10-07 17:06:53 +03:00
George Peter Banyard
2ee7e2982f Promote count() warning to TypeError
Closes GH-6180
2020-09-21 21:29:15 +01:00
Nikita Popov
213b666781 Synchronize GET_CLASS/GET_CALLED_CLASS opcodes with functions
These error conditions throw in the function implementations,
make the opcodes match.
2020-09-21 15:06:04 +02:00
Dmitry Stogov
d5d31ea3b3 Cleanup observer API and add JIT support 2020-09-18 12:55:58 +03:00
Sammy Kaye Powers
9e94bcfdbc Remove specialization of SPEC(OBSERVER) handlers 2020-09-18 00:47:36 +03:00
Bob Weinand
6d538e83aa Fix OSS Fuzz issue: yielding from an aborted generator 2020-09-15 20:07:33 +02:00
Nikita Popov
3c53732332 Fix undef var exception handling in JMP_NULL
We need to initialize the result variable in the exceptional
case as well.

Fixes oss-fuzz #25526.
2020-09-15 15:44:01 +02:00
Máté Kocsis
9975986b7e
Improve error messages mentioning parameters instead of arguments
Closes GH-5999
2020-09-09 10:47:43 +02:00
Dmitry Stogov
a6a96116ac micro-optimization 2020-09-08 16:47:30 +03:00
Nikita Popov
cd1c36f772 Merge branch 'PHP-7.4'
* PHP-7.4:
  Fixed bug #80049
2020-09-03 17:13:47 +02:00
Nikita Popov
2dabc4c305 Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3:
  Fixed bug #80049
2020-09-03 17:12:58 +02:00
Nikita Popov
46a49be6c8 Fixed bug #80049
Type checking may convert to refcounted values, so force freeing
of extra args.
2020-09-03 17:12:40 +02:00
Dmitry Stogov
0d157cf526 Micro-optimization 2020-09-02 17:31:48 +03:00
Levi Morrison
66c3e900e2 Add zend_observer API
Closes GH-5857.

Co-authored-by: Nikita Popov <nikita.ppv@gmail.com>
Co-authored-by: Sammy Powers <sammyk@datadoghq.com>
2020-09-01 09:59:59 -06:00
Nikita Popov
48e31be7a3 Fix FE_FETCH_R_SIMPLE specialization
After a99d08b5d1 the type can
include UNDEF. However, UNDEF can only reach FE_FREE, not FE_FETCH.
As such, simply ignore this type.
2020-09-01 14:43:06 +02:00
Nikita Popov
927771333b Fix unused variable warning 2020-08-28 17:19:32 +02:00
Nikita Popov
b2bc2c62fa Remove unnecessary cache_slot arguments
zend_verify_type_error_common() no longer needs the cache_slot,
so drop it there and from all users.
2020-08-28 17:15:09 +02:00
George Peter Banyard
fa8d9b1183 Improve type declarations for Zend APIs
Voidification of Zend API which always succeeded
Use bool argument types instead of int for boolean arguments
Use bool return type for functions which return true/false (1/0)
Use zend_result return type for functions which return SUCCESS/FAILURE as they don't follow normal boolean semantics

Closes GH-6002
2020-08-28 15:41:27 +02:00
Nikita Popov
86cd009718 Fix pass by ref error for named params 2020-08-26 15:10:08 +02:00