mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Merge branch 'PHP-8.2'
* PHP-8.2: Fix a memory leak in tracig JIT when the same closure is called through Closure::call() and natively.
This commit is contained in:
commit
ff85649431
2 changed files with 56 additions and 6 deletions
|
@ -160,15 +160,21 @@ ZEND_METHOD(Closure, call)
|
||||||
/* copied upon generator creation */
|
/* copied upon generator creation */
|
||||||
GC_DELREF(&closure->std);
|
GC_DELREF(&closure->std);
|
||||||
} else {
|
} else {
|
||||||
|
zend_closure *fake_closure;
|
||||||
zend_function *my_function;
|
zend_function *my_function;
|
||||||
|
|
||||||
|
fake_closure = emalloc(sizeof(zend_closure));
|
||||||
|
memset(&fake_closure->std, 0, sizeof(fake_closure->std));
|
||||||
|
fake_closure->std.gc.refcount = 1;
|
||||||
|
fake_closure->std.gc.u.type_info = GC_NULL;
|
||||||
|
ZVAL_UNDEF(&fake_closure->this_ptr);
|
||||||
|
fake_closure->called_scope = NULL;
|
||||||
|
my_function = &fake_closure->func;
|
||||||
if (ZEND_USER_CODE(closure->func.type)) {
|
if (ZEND_USER_CODE(closure->func.type)) {
|
||||||
my_function = emalloc(sizeof(zend_op_array));
|
|
||||||
memcpy(my_function, &closure->func, sizeof(zend_op_array));
|
memcpy(my_function, &closure->func, sizeof(zend_op_array));
|
||||||
} else {
|
} else {
|
||||||
my_function = emalloc(sizeof(zend_internal_function));
|
|
||||||
memcpy(my_function, &closure->func, sizeof(zend_internal_function));
|
memcpy(my_function, &closure->func, sizeof(zend_internal_function));
|
||||||
}
|
}
|
||||||
my_function->common.fn_flags &= ~ZEND_ACC_CLOSURE;
|
|
||||||
/* use scope of passed object */
|
/* use scope of passed object */
|
||||||
my_function->common.scope = newclass;
|
my_function->common.scope = newclass;
|
||||||
if (closure->func.type == ZEND_INTERNAL_FUNCTION) {
|
if (closure->func.type == ZEND_INTERNAL_FUNCTION) {
|
||||||
|
@ -194,10 +200,8 @@ ZEND_METHOD(Closure, call)
|
||||||
if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_HEAP_RT_CACHE) {
|
if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_HEAP_RT_CACHE) {
|
||||||
efree(ZEND_MAP_PTR(my_function->op_array.run_time_cache));
|
efree(ZEND_MAP_PTR(my_function->op_array.run_time_cache));
|
||||||
}
|
}
|
||||||
efree_size(my_function, sizeof(zend_op_array));
|
|
||||||
} else {
|
|
||||||
efree_size(my_function, sizeof(zend_internal_function));
|
|
||||||
}
|
}
|
||||||
|
efree_size(fake_closure, sizeof(zend_closure));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Z_TYPE(closure_result) != IS_UNDEF) {
|
if (Z_TYPE(closure_result) != IS_UNDEF) {
|
||||||
|
|
46
ext/opcache/tests/jit/closure_001.phpt
Normal file
46
ext/opcache/tests/jit/closure_001.phpt
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
--TEST--
|
||||||
|
Closures should be always called with ZEND_ACC_CLOSURE flag set
|
||||||
|
--INI--
|
||||||
|
opcache.enable=1
|
||||||
|
opcache.enable_cli=1
|
||||||
|
opcache.file_update_protection=0
|
||||||
|
opcache.jit_buffer_size=1M
|
||||||
|
opcache.protect_memory=1
|
||||||
|
opcache.jit_hot_func=2
|
||||||
|
--EXTENSIONS--
|
||||||
|
opcache
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
}
|
||||||
|
|
||||||
|
function bar() {
|
||||||
|
return function () {
|
||||||
|
return function () {
|
||||||
|
return function () {
|
||||||
|
return 42;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
$foo = new Foo;
|
||||||
|
$f = bar();
|
||||||
|
|
||||||
|
var_dump($f->call($foo));
|
||||||
|
var_dump($f->call($foo));
|
||||||
|
var_dump($f());
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
object(Closure)#3 (1) {
|
||||||
|
["this"]=>
|
||||||
|
object(Foo)#1 (0) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
object(Closure)#3 (1) {
|
||||||
|
["this"]=>
|
||||||
|
object(Foo)#1 (0) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
object(Closure)#3 (0) {
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue