Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 8.6.0alpha1

- Core:
. Added first-class callable cache to share instances for the duration of the
request. (ilutov)

- Intl:
. Added IntlNumberRangeFormatter class to format an interval of two numbers
with a given skeleton, locale, collapse type and identity fallback.
Expand Down
6 changes: 6 additions & 0 deletions Zend/Optimizer/compact_literals.c
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,12 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
cache_size += 2 * sizeof(void *);
}
break;
case ZEND_CALLABLE_CONVERT:
if (opline->extended_value != (uint32_t)-1) {
opline->extended_value = cache_size;
cache_size += sizeof(void *);
}
break;
}
opline++;
}
Expand Down
8 changes: 8 additions & 0 deletions Zend/tests/closures/fcc-cache.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
--TEST--
FCCs are cached and shared
--FILE--
<?php
var_dump(strlen(...) === strlen(...));
?>
--EXPECT--
bool(true)
6 changes: 3 additions & 3 deletions Zend/tests/exit/exit_as_function.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ foreach ($values as $value) {
}

?>
--EXPECT--
--EXPECTF--
string(4) "exit"
string(3) "die"
object(Closure)#1 (2) {
object(Closure)#%d (2) {
["function"]=>
string(4) "exit"
["parameter"]=>
Expand All @@ -31,7 +31,7 @@ object(Closure)#1 (2) {
string(10) "<optional>"
}
}
object(Closure)#2 (2) {
object(Closure)#%d (2) {
["function"]=>
string(4) "exit"
["parameter"]=>
Expand Down
8 changes: 4 additions & 4 deletions Zend/tests/first_class_callable/constexpr/namespace_004.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ foo();

?>
--EXPECTF--
object(Closure)#1 (2) {
object(Closure)#%d (2) {
["function"]=>
string(6) "strrev"
["parameter"]=>
Expand All @@ -36,7 +36,7 @@ object(Closure)#1 (2) {
}
}
string(3) "cba"
object(Closure)#2 (2) {
object(Closure)#%d (2) {
["function"]=>
string(6) "strrev"
["parameter"]=>
Expand All @@ -46,7 +46,7 @@ object(Closure)#2 (2) {
}
}
string(3) "cba"
object(Closure)#2 (2) {
object(Closure)#%d (2) {
["function"]=>
string(6) "strrev"
["parameter"]=>
Expand All @@ -56,7 +56,7 @@ object(Closure)#2 (2) {
}
}
string(3) "cba"
object(Closure)#1 (2) {
object(Closure)#%d (2) {
["function"]=>
string(6) "strrev"
["parameter"]=>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ var_dump(test1(...));
var_dump(test2(...));

?>
--EXPECT--
object(Closure)#1 (1) {
--EXPECTF--
object(Closure)#%d (1) {
["function"]=>
string(5) "test1"
}
object(Closure)#1 (1) {
object(Closure)#%d (1) {
["function"]=>
string(5) "test2"
}
14 changes: 7 additions & 7 deletions Zend/tests/magic_methods/trampoline_closure_named_arguments.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ var_dump($type);
var_dump($type->getName());

?>
--EXPECT--
--EXPECTF--
-- Non-static cases --
string(4) "test"
array(3) {
Expand All @@ -69,15 +69,15 @@ array(4) {
["a"]=>
int(123)
["b"]=>
object(Test)#1 (0) {
object(Test)#%d (0) {
}
}
string(4) "test"
array(2) {
["a"]=>
int(123)
["b"]=>
object(Test)#1 (0) {
object(Test)#%d (0) {
}
}
string(4) "test"
Expand Down Expand Up @@ -114,15 +114,15 @@ array(4) {
["a"]=>
int(123)
["b"]=>
object(Test)#1 (0) {
object(Test)#%d (0) {
}
}
string(10) "testStatic"
array(2) {
["a"]=>
int(123)
["b"]=>
object(Test)#1 (0) {
object(Test)#%d (0) {
}
}
string(10) "testStatic"
Expand All @@ -136,12 +136,12 @@ array(1) {
-- Reflection tests --
array(1) {
[0]=>
object(ReflectionParameter)#4 (1) {
object(ReflectionParameter)#%d (1) {
["name"]=>
string(9) "arguments"
}
}
bool(true)
object(ReflectionNamedType)#5 (0) {
object(ReflectionNamedType)#%d (0) {
}
string(5) "mixed"
9 changes: 8 additions & 1 deletion Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -3965,7 +3965,14 @@ static bool zend_compile_call_common(znode *result, zend_ast *args_ast, zend_fun
opline->op1.num = zend_vm_calc_used_stack(0, fbc);
}

zend_emit_op_tmp(result, ZEND_CALLABLE_CONVERT, NULL, NULL);
zend_op *callable_convert_op = zend_emit_op_tmp(result, ZEND_CALLABLE_CONVERT, NULL, NULL);
if (opline->opcode == ZEND_INIT_FCALL
|| opline->opcode == ZEND_INIT_FCALL_BY_NAME
|| opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME) {
callable_convert_op->extended_value = zend_alloc_cache_slot();
} else {
callable_convert_op->extended_value = (uint32_t)-1;
}
return true;
}

Expand Down
6 changes: 6 additions & 0 deletions Zend/zend_execute_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ void init_executor(void) /* {{{ */
zend_fiber_init();
zend_weakrefs_init();

zend_hash_init(&EG(callable_convert_cache), 8, NULL, ZVAL_PTR_DTOR, 0);

EG(active) = 1;
}
/* }}} */
Expand Down Expand Up @@ -420,6 +422,8 @@ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown)
zend_stack_clean(&EG(user_error_handlers), (void (*)(void *))ZVAL_PTR_DTOR, 1);
zend_stack_clean(&EG(user_exception_handlers), (void (*)(void *))ZVAL_PTR_DTOR, 1);

zend_hash_clean(&EG(callable_convert_cache));

#if ZEND_DEBUG
if (!CG(unclean_shutdown)) {
gc_collect_cycles();
Expand Down Expand Up @@ -516,6 +520,8 @@ void shutdown_executor(void) /* {{{ */
if (EG(ht_iterators) != EG(ht_iterators_slots)) {
efree(EG(ht_iterators));
}

zend_hash_destroy(&EG(callable_convert_cache));
}

#if ZEND_DEBUG
Expand Down
2 changes: 2 additions & 0 deletions Zend/zend_globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,8 @@ struct _zend_executor_globals {

zend_strtod_state strtod_state;

HashTable callable_convert_cache;

void *reserved[ZEND_MAX_RESERVED_RESOURCES];
};

Expand Down
20 changes: 18 additions & 2 deletions Zend/zend_vm_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -9709,12 +9709,28 @@ ZEND_VM_HANDLER(167, ZEND_COPY_TMP, TMPVAR, UNUSED)
ZEND_VM_NEXT_OPCODE();
}

ZEND_VM_HANDLER(202, ZEND_CALLABLE_CONVERT, UNUSED, UNUSED)
ZEND_VM_HANDLER(202, ZEND_CALLABLE_CONVERT, UNUSED, UNUSED, NUM|CACHE_SLOT)
{
USE_OPLINE
zend_execute_data *call = EX(call);

zend_closure_from_frame(EX_VAR(opline->result.var), call);
if (opline->extended_value != (uint32_t)-1) {
zend_object *closure = CACHED_PTR(opline->extended_value);
if (closure) {
ZVAL_OBJ_COPY(EX_VAR(opline->result.var), closure);
} else {
zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), (zend_ulong)(uintptr_t)call->func);
if (Z_TYPE_P(closure_zv) == IS_NULL) {
zend_closure_from_frame(closure_zv, call);
}
ZEND_ASSERT(Z_TYPE_P(closure_zv) == IS_OBJECT);
closure = Z_OBJ_P(closure_zv);
ZVAL_OBJ_COPY(EX_VAR(opline->result.var), closure);
CACHE_PTR(opline->extended_value, closure);
}
} else {
zend_closure_from_frame(EX_VAR(opline->result.var), call);
}

if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
OBJ_RELEASE(Z_OBJ(call->This));
Expand Down
36 changes: 34 additions & 2 deletions Zend/zend_vm_execute.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Zend/zend_vm_opcodes.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions build/php.m4
Original file line number Diff line number Diff line change
Expand Up @@ -2502,3 +2502,43 @@ AC_DEFUN([PHP_REMOVE_OPTIMIZATION_FLAGS], [
CFLAGS=$(echo "$CFLAGS" | $SED -e "$sed_script")
CXXFLAGS=$(echo "$CXXFLAGS" | $SED -e "$sed_script")
])

dnl
dnl PHP_C_STANDARD_LIBRARY
dnl
dnl Determine the C standard library used for the build. The uclibc is checked
dnl first because it also defines the __GLIBC__ and could otherwise be detected
dnl as glibc. Musl C library is determined heuristically.
dnl
AC_DEFUN([PHP_C_STANDARD_LIBRARY],
[AC_CACHE_CHECK([C standard library implementation],
[php_cv_c_standard_library],
[php_cv_c_standard_library=unknown
dnl Check if C standard library is uclibc.
AS_VAR_IF([php_cv_c_standard_library], [unknown],
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <features.h>],
[#ifndef __UCLIBC__
(void) __UCLIBC__;
#endif])],
[php_cv_c_standard_library=uclibc],
[php_cv_c_standard_library=unknown])])
dnl Check if C standard library is GNU C.
AS_VAR_IF([php_cv_c_standard_library], [unknown],
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <features.h>],
[#ifndef __GLIBC__
(void) __GLIBC__;
#endif])],
[php_cv_c_standard_library=glibc],
[php_cv_c_standard_library=unknown])])
dnl Check if C standard library is musl libc.
AS_VAR_IF([php_cv_c_standard_library], [unknown],
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <stdarg.h>],
[#ifndef __DEFINED_va_list
(void) __DEFINED_va_list;
#endif])],
[php_cv_c_standard_library=musl],
[AS_IF([command -v ldd >/dev/null && ldd --version 2>&1 | grep ^musl >/dev/null 2>&1],
[php_cv_c_standard_library=musl],
[php_cv_c_standard_library=unknown])])])
])
])
13 changes: 4 additions & 9 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -250,15 +250,10 @@ case $host_alias in
;;
esac

dnl Detect musl libc
AC_MSG_CHECKING([whether we are using musl libc])
if command -v ldd >/dev/null && ldd --version 2>&1 | grep ^musl >/dev/null 2>&1
then
AC_MSG_RESULT([yes])
AC_DEFINE([__MUSL__], [1], [Define to 1 when using musl libc.])
else
AC_MSG_RESULT([no])
fi
dnl Detect C library.
PHP_C_STANDARD_LIBRARY
AS_VAR_IF([php_cv_c_standard_library], [musl],
[AC_DEFINE([__MUSL__], [1], [Define to 1 when using musl libc.])])

dnl Add _GNU_SOURCE compile definition because the php_config.h with definitions
dnl by AC_USE_SYSTEM_EXTENSIONS might be included after the system headers which
Expand Down
Loading