summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Boerger <helly@php.net>2003-05-29 21:08:08 +0000
committerMarcus Boerger <helly@php.net>2003-05-29 21:08:08 +0000
commit283f52f415ce644c1a1ae626d34a3f76983fd3df (patch)
tree9140f5edf27eb9dd68363f37e55c88a79e9a760f
parent499f902a30fd8353aae4e8e9b105ec9d251401fa (diff)
downloadphp-git-283f52f415ce644c1a1ae626d34a3f76983fd3df.tar.gz
Optimize interface checks
-rwxr-xr-xext/spl/spl_engine.c33
-rwxr-xr-xext/spl/spl_engine.h10
-rwxr-xr-xext/spl/spl_foreach.c25
3 files changed, 39 insertions, 29 deletions
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);