mirror of
https://github.com/php/php-src.git
synced 2026-10-28 17:56:50 +08:00
[PFA 3/n] Support PFA in const exprs (#22785)
* Use a pointer to the declaring opline->lineno as unique addr, instead of the declaring opline itself zend_partial_create() takes a 'zend_op* declaring_opline' parameter for the purpose of building a cache key: the opline address is unique to this PFA as long as it's in SHM. However the declaring opline is not available when evaluating a PFA AST. Replace the parameter by 'uint32_t* declaring_lineno'. Callers can pass '&zend_op->lineno' or '&ast->lineno': Both are unique to the related PFA. * zend_partial_create(): Remove the dependency on the declaring op_array The declaring op_array is used for multiple purposes: * Generating a PFA name * Finding the filename * Finding whether op_array is cached, and therefore whether the PFA should be cached too However it's not available when evaluating a PFA AST. Remove the declaring_op_array argument, and pass the relevant information directly: * Generate the PFA name at compile time, pass it as argument to zend_partial_create() * Pass the filename and a cacheable flag as argument to zend_partial_create() * Support for PFA in constant expressions
This commit is contained in:
1 parent
99d2e3c166
commit
2d359a40b7
36 files changed
+901
-308
No files matched your search
@@ -26,6 +26,7 @@
|
||||
#include "zend_execute.h"
|
||||
#include "zend_vm.h"
|
||||
#include "zend_extensions.h"
|
||||
#include "zend_partial.h"
|
||||
|
||||
#define DEBUG_COMPACT_LITERALS 0
|
||||
|
||||
@@ -747,7 +748,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
|
||||
}
|
||||
break;
|
||||
case ZEND_CALLABLE_CONVERT_PARTIAL:
|
||||
opline->op1.num = cache_size;
|
||||
opline->extended_value = cache_size | (opline->extended_value & ZEND_PARTIAL_FLAGS);
|
||||
cache_size += 2 * sizeof(void *);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
--TEST--
|
||||
PFA in constexpr 001
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function f($a = g("foo", ?)) {
|
||||
return $a(1);
|
||||
}
|
||||
|
||||
function g(string $a, int $b) {
|
||||
return [$a, $b];
|
||||
}
|
||||
|
||||
class C {
|
||||
static function f($a = self::g("foo", ?)) {
|
||||
return $a(1);
|
||||
}
|
||||
|
||||
static function g(string $a, int $b) {
|
||||
return [$a, $b];
|
||||
}
|
||||
}
|
||||
|
||||
var_dump(f());
|
||||
var_dump(f());
|
||||
var_dump(C::f());
|
||||
var_dump(C::f());
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(3) "foo"
|
||||
[1]=>
|
||||
int(1)
|
||||
}
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(3) "foo"
|
||||
[1]=>
|
||||
int(1)
|
||||
}
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(3) "foo"
|
||||
[1]=>
|
||||
int(1)
|
||||
}
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(3) "foo"
|
||||
[1]=>
|
||||
int(1)
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
PFA in constexpr: non-constexpr arg
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function f($a = g(new stdClass, $x, ?)) {
|
||||
return $a(1);
|
||||
}
|
||||
|
||||
function g(string $a, int $b) {
|
||||
return [$a, $b];
|
||||
}
|
||||
|
||||
try {
|
||||
var_dump(f());
|
||||
} catch (Error $e) {
|
||||
echo $e::class, ": ", $e->getMessage(), " on line ", $e->getLine();
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Constant expression contains invalid operations in %s on line %d
|
||||
@@ -0,0 +1,25 @@
|
||||
--TEST--
|
||||
PFA in constexpr: named args
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function f($a = g(c: ?, ...)) {
|
||||
return $a(1.5, b: 3);
|
||||
}
|
||||
|
||||
function g(string $a = 'hello', int $b = 2, float $c = 0) {
|
||||
return [$a, $b, $c];
|
||||
}
|
||||
|
||||
var_dump(f());
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
array(3) {
|
||||
[0]=>
|
||||
string(5) "hello"
|
||||
[1]=>
|
||||
int(3)
|
||||
[2]=>
|
||||
float(1.5)
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
--TEST--
|
||||
PFA in constexpr: extra named args
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function f($a = g(?, foo: 'bar', ...)) {
|
||||
return $a(1, bar: 'baz');
|
||||
}
|
||||
|
||||
function g(...$args) {
|
||||
return [$args];
|
||||
}
|
||||
|
||||
var_dump(f());
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
array(1) {
|
||||
[0]=>
|
||||
array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
["foo"]=>
|
||||
string(3) "bar"
|
||||
["bar"]=>
|
||||
string(3) "baz"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
PFA in constexpr: variadic placeholder must be after positional params
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function f($a = g(..., 1)) {
|
||||
}
|
||||
|
||||
f();
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Variadic placeholder must be last in %s on line %d
|
||||
@@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
PFA in constexpr: variadic placeholder must be after named params
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function f($a = g(..., foo: 1)) {
|
||||
}
|
||||
|
||||
f();
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Variadic placeholder must be last in %s on line %d
|
||||
@@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
PFA in constexpr: variadic placeholder may only appear once
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function f($a = g(..., ...)) {
|
||||
}
|
||||
|
||||
f();
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Variadic placeholder may only appear once in %s on line %d
|
||||
@@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
PFA in constexpr: variadic placeholder not allowed to be named
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function f($a = g(foo: ...)) {
|
||||
}
|
||||
|
||||
f();
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Parse error: syntax error, unexpected token "..." in %s on line %d
|
||||
@@ -0,0 +1,20 @@
|
||||
--TEST--
|
||||
PFA in constexpr: error during partial creation
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function f($a = g(?)) {
|
||||
}
|
||||
|
||||
function g($a, $b) {
|
||||
}
|
||||
|
||||
try {
|
||||
f();
|
||||
} catch (Error $e) {
|
||||
echo $e::class, ": ", $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
ArgumentCountError: Partial application of g() expects exactly 2 arguments, 1 given
|
||||
@@ -0,0 +1,43 @@
|
||||
--TEST--
|
||||
PFA in constexpr: error during arg list evaluation
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function f($a = g(strlen(?), e: strlen(?), a: strlen(?), ...)) {
|
||||
}
|
||||
|
||||
function g($a, $b, $c, $d, $e) {
|
||||
}
|
||||
|
||||
function h($a = i(strlen(?), a: strlen(?), b: invalid(?), ...)) {
|
||||
}
|
||||
|
||||
function i(...$args) {
|
||||
}
|
||||
|
||||
function j($a = g(c: new stdClass, ...), $b = g(c: MISSING_CONST + 1, ...)) {
|
||||
}
|
||||
|
||||
try {
|
||||
f();
|
||||
} catch (Error $e) {
|
||||
echo $e::class, ": ", $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
h();
|
||||
} catch (Error $e) {
|
||||
echo $e::class, ": ", $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
j();
|
||||
} catch (Error $e) {
|
||||
echo $e::class, ": ", $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Error: Named parameter $a overwrites previous argument
|
||||
Error: Call to undefined function invalid()
|
||||
Error: Undefined constant "MISSING_CONST"
|
||||
@@ -0,0 +1,38 @@
|
||||
--TEST--
|
||||
PFA in constexpr: nested const expr
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function f($a = g(new stdClass, g(...), ...)) {
|
||||
return $a(1);
|
||||
}
|
||||
|
||||
function g($a, $b, $c) {
|
||||
return [$a, $b, $c];
|
||||
}
|
||||
|
||||
var_dump(f());
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(3) {
|
||||
[0]=>
|
||||
object(stdClass)#%d (0) {
|
||||
}
|
||||
[1]=>
|
||||
object(Closure)#%d (2) {
|
||||
["function"]=>
|
||||
string(1) "g"
|
||||
["parameter"]=>
|
||||
array(3) {
|
||||
["$a"]=>
|
||||
string(10) "<required>"
|
||||
["$b"]=>
|
||||
string(10) "<required>"
|
||||
["$c"]=>
|
||||
string(10) "<required>"
|
||||
}
|
||||
}
|
||||
[2]=>
|
||||
int(1)
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
--TEST--
|
||||
PFA in constexpr: sites
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
#[Attribute]
|
||||
class A {
|
||||
function __construct(public mixed $fn) {}
|
||||
}
|
||||
|
||||
#[A(strlen(?))]
|
||||
class C {
|
||||
const CC = strlen(?);
|
||||
|
||||
#[A(strlen(?))]
|
||||
function f($arg = strlen(?)) {
|
||||
return $arg;
|
||||
}
|
||||
}
|
||||
|
||||
const CC = strlen(?);
|
||||
|
||||
echo "# Class const\n";
|
||||
var_dump((C::CC)('hello'));
|
||||
echo "# Const\n";
|
||||
var_dump((CC)('hello'));
|
||||
echo "# Class attr\n";
|
||||
var_dump((new ReflectionClass(C::class)->getAttributes(A::class)[0]->newInstance()->fn)('hello'));
|
||||
echo "# Method attr\n";
|
||||
var_dump((new ReflectionMethod(C::class, 'f')->getAttributes(A::class)[0]->newInstance()->fn)('hello'));
|
||||
echo "# Method default value\n";
|
||||
var_dump((new C()->f())('hello'));
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
# Class const
|
||||
int(5)
|
||||
# Const
|
||||
int(5)
|
||||
# Class attr
|
||||
int(5)
|
||||
# Method attr
|
||||
int(5)
|
||||
# Method default value
|
||||
int(5)
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
#[Attribute]
|
||||
class A {
|
||||
function __construct(public mixed $fn) {}
|
||||
}
|
||||
|
||||
#[A(strlen(?))]
|
||||
class C {
|
||||
const CC = strlen(?);
|
||||
|
||||
#[A(strlen(?))]
|
||||
function f($arg = strlen(?)) {
|
||||
return $arg;
|
||||
}
|
||||
}
|
||||
|
||||
const CC = strlen(?);
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,33 @@
|
||||
--TEST--
|
||||
PFA in constexpr: preloading
|
||||
--INI--
|
||||
opcache.enable=1
|
||||
opcache.enable_cli=1
|
||||
opcache.optimization_level=-1
|
||||
opcache.preload={PWD}/constexpr_015.inc
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
echo "# Class const\n";
|
||||
var_dump((C::CC)('hello'));
|
||||
echo "# Class attr\n";
|
||||
var_dump((new ReflectionClass(C::class)->getAttributes(A::class)[0]->newInstance()->fn)('hello'));
|
||||
echo "# Method attr\n";
|
||||
var_dump((new ReflectionMethod(C::class, 'f')->getAttributes(A::class)[0]->newInstance()->fn)('hello'));
|
||||
echo "# Method default value\n";
|
||||
var_dump((new C()->f())('hello'));
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
# Class const
|
||||
int(5)
|
||||
# Class attr
|
||||
int(5)
|
||||
# Method attr
|
||||
int(5)
|
||||
# Method default value
|
||||
int(5)
|
||||
@@ -37,7 +37,7 @@ $_main:
|
||||
0005 INIT_FCALL_BY_NAME 2 string("foo")
|
||||
0006 SEND_PLACEHOLDER 1
|
||||
0007 SEND_PLACEHOLDER 2
|
||||
0008 T1 = CALLABLE_CONVERT_PARTIAL %d
|
||||
0008 T1 = CALLABLE_CONVERT_PARTIAL %d string("{closure:%s}")
|
||||
0009 INIT_DYNAMIC_CALL 1 T1
|
||||
0010 SEND_VAL_EX int(2) 1
|
||||
0011 DO_FCALL
|
||||
|
||||
@@ -37,7 +37,7 @@ $_main:
|
||||
0005 INIT_FCALL_BY_NAME 0 string("foo")
|
||||
0006 SEND_PLACEHOLDER string("a")
|
||||
0007 SEND_PLACEHOLDER string("b")
|
||||
0008 T1 = CALLABLE_CONVERT_PARTIAL %d array(...)
|
||||
0008 T1 = CALLABLE_CONVERT_PARTIAL %d string("{closure:%s}") array(...)
|
||||
0009 INIT_DYNAMIC_CALL 1 T1
|
||||
0010 SEND_VAL_EX int(2) 1
|
||||
0011 DO_FCALL
|
||||
|
||||
@@ -36,7 +36,7 @@ $_main:
|
||||
0004 DECLARE_FUNCTION string("foo") 0
|
||||
0005 INIT_FCALL_BY_NAME 0 string("foo")
|
||||
0006 SEND_VAL_EX int(1) string("a")
|
||||
0007 T1 = CALLABLE_CONVERT_PARTIAL %d
|
||||
0007 T1 = CALLABLE_CONVERT_PARTIAL %d string("{closure:%s}")
|
||||
0008 INIT_DYNAMIC_CALL 1 T1
|
||||
0009 SEND_VAL_EX int(2) 1
|
||||
0010 DO_FCALL
|
||||
|
||||
@@ -32,7 +32,7 @@ $_main:
|
||||
0004 DECLARE_FUNCTION string("foo") 0
|
||||
0005 INIT_FCALL_BY_NAME 0 string("foo")
|
||||
0006 SEND_VAL_EX int(2) string("b")
|
||||
0007 T0 = CALLABLE_CONVERT_PARTIAL 3
|
||||
0007 T0 = CALLABLE_CONVERT_PARTIAL %d string("{closure:%s}")
|
||||
0008 INIT_DYNAMIC_CALL 1 T0
|
||||
0009 SEND_VAL_EX int(1) 1
|
||||
0010 DO_FCALL
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
--TEST--
|
||||
PFA RFC examples: "Constant expressions" section
|
||||
--XFAIL--
|
||||
PFA in constant expressions not implemented yet
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
|
||||
+137
-6
@@ -25,6 +25,7 @@
|
||||
#include "zend_closures.h"
|
||||
#include "zend_constants.h"
|
||||
#include "zend_enum.h"
|
||||
#include "zend_partial.h"
|
||||
|
||||
ZEND_API zend_ast_process_t zend_ast_process = NULL;
|
||||
|
||||
@@ -60,6 +61,8 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_fcc(zend_ast *args) {
|
||||
ast->kind = ZEND_AST_CALLABLE_CONVERT;
|
||||
ast->attr = 0;
|
||||
ast->lineno = CG(zend_lineno);
|
||||
ast->filename = NULL;
|
||||
ast->name = NULL;
|
||||
ast->args = args;
|
||||
ZEND_MAP_PTR_INIT(ast->fptr, NULL);
|
||||
|
||||
@@ -671,6 +674,82 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_ex(
|
||||
return r;
|
||||
}
|
||||
|
||||
static zend_execute_data *zend_ast_evaluate_arg_list(
|
||||
zend_function *func,
|
||||
zend_ast_list *args_ast,
|
||||
zend_class_entry *scope,
|
||||
void *object_or_called_scope,
|
||||
bool *short_circuited_ptr,
|
||||
zend_ast_evaluate_ctx *ctx,
|
||||
zend_array **named_positions_ptr,
|
||||
bool *uses_variadic_placeholder
|
||||
) {
|
||||
zend_execute_data *frame = zend_vm_stack_push_call_frame_ex(
|
||||
zend_vm_calc_used_stack(args_ast->children, func),
|
||||
0, func, 0, object_or_called_scope);
|
||||
|
||||
for (uint32_t i = 0; i < args_ast->children; i++) {
|
||||
zend_ast *arg_ast = args_ast->child[i];
|
||||
uint32_t arg_num = i + 1;
|
||||
zval *arg;
|
||||
zend_string *arg_name = NULL;
|
||||
|
||||
if (arg_ast->kind == ZEND_AST_NAMED_ARG) {
|
||||
void *cache_slot[2] = {0};
|
||||
arg_name = zend_ast_get_str(arg_ast->child[0]);
|
||||
arg = zend_handle_named_arg(&frame, arg_name, &arg_num, (void**)&cache_slot);
|
||||
if (!arg) {
|
||||
goto fail;
|
||||
}
|
||||
if (named_positions_ptr) {
|
||||
if (!*named_positions_ptr) {
|
||||
*named_positions_ptr = zend_new_array(0);
|
||||
}
|
||||
zval tmp;
|
||||
ZVAL_LONG(&tmp, zend_hash_num_elements(*named_positions_ptr));
|
||||
zend_hash_add(*named_positions_ptr, arg_name, &tmp);
|
||||
}
|
||||
arg_ast = arg_ast->child[1];
|
||||
} else {
|
||||
arg = ZEND_CALL_VAR_NUM(frame, ZEND_CALL_NUM_ARGS(frame));
|
||||
}
|
||||
|
||||
if (arg_ast->kind == ZEND_AST_PLACEHOLDER_ARG) {
|
||||
if (arg_ast->attr == ZEND_PLACEHOLDER_VARIADIC) {
|
||||
if (uses_variadic_placeholder) {
|
||||
*uses_variadic_placeholder = true;
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
Z_TYPE_INFO_P(arg) = _IS_PLACEHOLDER;
|
||||
}
|
||||
} else {
|
||||
if (zend_ast_evaluate_ex(arg, arg_ast, scope, short_circuited_ptr, ctx) == FAILURE) {
|
||||
ZVAL_UNDEF(arg);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (!arg_name) {
|
||||
ZEND_CALL_NUM_ARGS(frame)++;
|
||||
}
|
||||
}
|
||||
|
||||
return frame;
|
||||
|
||||
fail:
|
||||
for (uint32_t i = 0, num_args = ZEND_CALL_NUM_ARGS(frame); i < num_args; i++) {
|
||||
zval_ptr_dtor(ZEND_CALL_VAR_NUM(frame, i));
|
||||
}
|
||||
if (ZEND_CALL_INFO(frame) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
|
||||
zend_array_destroy(frame->extra_named_params);
|
||||
}
|
||||
zend_vm_stack_free_call_frame(frame);
|
||||
if (named_positions_ptr && *named_positions_ptr) {
|
||||
zend_array_destroy(*named_positions_ptr);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
|
||||
zval *result,
|
||||
zend_ast *ast,
|
||||
@@ -1155,10 +1234,6 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
|
||||
|
||||
zend_ast_list *args = zend_ast_get_list(fcc_ast->args);
|
||||
ZEND_ASSERT(args->children > 0);
|
||||
if (args->children != 1 || args->child[0]->attr != ZEND_PLACEHOLDER_VARIADIC) {
|
||||
/* TODO: PFAs */
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Constant expression contains invalid operations");
|
||||
}
|
||||
|
||||
switch (ast->kind) {
|
||||
case ZEND_AST_CALL: {
|
||||
@@ -1248,9 +1323,46 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
|
||||
default: ZEND_UNREACHABLE();
|
||||
}
|
||||
|
||||
zend_create_fake_closure(result, fptr, fptr->common.scope, called_scope, NULL);
|
||||
bool is_fcc = args->children == 1 && args->child[0]->attr == ZEND_PLACEHOLDER_VARIADIC;
|
||||
|
||||
return SUCCESS;
|
||||
if (is_fcc) {
|
||||
zend_create_fake_closure(result, fptr, fptr->common.scope, called_scope, NULL);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
zend_array *named_positions = NULL;
|
||||
bool uses_variadic_placeholder = false;
|
||||
zend_execute_data *frame = zend_ast_evaluate_arg_list(
|
||||
fptr, args, scope, called_scope, short_circuited_ptr, ctx,
|
||||
&named_positions, &uses_variadic_placeholder);
|
||||
if (!frame) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
void *cache_slot[2] = {0};
|
||||
zend_array *extra_named_params = ZEND_CALL_INFO(frame) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS
|
||||
? frame->extra_named_params
|
||||
: NULL;
|
||||
uint32_t flags = (fcc_ast->attr & ZEND_PARTIAL_CACHEABLE_IN_SHM);
|
||||
if (uses_variadic_placeholder) {
|
||||
flags |= ZEND_PARTIAL_USES_VARIADIC_PLACEHOLDER;
|
||||
}
|
||||
zend_partial_create(result, &frame->This, fptr,
|
||||
ZEND_CALL_NUM_ARGS(frame), ZEND_CALL_ARG(frame, 1),
|
||||
extra_named_params, named_positions,
|
||||
fcc_ast->filename, &ast->lineno,
|
||||
(void**)cache_slot, fcc_ast->name, flags);
|
||||
|
||||
if (named_positions) {
|
||||
zend_array_release(named_positions);
|
||||
}
|
||||
if (extra_named_params) {
|
||||
zend_array_release(extra_named_params);
|
||||
}
|
||||
zend_vm_stack_free_call_frame(frame);
|
||||
|
||||
return EG(exception) ? FAILURE : SUCCESS;
|
||||
}
|
||||
case ZEND_AST_OP_ARRAY:
|
||||
{
|
||||
@@ -1425,6 +1537,16 @@ static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
|
||||
new->kind = old->kind;
|
||||
new->attr = old->attr;
|
||||
new->lineno = old->lineno;
|
||||
if (old->filename) {
|
||||
new->filename = zend_string_copy(old->filename);
|
||||
} else {
|
||||
new->filename = NULL;
|
||||
}
|
||||
if (old->name) {
|
||||
new->name = zend_string_copy(old->name);
|
||||
} else {
|
||||
new->name = NULL;
|
||||
}
|
||||
ZEND_MAP_PTR_INIT(new->fptr, ZEND_MAP_PTR(old->fptr));
|
||||
buf = (void*)((char*)buf + sizeof(zend_ast_fcc));
|
||||
new->args = buf;
|
||||
@@ -1525,6 +1647,12 @@ tail_call:
|
||||
} else if (EXPECTED(ast->kind == ZEND_AST_CALLABLE_CONVERT)) {
|
||||
zend_ast_fcc *fcc_ast = (zend_ast_fcc*) ast;
|
||||
|
||||
if (fcc_ast->filename) {
|
||||
zend_string_release_ex(fcc_ast->filename, 0);
|
||||
}
|
||||
if (fcc_ast->name) {
|
||||
zend_string_release_ex(fcc_ast->name, 0);
|
||||
}
|
||||
ast = fcc_ast->args;
|
||||
goto tail_call;
|
||||
}
|
||||
@@ -1543,6 +1671,9 @@ ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn, void *contex
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
fn(&list->child[i], context);
|
||||
}
|
||||
} else if (ast->kind == ZEND_AST_CALLABLE_CONVERT) {
|
||||
zend_ast_fcc *fcc_ast = (zend_ast_fcc*)ast;
|
||||
fn(&fcc_ast->args, context);
|
||||
} else if (zend_ast_is_decl(ast)) {
|
||||
/* Not implemented. */
|
||||
ZEND_UNREACHABLE();
|
||||
|
||||
@@ -233,6 +233,8 @@ typedef struct _zend_ast_fcc {
|
||||
zend_ast_kind kind; /* Type of the node (ZEND_AST_* enum constant) */
|
||||
zend_ast_attr attr; /* Additional attribute, use depending on node type */
|
||||
uint32_t lineno; /* Line number */
|
||||
zend_string *filename;
|
||||
zend_string *name;
|
||||
zend_ast *args;
|
||||
ZEND_MAP_PTR_DEF(zend_function *, fptr);
|
||||
} zend_ast_fcc;
|
||||
|
||||
+91
-27
@@ -40,6 +40,7 @@
|
||||
#include "zend_call_stack.h"
|
||||
#include "zend_frameless_function.h"
|
||||
#include "zend_property_hooks.h"
|
||||
#include "zend_partial.h"
|
||||
|
||||
#define SET_NODE(target, src) do { \
|
||||
target ## _type = (src)->op_type; \
|
||||
@@ -4088,7 +4089,50 @@ ZEND_API uint8_t zend_get_call_op(const zend_op *init_op, const zend_function *f
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_compile_call_partial(znode *result, uint32_t arg_count,
|
||||
static zend_string *zend_compile_partial_name(const zend_op_array *declaring_op_array,
|
||||
const uint32_t declaring_lineno)
|
||||
{
|
||||
/* We attempt to generate a name that hints at where the PFA was created,
|
||||
* similarly to Closures (GH-13550).
|
||||
* We do not attempt to make the name unique. */
|
||||
|
||||
zend_string *filename = declaring_op_array->filename;
|
||||
uint32_t start_lineno = declaring_lineno;
|
||||
|
||||
zend_string *class = zend_empty_string;
|
||||
zend_string *separator = zend_empty_string;
|
||||
zend_string *function = filename;
|
||||
const char *parens = "";
|
||||
|
||||
if (declaring_op_array->function_name) {
|
||||
function = declaring_op_array->function_name;
|
||||
if (declaring_op_array->fn_flags & ZEND_ACC_CLOSURE) {
|
||||
/* If the parent function is a closure, don't redundantly
|
||||
* add the classname and parentheses. */
|
||||
} else {
|
||||
parens = "()";
|
||||
|
||||
if (declaring_op_array->scope && declaring_op_array->scope->name) {
|
||||
class = declaring_op_array->scope->name;
|
||||
separator = ZSTR_KNOWN(ZEND_STR_PAAMAYIM_NEKUDOTAYIM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zend_string *name = zend_strpprintf_unchecked(
|
||||
0,
|
||||
"{closure:pfa:%S%S%S%s:%" PRIu32 "}",
|
||||
class,
|
||||
separator,
|
||||
function,
|
||||
parens,
|
||||
start_lineno
|
||||
);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
static void zend_compile_call_partial(znode *result, zend_ast_fcc *fcc_ast, uint32_t arg_count,
|
||||
bool may_have_extra_named_args, bool uses_variadic_placeholder,
|
||||
zval *named_positions, uint32_t opnum_init, const zend_function *fbc) {
|
||||
|
||||
@@ -4105,15 +4149,16 @@ static void zend_compile_call_partial(znode *result, uint32_t arg_count,
|
||||
zend_op *opline = zend_emit_op_tmp(result, ZEND_CALLABLE_CONVERT_PARTIAL,
|
||||
NULL, NULL);
|
||||
|
||||
opline->op1.num = zend_alloc_cache_slots(2);
|
||||
opline->extended_value = zend_alloc_cache_slots(2);
|
||||
|
||||
if (may_have_extra_named_args) {
|
||||
opline->extended_value = ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS;
|
||||
}
|
||||
if (uses_variadic_placeholder) {
|
||||
opline->extended_value |= ZEND_FCALL_USES_VARIADIC_PLACEHOLDER;
|
||||
opline->extended_value |= ZEND_PARTIAL_USES_VARIADIC_PLACEHOLDER;
|
||||
}
|
||||
|
||||
zend_string *name = zend_compile_partial_name(CG(active_op_array), opline->lineno);
|
||||
opline->op1.constant = zend_add_literal_string(&name);
|
||||
opline->op1_type = IS_CONST;
|
||||
|
||||
if (!Z_ISUNDEF_P(named_positions)) {
|
||||
opline->op2.constant = zend_add_literal(named_positions);
|
||||
opline->op2_type = IS_CONST;
|
||||
@@ -4156,7 +4201,8 @@ static bool zend_compile_call_common(znode *result, zend_ast *args_ast, const ze
|
||||
return true;
|
||||
}
|
||||
|
||||
args_ast = ((zend_ast_fcc*)args_ast)->args;
|
||||
zend_ast_fcc *fcc_ast = (zend_ast_fcc*)args_ast;
|
||||
args_ast = fcc_ast->args;
|
||||
|
||||
bool may_have_extra_named_args;
|
||||
bool uses_variadic_placeholder;
|
||||
@@ -4168,7 +4214,7 @@ static bool zend_compile_call_common(znode *result, zend_ast *args_ast, const ze
|
||||
&may_have_extra_named_args, true, &uses_variadic_placeholder,
|
||||
&named_positions);
|
||||
|
||||
zend_compile_call_partial(result, arg_count,
|
||||
zend_compile_call_partial(result, fcc_ast, arg_count,
|
||||
may_have_extra_named_args, uses_variadic_placeholder,
|
||||
&named_positions, opnum_init, fbc);
|
||||
|
||||
@@ -11856,7 +11902,8 @@ static bool zend_is_allowed_in_const_expr(zend_ast_kind kind) /* {{{ */
|
||||
|| kind == ZEND_AST_NAMED_ARG
|
||||
|| kind == ZEND_AST_PROP || kind == ZEND_AST_NULLSAFE_PROP
|
||||
|| kind == ZEND_AST_CLOSURE
|
||||
|| kind == ZEND_AST_CALL || kind == ZEND_AST_STATIC_CALL || kind == ZEND_AST_CALLABLE_CONVERT;
|
||||
|| kind == ZEND_AST_CALL || kind == ZEND_AST_STATIC_CALL || kind == ZEND_AST_CALLABLE_CONVERT
|
||||
|| kind == ZEND_AST_PLACEHOLDER_ARG;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -12021,24 +12068,20 @@ static void zend_compile_const_expr_closure(zend_ast **ast_ptr)
|
||||
|
||||
static void zend_compile_const_expr_fcc(zend_ast **ast_ptr)
|
||||
{
|
||||
zend_ast **args_ast;
|
||||
switch ((*ast_ptr)->kind) {
|
||||
case ZEND_AST_CALL:
|
||||
args_ast = &(*ast_ptr)->child[1];
|
||||
break;
|
||||
case ZEND_AST_STATIC_CALL:
|
||||
args_ast = &(*ast_ptr)->child[2];
|
||||
break;
|
||||
default: ZEND_UNREACHABLE();
|
||||
}
|
||||
if ((*args_ast)->kind != ZEND_AST_CALLABLE_CONVERT) {
|
||||
zend_ast *args_ast = zend_ast_call_get_args(*ast_ptr);
|
||||
|
||||
if (args_ast->kind != ZEND_AST_CALLABLE_CONVERT) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Constant expression contains invalid operations");
|
||||
}
|
||||
|
||||
zend_ast_list *args = zend_ast_get_list(((zend_ast_fcc*)*args_ast)->args);
|
||||
if (args->children != 1 || args->child[0]->attr != ZEND_PLACEHOLDER_VARIADIC) {
|
||||
// TODO: PFAs
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Constant expression contains invalid operations");
|
||||
zend_ast_fcc *fcc = (zend_ast_fcc*)args_ast;
|
||||
|
||||
zend_ast_list *args = zend_ast_get_list(fcc->args);
|
||||
bool is_fcc = args->children == 1 && args->child[0]->attr == ZEND_PLACEHOLDER_VARIADIC;
|
||||
|
||||
if (!is_fcc) {
|
||||
fcc->filename = zend_string_copy(CG(active_op_array)->filename);
|
||||
fcc->name = zend_compile_partial_name(CG(active_op_array), fcc->lineno);
|
||||
}
|
||||
|
||||
switch ((*ast_ptr)->kind) {
|
||||
@@ -12080,6 +12123,7 @@ static void zend_compile_const_expr_args(zend_ast **ast_ptr)
|
||||
{
|
||||
zend_ast_list *list = zend_ast_get_list(*ast_ptr);
|
||||
bool uses_named_args = false;
|
||||
bool uses_variadic_placeholder = false;
|
||||
for (uint32_t i = 0; i < list->children; i++) {
|
||||
const zend_ast *arg = list->child[i];
|
||||
if (arg->kind == ZEND_AST_UNPACK) {
|
||||
@@ -12088,11 +12132,31 @@ static void zend_compile_const_expr_args(zend_ast **ast_ptr)
|
||||
}
|
||||
if (arg->kind == ZEND_AST_NAMED_ARG) {
|
||||
uses_named_args = true;
|
||||
} else if (uses_named_args) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR,
|
||||
"Cannot use positional argument after named argument");
|
||||
if (uses_variadic_placeholder) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Variadic placeholder must be last");
|
||||
}
|
||||
} else {
|
||||
bool is_variadic_placeholder = arg->kind == ZEND_AST_PLACEHOLDER_ARG
|
||||
&& arg->attr == ZEND_PLACEHOLDER_VARIADIC;
|
||||
|
||||
if (uses_named_args && !is_variadic_placeholder) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use positional argument after named argument");
|
||||
}
|
||||
|
||||
if (uses_variadic_placeholder) {
|
||||
if (is_variadic_placeholder) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Variadic placeholder may only appear once");
|
||||
} else {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Variadic placeholder must be last");
|
||||
}
|
||||
}
|
||||
|
||||
if (is_variadic_placeholder) {
|
||||
uses_variadic_placeholder = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uses_named_args) {
|
||||
list->attr = 1;
|
||||
}
|
||||
|
||||
@@ -1121,7 +1121,6 @@ ZEND_API zend_string *zend_type_to_string(zend_type type);
|
||||
#define ZEND_THROW_IS_EXPR 1u
|
||||
|
||||
#define ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS (1<<0)
|
||||
#define ZEND_FCALL_USES_VARIADIC_PLACEHOLDER (1<<1)
|
||||
|
||||
/* The send mode, the is_variadic, the is_promoted, and the is_tentative flags are stored as part of zend_type */
|
||||
#define _ZEND_SEND_MODE_SHIFT _ZEND_TYPE_EXTRA_FLAGS_SHIFT
|
||||
|
||||
+22
-62
@@ -51,6 +51,7 @@
|
||||
#include "zend_closures.h"
|
||||
#include "zend_attributes.h"
|
||||
#include "zend_exceptions.h"
|
||||
#include "zend_partial.h"
|
||||
#include "ext/opcache/ZendAccelerator.h"
|
||||
|
||||
static zend_always_inline bool Z_IS_PLACEHOLDER_P(const zval *p) {
|
||||
@@ -502,49 +503,6 @@ static zend_ast *zp_param_attributes_to_ast(zend_function *function,
|
||||
return attributes_ast;
|
||||
}
|
||||
|
||||
static zend_string *zp_pfa_name(const zend_op_array *declaring_op_array,
|
||||
const zend_op *declaring_opline)
|
||||
{
|
||||
/* We attempt to generate a name that hints at where the PFA was created,
|
||||
* similarly to Closures (GH-13550).
|
||||
* We do not attempt to make the name unique. */
|
||||
|
||||
zend_string *filename = declaring_op_array->filename;
|
||||
uint32_t start_lineno = declaring_opline->lineno;
|
||||
|
||||
zend_string *class = zend_empty_string;
|
||||
zend_string *separator = zend_empty_string;
|
||||
zend_string *function = filename;
|
||||
const char *parens = "";
|
||||
|
||||
if (declaring_op_array->function_name) {
|
||||
function = declaring_op_array->function_name;
|
||||
if (declaring_op_array->fn_flags & ZEND_ACC_CLOSURE) {
|
||||
/* If the parent function is a closure, don't redundantly
|
||||
* add the classname and parentheses. */
|
||||
} else {
|
||||
parens = "()";
|
||||
|
||||
if (declaring_op_array->scope && declaring_op_array->scope->name) {
|
||||
class = declaring_op_array->scope->name;
|
||||
separator = ZSTR_KNOWN(ZEND_STR_PAAMAYIM_NEKUDOTAYIM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zend_string *name = zend_strpprintf_unchecked(
|
||||
0,
|
||||
"{closure:pfa:%S%S%S%s:%" PRIu32 "}",
|
||||
class,
|
||||
separator,
|
||||
function,
|
||||
parens,
|
||||
start_lineno
|
||||
);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/* Generate the AST for calling the actual function */
|
||||
static zend_ast *zp_compile_forwarding_call(
|
||||
zval *this_ptr, zend_function *function,
|
||||
@@ -701,9 +659,9 @@ static uint32_t zp_compute_num_required(const zend_function *function,
|
||||
static zend_op_array *zp_compile(zval *this_ptr, zend_function *function,
|
||||
uint32_t argc, zval *argv, zend_array *extra_named_params,
|
||||
const zend_array *named_positions,
|
||||
const zend_op_array *declaring_op_array,
|
||||
const zend_op *declaring_opline, void **cache_slot,
|
||||
bool uses_variadic_placeholder) {
|
||||
zend_string *declaring_filename,
|
||||
const uint32_t *declaring_lineno_ptr, void **cache_slot,
|
||||
zend_string *pfa_name, uint32_t flags) {
|
||||
|
||||
zend_op_array *op_array = NULL;
|
||||
|
||||
@@ -713,6 +671,8 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool uses_variadic_placeholder = flags & ZEND_PARTIAL_USES_VARIADIC_PLACEHOLDER;
|
||||
|
||||
if (UNEXPECTED(zp_args_check(function, argc, argv, extra_named_params, uses_variadic_placeholder) != SUCCESS)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
return NULL;
|
||||
@@ -1012,10 +972,8 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function,
|
||||
}
|
||||
#endif
|
||||
|
||||
zend_string *pfa_name = zp_pfa_name(declaring_op_array, declaring_opline);
|
||||
|
||||
op_array = zend_accel_compile_pfa(closure_ast, declaring_op_array,
|
||||
declaring_opline, function, pfa_name);
|
||||
op_array = zend_accel_compile_pfa(closure_ast, declaring_filename,
|
||||
declaring_lineno_ptr, function, pfa_name, flags & ZEND_PARTIAL_CACHEABLE_IN_SHM);
|
||||
|
||||
zend_ast_destroy(closure_ast);
|
||||
|
||||
@@ -1040,9 +998,9 @@ error:
|
||||
static const zend_op_array *zp_get_op_array(zval *this_ptr, zend_function *function,
|
||||
uint32_t argc, zval *argv, zend_array *extra_named_params,
|
||||
const zend_array *named_positions,
|
||||
const zend_op_array *declaring_op_array,
|
||||
const zend_op *declaring_opline, void **cache_slot,
|
||||
bool uses_variadic_placeholder) {
|
||||
zend_string *declaring_filename,
|
||||
const uint32_t *declaring_lineno_ptr, void **cache_slot,
|
||||
zend_string *pfa_name, uint32_t flags) {
|
||||
|
||||
if (EXPECTED(function->type == ZEND_INTERNAL_FUNCTION
|
||||
? cache_slot[0] == function
|
||||
@@ -1051,13 +1009,13 @@ static const zend_op_array *zp_get_op_array(zval *this_ptr, zend_function *funct
|
||||
return cache_slot[1];
|
||||
}
|
||||
|
||||
const zend_op_array *op_array = zend_accel_pfa_cache_get(declaring_op_array,
|
||||
declaring_opline, function);
|
||||
const zend_op_array *op_array = zend_accel_pfa_cache_get(declaring_lineno_ptr, function,
|
||||
flags & ZEND_PARTIAL_CACHEABLE_IN_SHM);
|
||||
|
||||
if (UNEXPECTED(!op_array)) {
|
||||
op_array = zp_compile(this_ptr, function, argc, argv,
|
||||
extra_named_params, named_positions, declaring_op_array, declaring_opline,
|
||||
cache_slot, uses_variadic_placeholder);
|
||||
extra_named_params, named_positions, declaring_filename, declaring_lineno_ptr,
|
||||
cache_slot, pfa_name, flags);
|
||||
}
|
||||
|
||||
if (EXPECTED(op_array) && !(function->common.fn_flags & ZEND_ACC_NEVER_CACHE)) {
|
||||
@@ -1135,14 +1093,16 @@ static void zp_bind(zval *result, zend_function *function, uint32_t argc, zval *
|
||||
void zend_partial_create(zval *result, zval *this_ptr, zend_function *function,
|
||||
uint32_t argc, zval *argv, zend_array *extra_named_params,
|
||||
const zend_array *named_positions,
|
||||
const zend_op_array *declaring_op_array,
|
||||
const zend_op *declaring_opline, void **cache_slot,
|
||||
bool uses_variadic_placeholder) {
|
||||
zend_string *declaring_filename,
|
||||
const uint32_t *declaring_lineno_ptr, void **cache_slot,
|
||||
zend_string *pfa_name, uint32_t flags) {
|
||||
|
||||
ZEND_ASSERT(pfa_name);
|
||||
|
||||
const zend_op_array *op_array = zp_get_op_array(this_ptr, function, argc, argv,
|
||||
extra_named_params, named_positions,
|
||||
declaring_op_array, declaring_opline,
|
||||
cache_slot, uses_variadic_placeholder);
|
||||
declaring_filename, declaring_lineno_ptr,
|
||||
cache_slot, pfa_name, flags);
|
||||
|
||||
if (UNEXPECTED(!op_array)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
|
||||
+13
-3
@@ -21,12 +21,22 @@
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
#define ZEND_PARTIAL_USES_VARIADIC_PLACEHOLDER (1<<0)
|
||||
/* Whether the PFA is cacheable in SHM. This flag is set only when the op_array that declares the PFA is itself in SHM,
|
||||
* for two reasons: Avoids SHM churn, and ensures that the PFA cache key is unique. */
|
||||
#define ZEND_PARTIAL_CACHEABLE_IN_SHM (1<<1)
|
||||
#define ZEND_PARTIAL_FLAGS (ZEND_PARTIAL_USES_VARIADIC_PLACEHOLDER|ZEND_PARTIAL_CACHEABLE_IN_SHM)
|
||||
|
||||
/* Create a partial application of 'function'
|
||||
* 'declaring_lineno_ptr' should be a pointer the zend_op.lineno or
|
||||
* zend_ast.lineno that declares the PFA. The address is used to build a cache
|
||||
* key. */
|
||||
void zend_partial_create(zval *result, zval *this_ptr, zend_function *function,
|
||||
uint32_t argc, zval *argv, zend_array *extra_named_params,
|
||||
const zend_array *named_positions,
|
||||
const zend_op_array *declaring_op_array,
|
||||
const zend_op *declaring_opline, void **cache_slot,
|
||||
bool uses_variadic_placeholder);
|
||||
zend_string *declaring_filename,
|
||||
const uint32_t *declaring_lineno_ptr, void **cache_slot,
|
||||
zend_string *pfa_name, uint32_t flags);
|
||||
|
||||
void zend_partial_op_array_dtor(zval *pDest);
|
||||
|
||||
|
||||
+5
-4
@@ -9866,14 +9866,15 @@ ZEND_VM_HANDLER(202, ZEND_CALLABLE_CONVERT, UNUSED, UNUSED, NUM|CACHE_SLOT)
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(212, ZEND_CALLABLE_CONVERT_PARTIAL, CACHE_SLOT, CONST|UNUSED, NUM)
|
||||
ZEND_VM_HANDLER(212, ZEND_CALLABLE_CONVERT_PARTIAL, CONST, CONST|UNUSED, NUM)
|
||||
{
|
||||
USE_OPLINE
|
||||
SAVE_OPLINE();
|
||||
|
||||
zend_execute_data *call = EX(call);
|
||||
void **cache_slot = CACHE_ADDR(opline->op1.num);
|
||||
void **cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_PARTIAL_FLAGS);
|
||||
zval *named_positions = GET_OP2_ZVAL_PTR();
|
||||
zend_string *pfa_name = Z_STR_P(GET_OP1_ZVAL_PTR());
|
||||
|
||||
zend_partial_create(EX_VAR(opline->result.var),
|
||||
&call->This, call->func,
|
||||
@@ -9881,8 +9882,8 @@ ZEND_VM_HANDLER(212, ZEND_CALLABLE_CONVERT_PARTIAL, CACHE_SLOT, CONST|UNUSED, NU
|
||||
(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) ?
|
||||
call->extra_named_params : NULL,
|
||||
OP2_TYPE == IS_CONST ? Z_ARRVAL_P(named_positions) : NULL,
|
||||
&EX(func)->op_array, opline, cache_slot,
|
||||
opline->extended_value & ZEND_FCALL_USES_VARIADIC_PLACEHOLDER);
|
||||
EX(func)->op_array.filename, &opline->lineno, cache_slot,
|
||||
pfa_name, opline->extended_value & ZEND_PARTIAL_FLAGS);
|
||||
|
||||
if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
|
||||
zend_array_release(call->extra_named_params);
|
||||
|
||||
Generated
+176
-172
@@ -4273,45 +4273,6 @@ recv_init_check_type:
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
SAVE_OPLINE();
|
||||
|
||||
zend_execute_data *call = EX(call);
|
||||
void **cache_slot = CACHE_ADDR(opline->op1.num);
|
||||
zval *named_positions = RT_CONSTANT(opline, opline->op2);
|
||||
|
||||
zend_partial_create(EX_VAR(opline->result.var),
|
||||
&call->This, call->func,
|
||||
ZEND_CALL_NUM_ARGS(call), ZEND_CALL_ARG(call, 1),
|
||||
(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) ?
|
||||
call->extra_named_params : NULL,
|
||||
IS_CONST == IS_CONST ? Z_ARRVAL_P(named_positions) : NULL,
|
||||
&EX(func)->op_array, opline, cache_slot,
|
||||
opline->extended_value & ZEND_FCALL_USES_VARIADIC_PLACEHOLDER);
|
||||
|
||||
if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
|
||||
zend_array_release(call->extra_named_params);
|
||||
}
|
||||
|
||||
if ((call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
|
||||
zend_free_trampoline(call->func);
|
||||
}
|
||||
|
||||
if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
|
||||
OBJ_RELEASE(Z_OBJ(call->This));
|
||||
} else if (ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE) {
|
||||
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(call->func));
|
||||
}
|
||||
|
||||
EX(call) = call->prev_execute_data;
|
||||
|
||||
zend_vm_stack_free_call_frame(call);
|
||||
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_DYNAMIC_CALL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@@ -4456,45 +4417,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_RECV_VARIADIC
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
SAVE_OPLINE();
|
||||
|
||||
zend_execute_data *call = EX(call);
|
||||
void **cache_slot = CACHE_ADDR(opline->op1.num);
|
||||
zval *named_positions = NULL;
|
||||
|
||||
zend_partial_create(EX_VAR(opline->result.var),
|
||||
&call->This, call->func,
|
||||
ZEND_CALL_NUM_ARGS(call), ZEND_CALL_ARG(call, 1),
|
||||
(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) ?
|
||||
call->extra_named_params : NULL,
|
||||
IS_UNUSED == IS_CONST ? Z_ARRVAL_P(named_positions) : NULL,
|
||||
&EX(func)->op_array, opline, cache_slot,
|
||||
opline->extended_value & ZEND_FCALL_USES_VARIADIC_PLACEHOLDER);
|
||||
|
||||
if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
|
||||
zend_array_release(call->extra_named_params);
|
||||
}
|
||||
|
||||
if ((call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
|
||||
zend_free_trampoline(call->func);
|
||||
}
|
||||
|
||||
if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
|
||||
OBJ_RELEASE(Z_OBJ(call->This));
|
||||
} else if (ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE) {
|
||||
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(call->func));
|
||||
}
|
||||
|
||||
EX(call) = call->prev_execute_data;
|
||||
|
||||
zend_vm_stack_free_call_frame(call);
|
||||
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FRAMELESS_ICALL_1_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@@ -8741,6 +8663,46 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_
|
||||
ZEND_VM_SMART_BRANCH(0, 1);
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
SAVE_OPLINE();
|
||||
|
||||
zend_execute_data *call = EX(call);
|
||||
void **cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_PARTIAL_FLAGS);
|
||||
zval *named_positions = RT_CONSTANT(opline, opline->op2);
|
||||
zend_string *pfa_name = Z_STR_P(RT_CONSTANT(opline, opline->op1));
|
||||
|
||||
zend_partial_create(EX_VAR(opline->result.var),
|
||||
&call->This, call->func,
|
||||
ZEND_CALL_NUM_ARGS(call), ZEND_CALL_ARG(call, 1),
|
||||
(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) ?
|
||||
call->extra_named_params : NULL,
|
||||
IS_CONST == IS_CONST ? Z_ARRVAL_P(named_positions) : NULL,
|
||||
EX(func)->op_array.filename, &opline->lineno, cache_slot,
|
||||
pfa_name, opline->extended_value & ZEND_PARTIAL_FLAGS);
|
||||
|
||||
if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
|
||||
zend_array_release(call->extra_named_params);
|
||||
}
|
||||
|
||||
if ((call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
|
||||
zend_free_trampoline(call->func);
|
||||
}
|
||||
|
||||
if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
|
||||
OBJ_RELEASE(Z_OBJ(call->This));
|
||||
} else if (ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE) {
|
||||
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(call->func));
|
||||
}
|
||||
|
||||
EX(call) = call->prev_execute_data;
|
||||
|
||||
zend_vm_stack_free_call_frame(call);
|
||||
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@@ -12067,6 +12029,46 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FUNC_GET_ARGS
|
||||
}
|
||||
|
||||
/* Contrary to what its name indicates, ZEND_COPY_TMP may receive and define references. */
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
SAVE_OPLINE();
|
||||
|
||||
zend_execute_data *call = EX(call);
|
||||
void **cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_PARTIAL_FLAGS);
|
||||
zval *named_positions = NULL;
|
||||
zend_string *pfa_name = Z_STR_P(RT_CONSTANT(opline, opline->op1));
|
||||
|
||||
zend_partial_create(EX_VAR(opline->result.var),
|
||||
&call->This, call->func,
|
||||
ZEND_CALL_NUM_ARGS(call), ZEND_CALL_ARG(call, 1),
|
||||
(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) ?
|
||||
call->extra_named_params : NULL,
|
||||
IS_UNUSED == IS_CONST ? Z_ARRVAL_P(named_positions) : NULL,
|
||||
EX(func)->op_array.filename, &opline->lineno, cache_slot,
|
||||
pfa_name, opline->extended_value & ZEND_PARTIAL_FLAGS);
|
||||
|
||||
if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
|
||||
zend_array_release(call->extra_named_params);
|
||||
}
|
||||
|
||||
if ((call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
|
||||
zend_free_trampoline(call->func);
|
||||
}
|
||||
|
||||
if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
|
||||
OBJ_RELEASE(Z_OBJ(call->This));
|
||||
} else if (ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE) {
|
||||
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(call->func));
|
||||
}
|
||||
|
||||
EX(call) = call->prev_execute_data;
|
||||
|
||||
zend_vm_stack_free_call_frame(call);
|
||||
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@@ -57089,45 +57091,6 @@ recv_init_check_type:
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
SAVE_OPLINE();
|
||||
|
||||
zend_execute_data *call = EX(call);
|
||||
void **cache_slot = CACHE_ADDR(opline->op1.num);
|
||||
zval *named_positions = RT_CONSTANT(opline, opline->op2);
|
||||
|
||||
zend_partial_create(EX_VAR(opline->result.var),
|
||||
&call->This, call->func,
|
||||
ZEND_CALL_NUM_ARGS(call), ZEND_CALL_ARG(call, 1),
|
||||
(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) ?
|
||||
call->extra_named_params : NULL,
|
||||
IS_CONST == IS_CONST ? Z_ARRVAL_P(named_positions) : NULL,
|
||||
&EX(func)->op_array, opline, cache_slot,
|
||||
opline->extended_value & ZEND_FCALL_USES_VARIADIC_PLACEHOLDER);
|
||||
|
||||
if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
|
||||
zend_array_release(call->extra_named_params);
|
||||
}
|
||||
|
||||
if ((call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
|
||||
zend_free_trampoline(call->func);
|
||||
}
|
||||
|
||||
if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
|
||||
OBJ_RELEASE(Z_OBJ(call->This));
|
||||
} else if (ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE) {
|
||||
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(call->func));
|
||||
}
|
||||
|
||||
EX(call) = call->prev_execute_data;
|
||||
|
||||
zend_vm_stack_free_call_frame(call);
|
||||
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_DYNAMIC_CALL_SPEC_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@@ -57272,45 +57235,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_RECV_VARIADIC_SPEC
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
SAVE_OPLINE();
|
||||
|
||||
zend_execute_data *call = EX(call);
|
||||
void **cache_slot = CACHE_ADDR(opline->op1.num);
|
||||
zval *named_positions = NULL;
|
||||
|
||||
zend_partial_create(EX_VAR(opline->result.var),
|
||||
&call->This, call->func,
|
||||
ZEND_CALL_NUM_ARGS(call), ZEND_CALL_ARG(call, 1),
|
||||
(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) ?
|
||||
call->extra_named_params : NULL,
|
||||
IS_UNUSED == IS_CONST ? Z_ARRVAL_P(named_positions) : NULL,
|
||||
&EX(func)->op_array, opline, cache_slot,
|
||||
opline->extended_value & ZEND_FCALL_USES_VARIADIC_PLACEHOLDER);
|
||||
|
||||
if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
|
||||
zend_array_release(call->extra_named_params);
|
||||
}
|
||||
|
||||
if ((call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
|
||||
zend_free_trampoline(call->func);
|
||||
}
|
||||
|
||||
if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
|
||||
OBJ_RELEASE(Z_OBJ(call->This));
|
||||
} else if (ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE) {
|
||||
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(call->func));
|
||||
}
|
||||
|
||||
EX(call) = call->prev_execute_data;
|
||||
|
||||
zend_vm_stack_free_call_frame(call);
|
||||
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FRAMELESS_ICALL_1_SPEC_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@@ -61557,6 +61481,46 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IN_AR
|
||||
ZEND_VM_SMART_BRANCH(0, 1);
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
SAVE_OPLINE();
|
||||
|
||||
zend_execute_data *call = EX(call);
|
||||
void **cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_PARTIAL_FLAGS);
|
||||
zval *named_positions = RT_CONSTANT(opline, opline->op2);
|
||||
zend_string *pfa_name = Z_STR_P(RT_CONSTANT(opline, opline->op1));
|
||||
|
||||
zend_partial_create(EX_VAR(opline->result.var),
|
||||
&call->This, call->func,
|
||||
ZEND_CALL_NUM_ARGS(call), ZEND_CALL_ARG(call, 1),
|
||||
(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) ?
|
||||
call->extra_named_params : NULL,
|
||||
IS_CONST == IS_CONST ? Z_ARRVAL_P(named_positions) : NULL,
|
||||
EX(func)->op_array.filename, &opline->lineno, cache_slot,
|
||||
pfa_name, opline->extended_value & ZEND_PARTIAL_FLAGS);
|
||||
|
||||
if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
|
||||
zend_array_release(call->extra_named_params);
|
||||
}
|
||||
|
||||
if ((call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
|
||||
zend_free_trampoline(call->func);
|
||||
}
|
||||
|
||||
if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
|
||||
OBJ_RELEASE(Z_OBJ(call->This));
|
||||
} else if (ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE) {
|
||||
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(call->func));
|
||||
}
|
||||
|
||||
EX(call) = call->prev_execute_data;
|
||||
|
||||
zend_vm_stack_free_call_frame(call);
|
||||
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@@ -64781,6 +64745,46 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FUNC_GET_ARGS_SPEC
|
||||
}
|
||||
|
||||
/* Contrary to what its name indicates, ZEND_COPY_TMP may receive and define references. */
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
SAVE_OPLINE();
|
||||
|
||||
zend_execute_data *call = EX(call);
|
||||
void **cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_PARTIAL_FLAGS);
|
||||
zval *named_positions = NULL;
|
||||
zend_string *pfa_name = Z_STR_P(RT_CONSTANT(opline, opline->op1));
|
||||
|
||||
zend_partial_create(EX_VAR(opline->result.var),
|
||||
&call->This, call->func,
|
||||
ZEND_CALL_NUM_ARGS(call), ZEND_CALL_ARG(call, 1),
|
||||
(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) ?
|
||||
call->extra_named_params : NULL,
|
||||
IS_UNUSED == IS_CONST ? Z_ARRVAL_P(named_positions) : NULL,
|
||||
EX(func)->op_array.filename, &opline->lineno, cache_slot,
|
||||
pfa_name, opline->extended_value & ZEND_PARTIAL_FLAGS);
|
||||
|
||||
if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
|
||||
zend_array_release(call->extra_named_params);
|
||||
}
|
||||
|
||||
if ((call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
|
||||
zend_free_trampoline(call->func);
|
||||
}
|
||||
|
||||
if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
|
||||
OBJ_RELEASE(Z_OBJ(call->This));
|
||||
} else if (ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE) {
|
||||
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(call->func));
|
||||
}
|
||||
|
||||
EX(call) = call->prev_execute_data;
|
||||
|
||||
zend_vm_stack_free_call_frame(call);
|
||||
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@@ -109528,10 +109532,10 @@ ZEND_API void execute_ex(zend_execute_data *ex)
|
||||
(void*)&&ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED_LABEL,
|
||||
(void*)&&ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST_LABEL,
|
||||
(void*)&&ZEND_TYPE_ASSERT_SPEC_CONST_LABEL,
|
||||
(void*)&&ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_LABEL,
|
||||
(void*)&&ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_CONST_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_UNUSED_LABEL,
|
||||
(void*)&&ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_UNUSED_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
(void*)&&ZEND_SEND_PLACEHOLDER_SPEC_UNUSED_CONST_LABEL,
|
||||
(void*)&&ZEND_NULL_LABEL,
|
||||
@@ -110942,11 +110946,6 @@ zend_leave_helper_SPEC_LABEL:
|
||||
ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
VM_TRACE_OP_END(ZEND_RECV_INIT_SPEC_CONST)
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST):
|
||||
VM_TRACE(ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST)
|
||||
ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
VM_TRACE_OP_END(ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST)
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_INIT_DYNAMIC_CALL_SPEC_TMP):
|
||||
VM_TRACE(ZEND_INIT_DYNAMIC_CALL_SPEC_TMP)
|
||||
ZEND_INIT_DYNAMIC_CALL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
@@ -110962,11 +110961,6 @@ zend_leave_helper_SPEC_LABEL:
|
||||
ZEND_RECV_VARIADIC_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
VM_TRACE_OP_END(ZEND_RECV_VARIADIC_SPEC_UNUSED)
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_UNUSED):
|
||||
VM_TRACE(ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_UNUSED)
|
||||
ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
VM_TRACE_OP_END(ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_UNUSED)
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_FRAMELESS_ICALL_1_SPEC_UNUSED):
|
||||
VM_TRACE(ZEND_FRAMELESS_ICALL_1_SPEC_UNUSED)
|
||||
ZEND_FRAMELESS_ICALL_1_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
@@ -111566,6 +111560,11 @@ zend_leave_helper_SPEC_LABEL:
|
||||
ZEND_IN_ARRAY_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
VM_TRACE_OP_END(ZEND_IN_ARRAY_SPEC_CONST_CONST)
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_CONST):
|
||||
VM_TRACE(ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_CONST)
|
||||
ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
VM_TRACE_OP_END(ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_CONST)
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_ADD_SPEC_CONST_TMPVARCV):
|
||||
VM_TRACE(ZEND_ADD_SPEC_CONST_TMPVARCV)
|
||||
ZEND_ADD_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
@@ -111926,6 +111925,11 @@ zend_leave_helper_SPEC_LABEL:
|
||||
ZEND_FUNC_GET_ARGS_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
VM_TRACE_OP_END(ZEND_FUNC_GET_ARGS_SPEC_CONST_UNUSED)
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_UNUSED):
|
||||
VM_TRACE(ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_UNUSED)
|
||||
ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
VM_TRACE_OP_END(ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_UNUSED)
|
||||
HYBRID_BREAK();
|
||||
HYBRID_CASE(ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED):
|
||||
VM_TRACE(ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED)
|
||||
ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
@@ -118496,10 +118500,10 @@ void zend_vm_init(void)
|
||||
ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED_HANDLER,
|
||||
ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST_HANDLER,
|
||||
ZEND_TYPE_ASSERT_SPEC_CONST_HANDLER,
|
||||
ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_HANDLER,
|
||||
ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_CONST_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_UNUSED_HANDLER,
|
||||
ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_UNUSED_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_SEND_PLACEHOLDER_SPEC_UNUSED_CONST_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
@@ -121984,10 +121988,10 @@ void zend_vm_init(void)
|
||||
ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED_TAILCALL_HANDLER,
|
||||
ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST_TAILCALL_HANDLER,
|
||||
ZEND_TYPE_ASSERT_SPEC_CONST_TAILCALL_HANDLER,
|
||||
ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_TAILCALL_HANDLER,
|
||||
ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_CONST_TAILCALL_HANDLER,
|
||||
ZEND_NULL_TAILCALL_HANDLER,
|
||||
ZEND_NULL_TAILCALL_HANDLER,
|
||||
ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_UNUSED_TAILCALL_HANDLER,
|
||||
ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_UNUSED_TAILCALL_HANDLER,
|
||||
ZEND_NULL_TAILCALL_HANDLER,
|
||||
ZEND_SEND_PLACEHOLDER_SPEC_UNUSED_CONST_TAILCALL_HANDLER,
|
||||
ZEND_NULL_TAILCALL_HANDLER,
|
||||
|
||||
Generated
+2
-2
@@ -1087,8 +1087,8 @@
|
||||
_(2556, ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED) \
|
||||
_(2557, ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST) \
|
||||
_(2558, ZEND_TYPE_ASSERT_SPEC_CONST) \
|
||||
_(2559, ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST) \
|
||||
_(2562, ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_UNUSED) \
|
||||
_(2559, ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_CONST) \
|
||||
_(2562, ZEND_CALLABLE_CONVERT_PARTIAL_SPEC_CONST_UNUSED) \
|
||||
_(2564, ZEND_SEND_PLACEHOLDER_SPEC_UNUSED_CONST) \
|
||||
_(2567, ZEND_SEND_PLACEHOLDER_SPEC_UNUSED_UNUSED) \
|
||||
_(2569, ZEND_INIT_FCALL_OFFSET_SPEC_CONST) \
|
||||
|
||||
Generated
+1
-1
@@ -451,7 +451,7 @@ static uint32_t zend_vm_opcodes_flags[214] = {
|
||||
0x01001103,
|
||||
0x00000303,
|
||||
0x01000003,
|
||||
0x010003a0,
|
||||
0x01000303,
|
||||
0x00001301,
|
||||
};
|
||||
|
||||
|
||||
@@ -2024,7 +2024,7 @@ static char *zend_accel_uintptr_hex(char *dest, uintptr_t n)
|
||||
* a scheme, except file:// and phar://. */
|
||||
#define PFA_KEY_PREFIX "pfa://"
|
||||
|
||||
static zend_string *zend_accel_pfa_key(const zend_op *declaring_opline,
|
||||
static zend_string *zend_accel_pfa_key(const uint32_t *declaring_lineno_ptr,
|
||||
const zend_function *called_function)
|
||||
{
|
||||
const size_t max_key_len = strlen(PFA_KEY_PREFIX) + (sizeof(uintptr_t)*2) + strlen(":") + (sizeof(uintptr_t)*2);
|
||||
@@ -2032,7 +2032,7 @@ static zend_string *zend_accel_pfa_key(const zend_op *declaring_opline,
|
||||
|
||||
char *dest = ZSTR_VAL(key);
|
||||
dest = zend_mempcpy(dest, PFA_KEY_PREFIX, strlen(PFA_KEY_PREFIX));
|
||||
dest = zend_accel_uintptr_hex(dest, (uintptr_t)declaring_opline);
|
||||
dest = zend_accel_uintptr_hex(dest, (uintptr_t)declaring_lineno_ptr);
|
||||
*dest++ = ':';
|
||||
|
||||
const void *ptr;
|
||||
@@ -2054,17 +2054,17 @@ static zend_string *zend_accel_pfa_key(const zend_op *declaring_opline,
|
||||
return key;
|
||||
}
|
||||
|
||||
const zend_op_array *zend_accel_pfa_cache_get(const zend_op_array *declaring_op_array,
|
||||
const zend_op *declaring_opline, const zend_function *called_function)
|
||||
const zend_op_array *zend_accel_pfa_cache_get(
|
||||
const uint32_t *declaring_lineno_ptr, const zend_function *called_function, bool cacheable_in_shm)
|
||||
{
|
||||
zend_string *key = zend_accel_pfa_key(declaring_opline, called_function);
|
||||
zend_string *key = zend_accel_pfa_key(declaring_lineno_ptr, called_function);
|
||||
zend_op_array *op_array = NULL;
|
||||
|
||||
/* A PFA is SHM-cacheable if the declaring_op_array and called_function are
|
||||
/* A PFA is SHM-cacheable if the declaring op_array and called_function are
|
||||
* cached. */
|
||||
if (ZCG(accelerator_enabled)
|
||||
&& !file_cache_only
|
||||
&& !declaring_op_array->refcount
|
||||
&& cacheable_in_shm /* declaring op_array is cached */
|
||||
&& (called_function->type != ZEND_USER_FUNCTION || !called_function->op_array.refcount)) {
|
||||
zend_persistent_script *persistent_script = zend_accel_hash_find(&ZCSG(hash), key);
|
||||
if (persistent_script) {
|
||||
@@ -2084,11 +2084,13 @@ const zend_op_array *zend_accel_pfa_cache_get(const zend_op_array *declaring_op_
|
||||
}
|
||||
|
||||
zend_op_array *zend_accel_compile_pfa(zend_ast *ast,
|
||||
const zend_op_array *declaring_op_array,
|
||||
const zend_op *declaring_opline,
|
||||
zend_string *declaring_filename,
|
||||
const uint32_t *declaring_lineno_ptr,
|
||||
const zend_function *called_function,
|
||||
zend_string *pfa_func_name)
|
||||
zend_string *pfa_func_name, bool cacheable_in_shm)
|
||||
{
|
||||
ZEND_ASSERT(zend_accel_in_shm((void*)declaring_lineno_ptr) || !cacheable_in_shm);
|
||||
|
||||
zend_begin_record_errors();
|
||||
zend_op_array *op_array;
|
||||
|
||||
@@ -2106,7 +2108,7 @@ zend_op_array *zend_accel_compile_pfa(zend_ast *ast,
|
||||
CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES;
|
||||
#endif
|
||||
|
||||
op_array = zend_compile_ast(ast, ZEND_USER_FUNCTION, declaring_op_array->filename);
|
||||
op_array = zend_compile_ast(ast, ZEND_USER_FUNCTION, declaring_filename);
|
||||
|
||||
CG(compiler_options) = orig_compiler_options;
|
||||
} zend_catch {
|
||||
@@ -2119,21 +2121,21 @@ zend_op_array *zend_accel_compile_pfa(zend_ast *ast,
|
||||
ZEND_ASSERT(op_array->num_dynamic_func_defs == 1);
|
||||
|
||||
zend_string_release(op_array->dynamic_func_defs[0]->function_name);
|
||||
op_array->dynamic_func_defs[0]->function_name = pfa_func_name;
|
||||
op_array->dynamic_func_defs[0]->function_name = zend_string_copy(pfa_func_name);
|
||||
|
||||
zend_string *key = zend_accel_pfa_key(declaring_opline, called_function);
|
||||
zend_string *key = zend_accel_pfa_key(declaring_lineno_ptr, called_function);
|
||||
|
||||
/* Cache op_array only if the declaring op_array and the called function
|
||||
* are cached */
|
||||
if (!ZCG(accelerator_enabled)
|
||||
|| file_cache_only
|
||||
|| declaring_op_array->refcount
|
||||
|| !cacheable_in_shm /* declaring op_array is not in SHM */
|
||||
|| (called_function->type == ZEND_USER_FUNCTION && called_function->op_array.refcount)
|
||||
|| (ZCSG(restart_in_progress) && accel_restart_is_active())
|
||||
|| (!ZCG(counted) && accel_activate_add() == FAILURE)) {
|
||||
zend_op_array *script_op_array = op_array;
|
||||
zend_op_array *op_array = script_op_array->dynamic_func_defs[0];
|
||||
GC_ADDREF(op_array->function_name);
|
||||
GC_TRY_ADDREF(op_array->function_name);
|
||||
(*op_array->refcount)++;
|
||||
destroy_op_array(script_op_array);
|
||||
efree(script_op_array);
|
||||
|
||||
@@ -334,15 +334,14 @@ zend_string* ZEND_FASTCALL accel_new_interned_string(zend_string *str);
|
||||
|
||||
uint32_t zend_accel_get_class_name_map_ptr(zend_string *type_name);
|
||||
|
||||
const zend_op_array *zend_accel_pfa_cache_get(const zend_op_array *declaring_op_array,
|
||||
const zend_op *declaring_opline,
|
||||
const zend_function *called_function);
|
||||
const zend_op_array *zend_accel_pfa_cache_get(
|
||||
const uint32_t *declaring_lineno_ptr, const zend_function *called_function, bool cacheable_in_shm);
|
||||
|
||||
zend_op_array *zend_accel_compile_pfa(zend_ast *ast,
|
||||
const zend_op_array *declaring_op_array,
|
||||
const zend_op *declaring_opline,
|
||||
zend_string *declaring_filename,
|
||||
const uint32_t *declaring_lineno_ptr,
|
||||
const zend_function *called_function,
|
||||
zend_string *pfa_func_name);
|
||||
zend_string *pfa_func_name, bool cacheable_in_shm);
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ $_main:
|
||||
0005 INIT_FCALL 2 %d string("array_map")
|
||||
0006 INIT_FCALL 0 %d string("plusn")
|
||||
0007 SEND_VAL int(2) string("n")
|
||||
0008 T2 = CALLABLE_CONVERT_PARTIAL 2
|
||||
0008 T2 = CALLABLE_CONVERT_PARTIAL %d string("{closure:%s}")
|
||||
0009 SEND_VAL T2 1
|
||||
0010 SEND_VAR CV0($array) 2
|
||||
0011 T2 = DO_ICALL
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "zend_attributes.h"
|
||||
#include "zend_system_id.h"
|
||||
#include "zend_enum.h"
|
||||
#include "zend_partial.h"
|
||||
|
||||
#include "php.h"
|
||||
#ifdef ZEND_WIN32
|
||||
@@ -382,6 +383,10 @@ static void zend_file_cache_serialize_ast(zend_ast *ast,
|
||||
} else if (ast->kind == ZEND_AST_CALLABLE_CONVERT) {
|
||||
zend_ast_fcc *fcc = (zend_ast_fcc*)ast;
|
||||
ZEND_MAP_PTR_INIT(fcc->fptr, NULL);
|
||||
/* Will be reset if needed during unserialize */
|
||||
fcc->attr |= ZEND_PARTIAL_CACHEABLE_IN_SHM;
|
||||
SERIALIZE_STR(fcc->filename);
|
||||
SERIALIZE_STR(fcc->name);
|
||||
if (!IS_SERIALIZED(fcc->args)) {
|
||||
SERIALIZE_PTR(fcc->args);
|
||||
tmp = fcc->args;
|
||||
@@ -636,6 +641,12 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (opline->opcode == ZEND_CALLABLE_CONVERT_PARTIAL) {
|
||||
/* Will be reset if needed during unserialize */
|
||||
opline->extended_value |= ZEND_PARTIAL_CACHEABLE_IN_SHM;
|
||||
}
|
||||
|
||||
zend_serialize_opcode_handler(opline);
|
||||
opline++;
|
||||
}
|
||||
@@ -1308,9 +1319,13 @@ static void zend_file_cache_unserialize_ast(zend_ast *ast,
|
||||
zend_ast_get_op_array(ast)->op_array = Z_PTR(z);
|
||||
} else if (ast->kind == ZEND_AST_CALLABLE_CONVERT) {
|
||||
zend_ast_fcc *fcc = (zend_ast_fcc*)ast;
|
||||
if (!script->corrupted) {
|
||||
if (script->corrupted) {
|
||||
fcc->attr &= ~ZEND_PARTIAL_CACHEABLE_IN_SHM;
|
||||
} else {
|
||||
ZEND_MAP_PTR_NEW(fcc->fptr);
|
||||
}
|
||||
UNSERIALIZE_STR(fcc->filename);
|
||||
UNSERIALIZE_STR(fcc->name);
|
||||
if (!IS_UNSERIALIZED(fcc->args)) {
|
||||
UNSERIALIZE_PTR(fcc->args);
|
||||
zend_file_cache_unserialize_ast(fcc->args, script, buf);
|
||||
@@ -1541,6 +1556,13 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr
|
||||
zval *literal = RT_CONSTANT(opline, opline->op1);
|
||||
UNSERIALIZE_ATTRIBUTES(Z_PTR_P(literal));
|
||||
}
|
||||
|
||||
if (opline->opcode == ZEND_CALLABLE_CONVERT_PARTIAL) {
|
||||
if (script->corrupted) {
|
||||
opline->extended_value &= ~ZEND_PARTIAL_CACHEABLE_IN_SHM;
|
||||
}
|
||||
}
|
||||
|
||||
zend_deserialize_opcode_handler(opline);
|
||||
opline++;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "zend_operators.h"
|
||||
#include "zend_interfaces.h"
|
||||
#include "zend_attributes.h"
|
||||
#include "zend_partial.h"
|
||||
|
||||
#ifdef HAVE_JIT
|
||||
# include "Optimizer/zend_func_info.h"
|
||||
@@ -197,6 +198,13 @@ static zend_ast *zend_persist_ast(zend_ast *ast)
|
||||
zend_ast_fcc *copy = zend_shared_memdup(ast, sizeof(zend_ast_fcc));
|
||||
if (!ZCG(current_persistent_script)->corrupted) {
|
||||
ZEND_MAP_PTR_NEW(copy->fptr);
|
||||
copy->attr |= ZEND_PARTIAL_CACHEABLE_IN_SHM;
|
||||
}
|
||||
if (copy->filename) {
|
||||
zend_accel_store_interned_string(copy->filename);
|
||||
}
|
||||
if (copy->name) {
|
||||
zend_accel_store_interned_string(copy->name);
|
||||
}
|
||||
copy->args = zend_persist_ast(copy->args);
|
||||
node = (zend_ast *) copy;
|
||||
@@ -624,6 +632,12 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
|
||||
attributes = zend_persist_attributes(attributes);
|
||||
ZVAL_PTR(literal, attributes);
|
||||
}
|
||||
|
||||
if (opline->opcode == ZEND_CALLABLE_CONVERT_PARTIAL) {
|
||||
if (!ZCG(current_persistent_script)->corrupted) {
|
||||
opline->extended_value |= ZEND_PARTIAL_CACHEABLE_IN_SHM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
efree(op_array->opcodes);
|
||||
|
||||
@@ -92,6 +92,12 @@ static void zend_persist_ast_calc(zend_ast *ast)
|
||||
} else if (ast->kind == ZEND_AST_CALLABLE_CONVERT) {
|
||||
zend_ast_fcc *fcc_ast = (zend_ast_fcc*)ast;
|
||||
ADD_SIZE(sizeof(zend_ast_fcc));
|
||||
if (fcc_ast->filename) {
|
||||
ADD_INTERNED_STRING(fcc_ast->filename);
|
||||
}
|
||||
if (fcc_ast->name) {
|
||||
ADD_INTERNED_STRING(fcc_ast->name);
|
||||
}
|
||||
zend_persist_ast_calc(fcc_ast->args);
|
||||
} else if (zend_ast_is_decl(ast)) {
|
||||
/* Not implemented. */
|
||||
|
||||
Reference in new issue
Block a user