Skip to content

Commit 0f6c002

Browse files
committed
Speed up __sleep() and __wakeup() calls
1 parent 7920c9d commit 0f6c002

File tree

3 files changed

+58
-35
lines changed

3 files changed

+58
-35
lines changed

Zend/zend_string.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,8 @@ EMPTY_SWITCH_DEFAULT_CASE()
551551
_(ZEND_STR_FALSE, "false") \
552552
_(ZEND_STR_NULL_LOWERCASE, "null") \
553553
_(ZEND_STR_MIXED, "mixed") \
554+
_(ZEND_STR_SLEEP, "__sleep") \
555+
_(ZEND_STR_WAKEUP, "__wakeup") \
554556

555557

556558
typedef enum _zend_known_string_id {

ext/standard/var.c

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -722,28 +722,36 @@ static inline bool php_var_serialize_class_name(smart_str *buf, zval *struc) /*
722722
}
723723
/* }}} */
724724

725-
static int php_var_serialize_call_sleep(zval *retval, zval *struc) /* {{{ */
725+
static zend_result php_var_serialize_call_sleep(zend_object *obj, zend_function *fn, zval *retval) /* {{{ */
726726
{
727-
zval fname;
728-
int res;
727+
zend_result res;
728+
zend_fcall_info fci;
729+
zend_fcall_info_cache fci_cache;
730+
731+
fci.size = sizeof(fci);
732+
fci.object = obj;
733+
fci.retval = retval;
734+
fci.param_count = 0;
735+
fci.params = NULL;
736+
fci.named_params = NULL;
737+
ZVAL_UNDEF(&fci.function_name);
738+
739+
fci_cache.function_handler = fn;
740+
fci_cache.object = obj;
741+
fci_cache.called_scope = obj->ce;
729742

730-
ZVAL_STRINGL(&fname, "__sleep", sizeof("__sleep") - 1);
731743
BG(serialize_lock)++;
732-
res = call_user_function(NULL, struc, &fname, retval, 0, 0);
744+
res = zend_call_function(&fci, &fci_cache);
733745
BG(serialize_lock)--;
734-
zval_ptr_dtor_str(&fname);
735746

736747
if (res == FAILURE || Z_ISUNDEF_P(retval)) {
737748
zval_ptr_dtor(retval);
738749
return FAILURE;
739750
}
740751

741752
if (!HASH_OF(retval)) {
742-
zend_class_entry *ce;
743-
ZEND_ASSERT(Z_TYPE_P(struc) == IS_OBJECT);
744-
ce = Z_OBJCE_P(struc);
745753
zval_ptr_dtor(retval);
746-
php_error_docref(NULL, E_WARNING, "%s::__sleep() should return an array only containing the names of instance-variables to serialize", ZSTR_VAL(ce->name));
754+
php_error_docref(NULL, E_WARNING, "%s::__sleep() should return an array only containing the names of instance-variables to serialize", ZSTR_VAL(obj->ce->name));
747755
return FAILURE;
748756
}
749757

@@ -1067,25 +1075,28 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
10671075
return;
10681076
}
10691077

1070-
if (ce != PHP_IC_ENTRY && zend_hash_str_exists(&ce->function_table, "__sleep", sizeof("__sleep")-1)) {
1071-
zval retval, tmp;
1072-
1073-
ZVAL_OBJ_COPY(&tmp, Z_OBJ_P(struc));
1074-
1075-
if (php_var_serialize_call_sleep(&retval, &tmp) == FAILURE) {
1076-
if (!EG(exception)) {
1077-
/* we should still add element even if it's not OK,
1078-
* since we already wrote the length of the array before */
1079-
smart_str_appendl(buf, "N;", 2);
1078+
if (ce != PHP_IC_ENTRY) {
1079+
zval *zv = zend_hash_find_ex(&ce->function_table, ZSTR_KNOWN(ZEND_STR_SLEEP), 1);
1080+
1081+
if (zv) {
1082+
zval retval, tmp;
1083+
1084+
ZVAL_OBJ_COPY(&tmp, Z_OBJ_P(struc));
1085+
if (php_var_serialize_call_sleep(Z_OBJ(tmp), Z_FUNC_P(zv), &retval) == FAILURE) {
1086+
if (!EG(exception)) {
1087+
/* we should still add element even if it's not OK,
1088+
* since we already wrote the length of the array before */
1089+
smart_str_appendl(buf, "N;", 2);
1090+
}
1091+
OBJ_RELEASE(Z_OBJ(tmp));
1092+
return;
10801093
}
1081-
zval_ptr_dtor(&tmp);
1094+
1095+
php_var_serialize_class(buf, &tmp, &retval, var_hash);
1096+
zval_ptr_dtor(&retval);
1097+
OBJ_RELEASE(Z_OBJ(tmp));
10821098
return;
10831099
}
1084-
1085-
php_var_serialize_class(buf, &tmp, &retval, var_hash);
1086-
zval_ptr_dtor(&retval);
1087-
zval_ptr_dtor(&tmp);
1088-
return;
10891100
}
10901101

10911102
incomplete_class = php_var_serialize_class_name(buf, struc);

ext/standard/var_unserializer.re

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,6 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
222222
var_entries *var_hash = (*var_hashx)->entries.next;
223223
var_dtor_entries *var_dtor_hash = (*var_hashx)->first_dtor;
224224
bool delayed_call_failed = 0;
225-
zval wakeup_name;
226-
ZVAL_UNDEF(&wakeup_name);
227225

228226
#if VAR_ENTRIES_DBG
229227
fprintf(stderr, "var_destroy( " ZEND_LONG_FMT ")\n", var_hash?var_hash->used_slots:-1L);
@@ -246,12 +244,26 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
246244
/* Perform delayed __wakeup calls */
247245
if (!delayed_call_failed) {
248246
zval retval;
249-
if (Z_ISUNDEF(wakeup_name)) {
250-
ZVAL_STRINGL(&wakeup_name, "__wakeup", sizeof("__wakeup") - 1);
251-
}
247+
zend_fcall_info fci;
248+
zend_fcall_info_cache fci_cache;
249+
250+
ZEND_ASSERT(Z_TYPE_P(zv) == IS_OBJECT);
251+
252+
fci.size = sizeof(fci);
253+
fci.object = Z_OBJ_P(zv);
254+
fci.retval = &retval;
255+
fci.param_count = 0;
256+
fci.params = NULL;
257+
fci.named_params = NULL;
258+
ZVAL_UNDEF(&fci.function_name);
259+
260+
fci_cache.function_handler = zend_hash_find_ptr(
261+
&fci.object->ce->function_table, ZSTR_KNOWN(ZEND_STR_WAKEUP));
262+
fci_cache.object = fci.object;
263+
fci_cache.called_scope = fci.object->ce;
252264

253265
BG(serialize_lock)++;
254-
if (call_user_function(NULL, zv, &wakeup_name, &retval, 0, 0) == FAILURE || Z_ISUNDEF(retval)) {
266+
if (zend_call_function(&fci, &fci_cache) == FAILURE || Z_ISUNDEF(retval)) {
255267
delayed_call_failed = 1;
256268
GC_ADD_FLAGS(Z_OBJ_P(zv), IS_OBJ_DESTRUCTOR_CALLED);
257269
}
@@ -288,8 +300,6 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
288300
var_dtor_hash = next;
289301
}
290302

291-
zval_ptr_dtor_nogc(&wakeup_name);
292-
293303
if ((*var_hashx)->ref_props) {
294304
zend_hash_destroy((*var_hashx)->ref_props);
295305
FREE_HASHTABLE((*var_hashx)->ref_props);
@@ -788,7 +798,7 @@ static inline int object_common(UNSERIALIZE_PARAMETER, zend_long elements, bool
788798
}
789799

790800
has_wakeup = Z_OBJCE_P(rval) != PHP_IC_ENTRY
791-
&& zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1);
801+
&& zend_hash_exists(&Z_OBJCE_P(rval)->function_table, ZSTR_KNOWN(ZEND_STR_WAKEUP));
792802

793803
ht = Z_OBJPROP_P(rval);
794804
if (elements >= (zend_long)(HT_MAX_SIZE - zend_hash_num_elements(ht))) {

0 commit comments

Comments
 (0)