Skip to content

Commit 16649cb

Browse files
committed
Cache haschildren/getchildren methods of recursive iterators.
1 parent db33af7 commit 16649cb

File tree

1 file changed

+26
-9
lines changed

1 file changed

+26
-9
lines changed

ext/spl/spl_iterators.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ typedef struct _spl_sub_iterator {
8585
zval zobject;
8686
zend_class_entry *ce;
8787
RecursiveIteratorState state;
88+
zend_function *haschildren;
89+
zend_function *getchildren;
8890
} spl_sub_iterator;
8991

9092
typedef struct _spl_recursive_it_object {
@@ -222,7 +224,6 @@ static void spl_recursive_it_get_current_key(zend_object_iterator *iter, zval *k
222224
static void spl_recursive_it_move_forward_ex(spl_recursive_it_object *object, zval *zthis)
223225
{
224226
zend_object_iterator *iterator;
225-
zval *zobject;
226227
zend_class_entry *ce;
227228
zval retval, child;
228229
zend_object_iterator *sub_iter;
@@ -251,12 +252,14 @@ static void spl_recursive_it_move_forward_ex(spl_recursive_it_object *object, zv
251252
object->iterators[object->level].state = RS_TEST;
252253
/* break; */
253254
case RS_TEST:
254-
ce = object->iterators[object->level].ce;
255-
zobject = &object->iterators[object->level].zobject;
256255
if (object->callHasChildren) {
257256
zend_call_method_with_0_params(Z_OBJ_P(zthis), object->ce, &object->callHasChildren, "callHasChildren", &retval);
258257
} else {
259-
zend_call_method_with_0_params(Z_OBJ_P(zobject), ce, NULL, "haschildren", &retval);
258+
zend_class_entry *ce = object->iterators[object->level].ce;
259+
zend_object *obj = Z_OBJ(object->iterators[object->level].zobject);
260+
zend_function **cache = &object->iterators[object->level].haschildren;
261+
262+
zend_call_method_with_0_params(obj, ce, cache, "haschildren", &retval);
260263
}
261264
if (EG(exception)) {
262265
if (!(object->flags & RIT_CATCH_GET_CHILD)) {
@@ -313,12 +316,14 @@ static void spl_recursive_it_move_forward_ex(spl_recursive_it_object *object, zv
313316
}
314317
return /* self */;
315318
case RS_CHILD:
316-
ce = object->iterators[object->level].ce;
317-
zobject = &object->iterators[object->level].zobject;
318319
if (object->callGetChildren) {
319320
zend_call_method_with_0_params(Z_OBJ_P(zthis), object->ce, &object->callGetChildren, "callGetChildren", &child);
320321
} else {
321-
zend_call_method_with_0_params(Z_OBJ_P(zobject), ce, NULL, "getchildren", &child);
322+
zend_class_entry *ce = object->iterators[object->level].ce;
323+
zend_object *obj = Z_OBJ(object->iterators[object->level].zobject);
324+
zend_function **cache = &object->iterators[object->level].getchildren;
325+
326+
zend_call_method_with_0_params(obj, ce, cache, "getchildren", &child);
322327
}
323328

324329
if (EG(exception)) {
@@ -350,6 +355,16 @@ static void spl_recursive_it_move_forward_ex(spl_recursive_it_object *object, zv
350355
object->iterators[object->level].iterator = sub_iter;
351356
object->iterators[object->level].ce = ce;
352357
object->iterators[object->level].state = RS_START;
358+
if (object->level > 0
359+
&& object->iterators[object->level - 1].ce == 0) {
360+
object->iterators[object->level].haschildren =
361+
object->iterators[object->level - 1].haschildren;
362+
object->iterators[object->level].getchildren =
363+
object->iterators[object->level - 1].getchildren;
364+
} else {
365+
object->iterators[object->level].haschildren = NULL;
366+
object->iterators[object->level].getchildren = NULL;
367+
}
353368
if (sub_iter->funcs->rewind) {
354369
sub_iter->funcs->rewind(sub_iter);
355370
}
@@ -572,6 +587,8 @@ static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_cla
572587
ZVAL_OBJ(&intern->iterators[0].zobject, Z_OBJ_P(iterator));
573588
intern->iterators[0].ce = ce_iterator;
574589
intern->iterators[0].state = RS_START;
590+
intern->iterators[0].haschildren = NULL;
591+
intern->iterators[0].getchildren = NULL;
575592

576593
zend_restore_error_handling(&error_handling);
577594

@@ -761,7 +778,7 @@ PHP_METHOD(RecursiveIteratorIterator, callHasChildren)
761778
if (Z_TYPE_P(zobject) == IS_UNDEF) {
762779
RETURN_FALSE;
763780
} else {
764-
zend_call_method_with_0_params(Z_OBJ_P(zobject), ce, NULL, "haschildren", return_value);
781+
zend_call_method_with_0_params(Z_OBJ_P(zobject), ce, &object->iterators[object->level].haschildren, "haschildren", return_value);
765782
if (Z_TYPE_P(return_value) == IS_UNDEF) {
766783
RETURN_FALSE;
767784
}
@@ -785,7 +802,7 @@ PHP_METHOD(RecursiveIteratorIterator, callGetChildren)
785802
if (Z_TYPE_P(zobject) == IS_UNDEF) {
786803
return;
787804
} else {
788-
zend_call_method_with_0_params(Z_OBJ_P(zobject), ce, NULL, "getchildren", return_value);
805+
zend_call_method_with_0_params(Z_OBJ_P(zobject), ce, &object->iterators[object->level].getchildren, "getchildren", return_value);
789806
if (Z_TYPE_P(return_value) == IS_UNDEF) {
790807
RETURN_NULL();
791808
}

0 commit comments

Comments
 (0)