]> granicus.if.org Git - php/commitdiff
Optimize interface checks
authorMarcus Boerger <helly@php.net>
Thu, 29 May 2003 21:08:08 +0000 (21:08 +0000)
committerMarcus Boerger <helly@php.net>
Thu, 29 May 2003 21:08:08 +0000 (21:08 +0000)
ext/spl/spl_engine.c
ext/spl/spl_engine.h
ext/spl/spl_foreach.c

index 02be8d000d29386639b5f4574f0e4b4ff0ba34b2..1f4bb78f477293b0f58573e88397bcf41296e156 100755 (executable)
@@ -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;
 }
 /* }}} */
 
index 90d2320734ae0265a670a6f91bef1162bd482107..ae9db4a45092d63775b5a339b7e70a663143440b 100755 (executable)
@@ -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 */
 
index abf64ccd57f1cb5e1927782d204977c6f07ab516..6476a8246170c2e83070196d5c44d94a82f8974e 100755 (executable)
@@ -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);