Skip to content

Commit 5c4816c

Browse files
author
coderzhao
committed
Merge branch 'master' into fix/gh-22857-jit-fetch-obj-func-arg-hook
2 parents 05c5cc3 + c5cdea5 commit 5c4816c

75 files changed

Lines changed: 1589 additions & 544 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

NEWS

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ PHP NEWS
88
failure path). (David Carlier)
99
. Fixed bug GH-18985 (Wrong line numbers for match with constant arms).
1010
(ilutov)
11+
. Fixed bug GH-18847 (SEGV in zend_fetch_debug_backtrace() when the memory
12+
limit is reached while the tracing JIT enters a call frame). (Arnaud,
13+
iliaal)
1114

1215
- DOM:
1316
. Fixed bug GH-22825 (DOMElement::setAttribute() fails silently when the DTD
@@ -65,6 +68,12 @@ PHP NEWS
6568
TCP_USER_TIMEOUT, and SO_LINGER options. (Weilin Du)
6669
. Fixed various memory related issues in ext/sockets. (David Carlier)
6770

71+
- Standard:
72+
. Fixed setlocale() to reject locale names containing NUL bytes instead of
73+
silently truncating them, and to reject arrays passed after the $locales
74+
argument or additional arguments passed after an array $locales argument.
75+
(Weilin Du)
76+
6877
- Streams:
6978
. Added a new IO copy API used by php_stream_copy_to_stream_ex() that
7079
leverages platform primitives (sendfile, splice, copy_file_range,

UPGRADING

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,12 @@ PHP 8.6 UPGRADE NOTES
201201
bytes.
202202
. parse_str() now raises a ValueError when the $string argument contains NUL
203203
bytes.
204+
. setlocale() now raises a ValueError when a locale name contains NUL bytes,
205+
instead of silently truncating it.
206+
Arrays are now accepted only for the $locales argument. Passing an array as
207+
a later variadic locale argument now throws a TypeError. Passing any
208+
additional locale arguments when $locales is an array now throws an
209+
ArgumentCountError.
204210
. linkinfo() now raises a ValueError when the $path argument is empty.
205211
. pathinfo() now raises a ValueError when an invalid $flag argument value is
206212
passed.

UPGRADING.INTERNALS

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,43 @@ PHP 8.6 INTERNALS UPGRADE NOTES
8383
. The php_error_docref1() and php_error_docref2() functions have been
8484
removed, instead rely on the error_include_args INI option to show the
8585
arguments to functions in a consistent manner.
86+
. The following PHP stream functions prefixed with _ have been removed,
87+
and the macro without it has become the canonical function name:
88+
* _php_stream_cast()
89+
* _php_stream_free_enclosed()
90+
* _php_stream_free()
91+
* _php_stream_seek()
92+
* _php_stream_tell()
93+
* _php_stream_read()
94+
* _php_stream_write()
95+
* _php_stream_fill_read_buffer()
96+
* _php_stream_printf()
97+
* _php_stream_eof()
98+
* _php_stream_getc()
99+
* _php_stream_putc()
100+
* _php_stream_flush()
101+
* _php_stream_sync()
102+
* _php_stream_get_line()
103+
* _php_stream_puts()
104+
* _php_stream_stat()
105+
* _php_stream_mkdir()
106+
* _php_stream_rmdir()
107+
* _php_stream_readdir()
108+
* _php_stream_set_option()
109+
* _php_stream_get_url_stream_wrappers_hash()
110+
* _php_get_stream_filters_hash()
111+
* _php_stream_mmap_unmap()
112+
* _php_stream_mmap_unmap_ex()
113+
* _php_stream_filter_prepend()
114+
* _php_stream_filter_append()
115+
* _php_stream_filter_flush()
116+
. The PHP stream function _php_stream_stat_path() has been renamed to
117+
php_stream_stat_path_ex()
118+
. The PHP stream function _php_stream_scandir() was removed,
119+
insted the PHP macro php_stream_scandir() is now a function as the
120+
flags parameter was never used.
121+
. The PHP stream function _php_stream_flush() was removed,
122+
instead the PHP macro php_stream_flush() is now a proper function.
86123

87124
- Changed:
88125
. Internal functions that return by reference are now expected to

Zend/Optimizer/compact_literals.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "zend_execute.h"
2727
#include "zend_vm.h"
2828
#include "zend_extensions.h"
29+
#include "zend_partial.h"
2930

3031
#define DEBUG_COMPACT_LITERALS 0
3132

@@ -747,7 +748,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
747748
}
748749
break;
749750
case ZEND_CALLABLE_CONVERT_PARTIAL:
750-
opline->op1.num = cache_size;
751+
opline->extended_value = cache_size | (opline->extended_value & ZEND_PARTIAL_FLAGS);
751752
cache_size += 2 * sizeof(void *);
752753
break;
753754
}

Zend/Optimizer/dfa_pass.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,34 @@ static uint32_t zend_dfa_optimize_calls(zend_op_array *op_array, zend_ssa *ssa)
469469
}
470470
}
471471
}
472+
473+
if (call_info->caller_call_opline && call_info->caller_call_opline->opcode == ZEND_CALLABLE_CONVERT_PARTIAL) {
474+
/* Build a bitset of constant pre-bound PFA args: These are args whose value is alway the same for all
475+
* instances of a PFA. */
476+
uint32_t const_args = 0;
477+
for (uint32_t i = 0, l = MIN(sizeof(const_args)*CHAR_BIT, call_info->num_args); i < l; i++) {
478+
zend_op *send_opline = call_info->arg_info[i].opline;
479+
if (send_opline->op1_type == IS_CONST) {
480+
zval *value = CT_CONSTANT_EX(op_array, send_opline->op1.constant);
481+
if (Z_TYPE_P(value) == IS_CONSTANT_AST) {
482+
/* Const exprs can evaluate to non-const zvals (e.g. objects), and are not idempotent */
483+
continue;
484+
}
485+
const_args |= (UINT32_C(1) << i);
486+
}
487+
}
488+
489+
/* Pass the bitset to the ZEND_CALLABLE_CONVERT_PARTIAL opline. */
490+
zend_op *call_opline = call_info->caller_call_opline;
491+
if (call_opline->op2_type == IS_UNUSED) {
492+
call_opline->op2.num = const_args;
493+
} else {
494+
ZEND_ASSERT(call_opline->op2_type == IS_CONST);
495+
zval *zv = CT_CONSTANT_EX(op_array, call_opline->op2.constant);
496+
Z_EXTRA_P(zv) = const_args;
497+
}
498+
}
499+
472500
call_info = call_info->next_callee;
473501
} while (call_info);
474502
}

Zend/tests/lazy_objects/setRawValueWithoutLazyInitialization_no_dynamic_prop.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,6 @@ test('Proxy', $obj);
3838
?>
3939
--EXPECT--
4040
# Ghost
41-
ReflectionException: Can not use setRawValueWithoutLazyInitialization on dynamic property C::$dyn
41+
ReflectionException: Cannot use setRawValueWithoutLazyInitialization() on dynamic property C::$dyn
4242
# Proxy
43-
ReflectionException: Can not use setRawValueWithoutLazyInitialization on dynamic property C::$dyn
43+
ReflectionException: Cannot use setRawValueWithoutLazyInitialization() on dynamic property C::$dyn

Zend/tests/lazy_objects/skipLazyInitialization.phpt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,10 @@ getValue(): string(5) "value"
198198
## Property [ public static $static = 'static' ]
199199

200200
skipInitializerForProperty():
201-
ReflectionException: Can not use skipLazyInitialization on static property A::$static
201+
ReflectionException: Cannot use skipLazyInitialization() on static property A::$static
202202

203203
setRawValueWithoutLazyInitialization():
204-
ReflectionException: Can not use setRawValueWithoutLazyInitialization on static property A::$static
204+
ReflectionException: Cannot use setRawValueWithoutLazyInitialization() on static property A::$static
205205

206206
## Property [ public $noDefault = NULL ]
207207

@@ -238,10 +238,10 @@ getValue(): string(5) "value"
238238
## Property [ public virtual $virtual { get; set; } ]
239239

240240
skipInitializerForProperty():
241-
ReflectionException: Can not use skipLazyInitialization on virtual property A::$virtual
241+
ReflectionException: Cannot use skipLazyInitialization() on virtual property A::$virtual
242242

243243
setRawValueWithoutLazyInitialization():
244-
ReflectionException: Can not use setRawValueWithoutLazyInitialization on virtual property A::$virtual
244+
ReflectionException: Cannot use setRawValueWithoutLazyInitialization() on virtual property A::$virtual
245245

246246
## Property [ $dynamicProp ]
247247

@@ -295,10 +295,10 @@ getValue(): string(5) "value"
295295
## Property [ public static $static = 'static' ]
296296

297297
skipInitializerForProperty():
298-
ReflectionException: Can not use skipLazyInitialization on static property A::$static
298+
ReflectionException: Cannot use skipLazyInitialization() on static property A::$static
299299

300300
setRawValueWithoutLazyInitialization():
301-
ReflectionException: Can not use setRawValueWithoutLazyInitialization on static property A::$static
301+
ReflectionException: Cannot use setRawValueWithoutLazyInitialization() on static property A::$static
302302

303303
## Property [ public $noDefault = NULL ]
304304

@@ -335,10 +335,10 @@ getValue(): string(5) "value"
335335
## Property [ public virtual $virtual { get; set; } ]
336336

337337
skipInitializerForProperty():
338-
ReflectionException: Can not use skipLazyInitialization on virtual property A::$virtual
338+
ReflectionException: Cannot use skipLazyInitialization() on virtual property A::$virtual
339339

340340
setRawValueWithoutLazyInitialization():
341-
ReflectionException: Can not use setRawValueWithoutLazyInitialization on virtual property A::$virtual
341+
ReflectionException: Cannot use setRawValueWithoutLazyInitialization() on virtual property A::$virtual
342342

343343
## Property [ $dynamicProp ]
344344

Zend/tests/lazy_objects/skipLazyInitialization_no_dynamic_prop.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,6 @@ test('Proxy', $obj);
3838
?>
3939
--EXPECT--
4040
# Ghost
41-
ReflectionException: Can not use skipLazyInitialization on dynamic property C::$dyn
41+
ReflectionException: Cannot use skipLazyInitialization() on dynamic property C::$dyn
4242
# Proxy
43-
ReflectionException: Can not use skipLazyInitialization on dynamic property C::$dyn
43+
ReflectionException: Cannot use skipLazyInitialization() on dynamic property C::$dyn
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
--TEST--
2+
Constant argument optimization
3+
--DESCRIPTION--
4+
Pre-bound arguments that are constant can be burned into the generated
5+
op_array instead of being passed via the Closure's lexical vars.
6+
--ENV--
7+
A=1
8+
--INI--
9+
opcache.enable=1
10+
opcache.enable_cli=1
11+
opcache.optimization_level=-1
12+
--FILE--
13+
<?php
14+
15+
function f($a, $b) {
16+
var_dump([$a, $b]);
17+
}
18+
19+
function g() {
20+
return 3;
21+
}
22+
23+
function h($a, $b, $c) {
24+
var_dump([$a, $b, $c]);
25+
}
26+
27+
function i($a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8, $a9, $a10, $a11, $a12, $a13, $a14, $a15, $a16, $a17, $a18, $a19, $a20, $a21, $a22, $a23, $a24, $a25, $a26, $a27, $a28, $a29, $a30, $a31, $a32, $a33) {
28+
var_dump($a33);
29+
}
30+
31+
function print_lexical_vars($f) {
32+
$vars = new ReflectionFunction($f)->getClosureUsedVariables();
33+
if ($vars === []) {
34+
echo "no lexical vars\n";
35+
} else {
36+
$varNames = array_keys($vars);
37+
echo 'lexical vars: ', implode(', ', $varNames), "\n";
38+
}
39+
}
40+
41+
echo "# Non-constant pre-bound argument:\n";
42+
$f = f(getenv('A'), ?);
43+
print_lexical_vars($f);
44+
$f(2);
45+
46+
echo "# Constant pre-bound argument:\n";
47+
$f = f(2, ?);
48+
print_lexical_vars($f);
49+
$f(2);
50+
51+
echo "# Constant pre-bound argument (inverted):\n";
52+
$f = f(?, 2);
53+
print_lexical_vars($f);
54+
$f(1);
55+
56+
echo "# Inlined pre-bound argument:\n";
57+
$f = f(g(), ?);
58+
print_lexical_vars($f);
59+
$f(2);
60+
61+
echo "# Constexpr pre-bound argument:\n";
62+
const B = 4;
63+
$f = f(B, ?);
64+
print_lexical_vars($f);
65+
$f(2);
66+
67+
echo "# Mixed arguments:\n";
68+
$f = h(5, getenv('A'), ?);
69+
print_lexical_vars($f);
70+
$f(2);
71+
72+
echo "# Constant array pre-bound argument:\n";
73+
$f = f(['foo' => 'bar'], ?);
74+
print_lexical_vars($f);
75+
$f(2);
76+
77+
echo "# Named arguments:\n";
78+
$f = h(1, c: ?, b: ?);
79+
print_lexical_vars($f);
80+
$f(2, 3);
81+
82+
echo "# Many arguments (optimization can not be applied for all args) :\n";
83+
$f = i(?, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33);
84+
print_lexical_vars($f);
85+
$f(33);
86+
87+
?>
88+
--EXPECT--
89+
# Non-constant pre-bound argument:
90+
lexical vars: a
91+
array(2) {
92+
[0]=>
93+
string(1) "1"
94+
[1]=>
95+
int(2)
96+
}
97+
# Constant pre-bound argument:
98+
no lexical vars
99+
array(2) {
100+
[0]=>
101+
int(2)
102+
[1]=>
103+
int(2)
104+
}
105+
# Constant pre-bound argument (inverted):
106+
no lexical vars
107+
array(2) {
108+
[0]=>
109+
int(1)
110+
[1]=>
111+
int(2)
112+
}
113+
# Inlined pre-bound argument:
114+
no lexical vars
115+
array(2) {
116+
[0]=>
117+
int(3)
118+
[1]=>
119+
int(2)
120+
}
121+
# Constexpr pre-bound argument:
122+
lexical vars: a
123+
array(2) {
124+
[0]=>
125+
int(4)
126+
[1]=>
127+
int(2)
128+
}
129+
# Mixed arguments:
130+
lexical vars: b
131+
array(3) {
132+
[0]=>
133+
int(5)
134+
[1]=>
135+
string(1) "1"
136+
[2]=>
137+
int(2)
138+
}
139+
# Constant array pre-bound argument:
140+
no lexical vars
141+
array(2) {
142+
[0]=>
143+
array(1) {
144+
["foo"]=>
145+
string(3) "bar"
146+
}
147+
[1]=>
148+
int(2)
149+
}
150+
# Named arguments:
151+
no lexical vars
152+
array(3) {
153+
[0]=>
154+
int(1)
155+
[1]=>
156+
int(3)
157+
[2]=>
158+
int(2)
159+
}
160+
# Many arguments (optimization can not be applied for all args) :
161+
lexical vars: a33
162+
int(33)

0 commit comments

Comments
 (0)