From: Marcus Boerger Date: Thu, 29 May 2003 21:08:08 +0000 (+0000) Subject: Optimize interface checks X-Git-Tag: RELEASE_1_0_2~533 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=283f52f415ce644c1a1ae626d34a3f76983fd3df;p=php Optimize interface checks --- diff --git a/ext/spl/spl_engine.c b/ext/spl/spl_engine.c index 02be8d000d..1f4bb78f47 100755 --- a/ext/spl/spl_engine.c +++ b/ext/spl/spl_engine.c @@ -144,34 +144,27 @@ int spl_is_instance_of(zval **obj, zend_class_entry *ce TSRMLS_DC) zend_class_entry *instance_ce; if (obj && (instance_ce = spl_get_class_entry(*obj TSRMLS_CC)) != NULL) { - if (instanceof_function(instance_ce, ce TSRMLS_CC)) { - return 1; - } + return instanceof_function(instance_ce, ce TSRMLS_CC); } return 0; } /* }}} */ /* {{{ spl_implements */ -int spl_implements(zval **obj, zend_class_entry *ce TSRMLS_DC) +spl_is_a spl_implements(zend_class_entry *ce) { - /* Ensure everything needed is available before checking for the type. - */ - zend_class_entry *instance_ce; - - if (obj && (instance_ce = spl_get_class_entry(*obj TSRMLS_CC)) != NULL) { - int i; - - while (instance_ce) { - for (i = 0; i < instance_ce->num_interfaces; i++) { - if (instance_ce->interfaces[i] == ce) { - return 1; - } - } - instance_ce = instance_ce->parent; - } + register spl_is_a is_a = 0; + register int i = ce->num_interfaces; + register zend_class_entry **pce = ce->interfaces; + + while (i--) { + if (*pce == spl_ce_iterator) is_a |= SPL_IS_A_ITERATOR; + else if (*pce == spl_ce_forward) is_a |= SPL_IS_A_FORWARD; + else if (*pce == spl_ce_assoc) is_a |= SPL_IS_A_ASSOC; + else if (*pce == spl_ce_sequence) is_a |= SPL_IS_A_SEQUENCE; + pce++; } - return spl_is_instance_of(obj, ce TSRMLS_CC); + return is_a; } /* }}} */ diff --git a/ext/spl/spl_engine.h b/ext/spl/spl_engine.h index 90d2320734..ae9db4a450 100755 --- a/ext/spl/spl_engine.h +++ b/ext/spl/spl_engine.h @@ -106,7 +106,15 @@ void spl_unlock_zval_ptr_ptr(znode *node, temp_variable *Ts TSRMLS_DC); zval * spl_get_zval_ptr(znode *node, temp_variable *Ts, zval **should_free TSRMLS_DC); int spl_is_instance_of(zval **obj, zend_class_entry *ce TSRMLS_DC); -int spl_implements(zval **obj, zend_class_entry *ce TSRMLS_DC); + +typedef enum { + SPL_IS_A_ITERATOR = 1, + SPL_IS_A_FORWARD = 2, + SPL_IS_A_ASSOC = 4, + SPL_IS_A_SEQUENCE = 8 +} spl_is_a; + +spl_is_a spl_implements(zend_class_entry *ce); #endif /* SPL_ENGINE_H */ diff --git a/ext/spl/spl_foreach.c b/ext/spl/spl_foreach.c index abf64ccd57..6476a82461 100755 --- a/ext/spl/spl_foreach.c +++ b/ext/spl/spl_foreach.c @@ -40,7 +40,7 @@ typedef struct { zval *obj; zend_class_entry *obj_ce; zend_uint index; - zend_uint is_ce_assoc; + spl_is_a is_a; zend_function *f_next; zend_function *f_rewind; zend_function *f_more; @@ -53,17 +53,26 @@ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_RESET) { zval **obj, *retval; spl_foreach_proxy proxy; + zend_class_entry *instance_ce; + spl_is_a is_a = 0; obj = spl_get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts) TSRMLS_CC); - if (spl_implements(obj, spl_ce_iterator TSRMLS_CC)) { + + if (obj && (instance_ce = spl_get_class_entry(*obj TSRMLS_CC)) != NULL) { + is_a = spl_implements(instance_ce); + } + + if (is_a & SPL_IS_A_ITERATOR) { spl_unlock_zval_ptr_ptr(&EX(opline)->op1, EX(Ts) TSRMLS_CC); spl_begin_method_call_ex(obj, NULL, NULL, "new_iterator", sizeof("new_iterator")-1, &retval TSRMLS_CC); - if (!spl_implements(&retval, spl_ce_forward TSRMLS_CC)) { + instance_ce = spl_get_class_entry(retval TSRMLS_CC); + is_a = spl_implements(instance_ce); + if (!(is_a & SPL_IS_A_FORWARD)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Objects created by new_iterator() must implement spl::forward"); ZEND_EXECUTE_HOOK_ORIGINAL(ZEND_FE_RESET); } PZVAL_LOCK(retval); - } else if (spl_implements(obj, spl_ce_forward TSRMLS_CC)) { + } else if (is_a & SPL_IS_A_FORWARD) { spl_unlock_zval_ptr_ptr(&EX(opline)->op1, EX(Ts) TSRMLS_CC); (*obj)->refcount += 2; /* lock two times */ retval = *obj; @@ -74,8 +83,8 @@ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_RESET) /* create the proxy */ memset(&proxy, 0, sizeof(spl_foreach_proxy)); proxy.obj = retval; - proxy.obj_ce = spl_get_class_entry(retval TSRMLS_CC); - proxy.is_ce_assoc = spl_implements(&retval, spl_ce_assoc TSRMLS_CC); + proxy.obj_ce = instance_ce; + proxy.is_a = is_a; /* And pack it into a zval. Since it is nowhere accessible using a * zval of type STRING is the fastest approach of storing the proxy. */ @@ -130,7 +139,7 @@ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_FETCH) if (proxy->index++) { spl_begin_method_call_this(obj, proxy->obj_ce, &proxy->f_next, "next", sizeof("next")-1, &tmp TSRMLS_CC); } else { - if (spl_implements(obj, spl_ce_sequence TSRMLS_CC)) { + if (proxy->is_a & SPL_IS_A_SEQUENCE) { spl_begin_method_call_this(obj, proxy->obj_ce, &proxy->f_rewind, "rewind", sizeof("rewind")-1, &tmp TSRMLS_CC); } op_array->opcodes[EX(opline)->op2.u.opline_num].op2 = *op1; @@ -142,7 +151,7 @@ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_FETCH) spl_begin_method_call_ex(obj, proxy->obj_ce, &proxy->f_current, "current", sizeof("current")-1, &value TSRMLS_CC); - if (proxy->is_ce_assoc) { + if (proxy->is_a & SPL_IS_A_ASSOC) { spl_begin_method_call_ex(obj, proxy->obj_ce, &proxy->f_key, "key", sizeof("key")-1, &key TSRMLS_CC); } else { MAKE_STD_ZVAL(key);