]> granicus.if.org Git - php/commitdiff
Fixes and optimizations
authorMarcus Boerger <helly@php.net>
Sat, 24 May 2003 13:47:49 +0000 (13:47 +0000)
committerMarcus Boerger <helly@php.net>
Sat, 24 May 2003 13:47:49 +0000 (13:47 +0000)
ext/spl/README
ext/spl/spl_array.c
ext/spl/spl_engine.c
ext/spl/spl_engine.h
ext/spl/spl_foreach.c
ext/spl/spl_functions.c
ext/spl/tests/foreach.phpt

index e4d9aaf7a26eb05a8b032d43c9db9847e5d387f0..5d12e7d42f270a6e60f2f0d9d8f746e3491f3977 100755 (executable)
@@ -1,4 +1,3 @@
-<pre>
 This is an extension that aims to implement some efficient data access 
 interfaces and classes.
 
@@ -35,5 +34,3 @@ There is no efficient way for "lazy or just in time evaluating" so 4) should
 be the best case. And 4) also enables the foreach trick.
 
 To implement 3) and 4) with other db extensions ask me and wait for LT to pass.
-
-</pre>
\ No newline at end of file
index 7c68d3c06f17ca978e76e6f335719452a3d3e150..186cdb78a70d2ae2e71b478a741646019447534c 100755 (executable)
@@ -119,13 +119,10 @@ zend_object_value spl_array_writer_default_create(zend_class_entry *class_type T
 /* {{{ spl_array_writer_default_set */
 void spl_array_writer_default_set(zval *object, zval *newval, zval **retval TSRMLS_DC)
 {
-       zval *obj, *idx;
        spl_array_writer_object *writer;
 
        writer = (spl_array_writer_object *) zend_object_store_get_object(object TSRMLS_CC);
-       obj = writer->obj;
-       idx = writer->idx;
-       spl_begin_method_call_arg_ex2(&obj, "set", retval, &idx, &newval, 0, NULL TSRMLS_CC);
+       spl_begin_method_call_arg_ex2(&writer->obj, NULL, "set", sizeof("set")-1, retval, writer->idx, newval TSRMLS_CC);
 }
 /* }}} */
 
@@ -172,7 +169,7 @@ int spl_fetch_dimension_address(znode *result, znode *op1, znode *op2, temp_vari
                zval *exists;
 
                /*ALLOC_ZVAL(exists); not needed */
-               spl_begin_method_call_arg_ex1(container_ptr, "exists", &exists, &dim, 0, NULL TSRMLS_CC);
+               spl_begin_method_call_arg_ex1(container_ptr, NULL, "exists", sizeof("exists")-1, &exists, dim TSRMLS_CC);
                if (!i_zend_is_true(exists)) {
                        if (type == BP_VAR_R || type == BP_VAR_RW) {
                                SEPARATE_ZVAL(&dim);
@@ -191,13 +188,13 @@ int spl_fetch_dimension_address(znode *result, znode *op1, znode *op2, temp_vari
                }
                DELETE_RET_ZVAL(exists);
                if (type == BP_VAR_R || type == BP_VAR_IS) {
-                       spl_begin_method_call_arg_ex1(container_ptr, "get", retval, &dim, 0, NULL TSRMLS_CC);
+                       spl_begin_method_call_arg_ex1(container_ptr, NULL, "get", sizeof("get")-1, retval, dim TSRMLS_CC);
                        (*retval)->refcount--;
                } else 
 #ifdef SPL_ARRAY_WRITE
                if (spl_is_instance_of(container_ptr, spl_ce_array_access_ex TSRMLS_CC)) {
                        /* array_access_ex instaces have their own way of creating an access_writer */
-                       spl_begin_method_call_arg_ex1(container_ptr, "new_writer", retval, &dim, 0, NULL TSRMLS_CC);
+                       spl_begin_method_call_arg_ex1(container_ptr, NULL, "new_writer", sizeof("new_writer")-1, retval, dim TSRMLS_CC);
                        T(result->u.var).var.ptr = *retval;
                        AI_PTR_2_PTR_PTR(T(result->u.var).var);
                        SELECTIVE_PZVAL_LOCK(*retval, result);
@@ -217,7 +214,7 @@ int spl_fetch_dimension_address(znode *result, znode *op1, znode *op2, temp_vari
                }
                SELECTIVE_PZVAL_LOCK(*retval, result);
 #else
-               zend_error(E_ERROR, "SPL compiled withut array write hook");
+               zend_error(E_ERROR, "SPL compiled without array write hook");
 #endif
                FREE_OP(Ts, op2, EG(free_op2));
                return 0;
@@ -294,7 +291,7 @@ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_ASSIGN)
                        spl_array_writer_default_set(*writer, newval, &retval TSRMLS_CC);
                } else if (spl_is_instance_of(writer, spl_ce_array_writer TSRMLS_CC)) {
                        newval = spl_get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2) TSRMLS_CC);
-                       spl_begin_method_call_arg_ex1(writer, "set", &retval, &newval, 0, NULL TSRMLS_CC);
+                       spl_begin_method_call_arg_ex1(writer, NULL, "set", sizeof("set")-1, &retval, newval TSRMLS_CC);
                } else {
                        ZEND_EXECUTE_HOOK_ORIGINAL(ZEND_ASSIGN);
                }
index 04dbd75d7860cb33b93142deadcb5bbf59caa658..aa72cfd9cdfbf094149c1d7b6afa909bb69d7d2c 100755 (executable)
 #include "spl_functions.h"
 #include "spl_engine.h"
 
-/* {{{ spl_begin_method_call_arg */
-int spl_begin_method_call_arg(zval **ce, char *function_name, zval *retval, zval *arg1 TSRMLS_DC)
-{
-       zval *args[1];
-       zval fn_name;
-       
-       ZVAL_STRING(&fn_name, function_name, 0);
-       
-       args[0] = arg1;
-       return call_user_function(&Z_OBJCE_PP(ce)->function_table, ce, &fn_name, retval, 1, args TSRMLS_CC);
-}
-/* }}} */
-
-/* {{{ spl_begin_method_call_this */
-int spl_begin_method_call_this(zval **ce, char *function_name, zval *retval TSRMLS_DC)
-{
-       zval fn_name;
-       
-       ZVAL_STRING(&fn_name, function_name, 0);
-       
-       return call_user_function(&Z_OBJCE_PP(ce)->function_table, ce, &fn_name, retval, 0, NULL TSRMLS_CC);
-}
-/* }}} */
-
-/* {{{ spl_begin_method_call_arg_ex1 */
-int spl_begin_method_call_arg_ex1(zval **ce, char *function_name, zval **retval, zval **arg1, int no_separation, HashTable *symbol_table TSRMLS_DC)
-{
-       zval **args[1];
-       zval fn_name;
-       
-       ZVAL_STRING(&fn_name, function_name, 0);
-       
-       args[0] = arg1;
-       return call_user_function_ex(&Z_OBJCE_PP(ce)->function_table, ce, &fn_name, retval, 1, args, no_separation, symbol_table TSRMLS_CC);
-}
-/* }}} */
-
-/* {{{ spl_begin_method_call_arg_ex2 */
-int spl_begin_method_call_arg_ex2(zval **ce, char *function_name, zval **retval, zval **arg1, zval **arg2, int no_separation, HashTable *symbol_table TSRMLS_DC)
-{
-       zval **args[2];
-       zval fn_name;
-       
-       ZVAL_STRING(&fn_name, function_name, 0);
-       
-       args[0] = arg1;
-       args[1] = arg2;
-       return call_user_function_ex(&Z_OBJCE_PP(ce)->function_table, ce, &fn_name, retval, 2, args, no_separation, symbol_table TSRMLS_CC);
-}
-/* }}} */
-
 /* {{{ spl_instanciate */
 void spl_instanciate(zend_class_entry *pce, zval **object TSRMLS_DC)
 {
@@ -92,21 +41,15 @@ void spl_instanciate(zend_class_entry *pce, zval **object TSRMLS_DC)
 /* }}} */
 
 /* {{{ spl_instanciate_arg_ex2 */
-int spl_instanciate_arg_ex2(zend_class_entry *pce, zval **retval, zval **arg1, zval **arg2, int no_separation, HashTable *symbol_table TSRMLS_DC)
+int spl_instanciate_arg_ex2(zend_class_entry *pce, zval **retval, zval *arg1, zval *arg2, HashTable *symbol_table TSRMLS_DC)
 {
-       zval **args[2];
-       zval fn_name;
        zval *object;
        
        spl_instanciate(pce, &object TSRMLS_CC);
        
        retval = &EG(uninitialized_zval_ptr);
        
-       ZVAL_STRING(&fn_name, pce->constructor->common.function_name, 0);
-       
-       args[0] = arg1;
-       args[1] = arg2;
-       call_user_function_ex(&pce->function_table, &object, &fn_name, retval, 2, args, no_separation, symbol_table TSRMLS_CC);
+       spl_call_method(&object, NULL, pce->constructor->common.function_name, strlen(pce->constructor->common.function_name), retval, NULL TSRMLS_CC, 2, arg1, arg2);
        *retval = object;
        return 0;
 }
@@ -243,6 +186,167 @@ int spl_implements(zval **obj, zend_class_entry *ce TSRMLS_DC)
 }
 /* }}} */
 
+#undef EX
+#define EX(element) execute_data.element
+
+/* {{{ spl_call_method */
+int spl_call_method(zval **object_pp, zend_function **fn_proxy, char *function_name, int fname_len, zval **retval, HashTable *symbol_table TSRMLS_DC, int param_count, ...)
+{
+       int i;
+       zval **original_return_value;
+       HashTable *calling_symbol_table;
+       zend_function_state *original_function_state_ptr;
+       zend_op_array *original_op_array;
+       zend_op **original_opline_ptr;
+       zval *orig_free_op1, *orig_free_op2;
+       int (*orig_unary_op)(zval *result, zval *op1);
+       int (*orig_binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC);
+       zend_class_entry *current_scope;
+       zend_class_entry *calling_scope = NULL;
+       zval *current_this;
+       zend_namespace *current_namespace = EG(active_namespace);
+       zend_execute_data execute_data;
+       zend_class_entry *obj_ce;
+       va_list args;
+
+       if (!object_pp || (obj_ce = spl_get_class_entry(*object_pp TSRMLS_CC)) == NULL) {
+               return FAILURE;
+       }
+
+       /* Initialize execute_data */
+       EX(fbc) = NULL;
+       EX(Ts) = NULL;
+       EX(op_array) = NULL;
+       EX(opline) = NULL;
+
+       EX(object) = *object_pp;
+       calling_scope = Z_OBJCE_PP(object_pp);
+
+       original_function_state_ptr = EG(function_state_ptr);
+       if (fn_proxy && *fn_proxy) {
+               EX(function_state).function = *fn_proxy;
+       } else {
+               if (zend_hash_find(&obj_ce->function_table, function_name, fname_len+1, (void **) &EX(function_state).function)==FAILURE) {
+                       return FAILURE;
+               }
+               if (fn_proxy) {
+                       *fn_proxy = EX(function_state).function;
+               }
+       }
+
+       va_start(args, param_count);
+       for (i=0; i<param_count; i++) {
+               zval *arg;
+               zval *param;
+
+               arg = va_arg(args, zval*);
+
+               if (EX(function_state).function->common.arg_types
+                       && i<EX(function_state).function->common.arg_types[0]
+                       && EX(function_state).function->common.arg_types[i+1]==BYREF_FORCE
+                       && !PZVAL_IS_REF(arg)) {
+                       if (arg->refcount > 1) {
+                               zval *new_zval;
+
+                               ALLOC_ZVAL(new_zval);
+                               *new_zval = *arg;
+                               zval_copy_ctor(new_zval);
+                               new_zval->refcount = 1;
+                               arg->refcount--;
+                               arg = new_zval;
+                       }
+                       arg->refcount++;
+                       arg->is_ref = 1;
+                       param = arg;
+               } else if (arg != &EG(uninitialized_zval)) {
+                       arg->refcount++;
+                       param = arg;
+               } else {
+                       ALLOC_ZVAL(param);
+                       *param = *arg;
+                       INIT_PZVAL(param);
+               }
+               zend_ptr_stack_push(&EG(argument_stack), param);
+       }
+       va_end(args);
+
+       zend_ptr_stack_n_push(&EG(argument_stack), 2, (void *) (long) param_count, NULL);
+
+       EG(function_state_ptr) = &EX(function_state);
+
+       current_scope = EG(scope);
+       EG(scope) = calling_scope;
+
+       current_this = EG(This);
+
+       EG(This) = *object_pp;
+
+       if (!PZVAL_IS_REF(EG(This))) {
+               EG(This)->refcount++; /* For $this pointer */
+       } else {
+               zval *this_ptr;
+
+               ALLOC_ZVAL(this_ptr);
+               *this_ptr = *EG(This);
+               INIT_PZVAL(this_ptr);
+               zval_copy_ctor(this_ptr);
+               EG(This) = this_ptr;
+       }
+
+       EX(prev_execute_data) = EG(current_execute_data);
+       EG(current_execute_data) = &execute_data;
+
+       if (EX(function_state).function->type == ZEND_USER_FUNCTION) {
+               calling_symbol_table = EG(active_symbol_table);
+               if (symbol_table) {
+                       EG(active_symbol_table) = symbol_table;
+               } else {
+                       ALLOC_HASHTABLE(EG(active_symbol_table));
+                       zend_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0);
+               }
+
+               original_return_value = EG(return_value_ptr_ptr);
+               original_op_array = EG(active_op_array);
+               EG(return_value_ptr_ptr) = retval;
+               EG(active_op_array) = (zend_op_array *) EX(function_state).function;
+               original_opline_ptr = EG(opline_ptr);
+               orig_free_op1 = EG(free_op1);
+               orig_free_op2 = EG(free_op2);
+               orig_unary_op = EG(unary_op);
+               orig_binary_op = EG(binary_op);
+               zend_execute(EG(active_op_array) TSRMLS_CC);
+               if (!symbol_table) {
+                       zend_hash_destroy(EG(active_symbol_table));
+                       FREE_HASHTABLE(EG(active_symbol_table));
+               }
+               EG(active_symbol_table) = calling_symbol_table;
+               EG(active_op_array) = original_op_array;
+               EG(return_value_ptr_ptr)=original_return_value;
+               EG(opline_ptr) = original_opline_ptr;
+               EG(free_op1) = orig_free_op1;
+               EG(free_op2) = orig_free_op2;
+               EG(unary_op) = orig_unary_op;
+               EG(binary_op) = orig_binary_op;
+       } else {
+               ALLOC_INIT_ZVAL(*retval);
+               ((zend_internal_function *) EX(function_state).function)->handler(param_count, *retval, (object_pp?*object_pp:NULL), 1 TSRMLS_CC);
+               INIT_PZVAL(*retval);
+       }
+       zend_ptr_stack_clear_multiple(TSRMLS_C);
+       EG(function_state_ptr) = original_function_state_ptr;
+       EG(active_namespace) = current_namespace;
+
+       if (EG(This)) {
+               zval_ptr_dtor(&EG(This));
+       }
+       EG(scope) = current_scope;
+       EG(This) = current_this;
+       EG(current_execute_data) = EX(prev_execute_data);                       \
+
+       return SUCCESS;
+}
+/* }}} */
+
 /*
  * Local variables:
  * tab-width: 4
index db61a1982df8733bcd91406c3ec93cbb8b0e8973..040862f8bf39899ca4acd1bc905445c65d95fe59 100755 (executable)
 
 int zend_do_fcall_common_helper(ZEND_OPCODE_HANDLER_ARGS);
 
-int spl_begin_method_call_arg(zval **ce, char *function_name, zval *retval, zval *arg1 TSRMLS_DC);
-int spl_begin_method_call_this(zval **ce, char *function_name, zval *retval TSRMLS_DC);
-int spl_begin_method_call_arg_ex1(zval **ce, char *function_name, zval **retval, zval **arg1, int no_separation, HashTable *symbol_table TSRMLS_DC);
-int spl_begin_method_call_arg_ex2(zval **ce, char *function_name, zval **retval, zval **arg1, zval **arg2, int no_separation, HashTable *symbol_table TSRMLS_DC);
+int spl_call_method(zval **object_pp, zend_function **fn_proxy, char *function_name, int function_name_len, zval **retval_ptr, HashTable *symbol_table TSRMLS_DC, int param_count, ...);
+
+/* {{{ spl_begin_method_call_arg */
+static inline int spl_begin_method_call_arg(zval **ce, zend_function **fn_proxy, char *function_name, int fname_len, zval *retval, zval *arg1 TSRMLS_DC)
+{
+       zval *local_retval;
+       int ret = spl_call_method(ce, fn_proxy, function_name, fname_len, &local_retval, NULL TSRMLS_CC, 1, arg1);
+       if (local_retval) {
+               COPY_PZVAL_TO_ZVAL(*retval, local_retval);
+       } else {
+               INIT_ZVAL(*retval);
+       }
+       return ret;
+}
+/* }}} */
+
+/* {{{ spl_begin_method_call_this */
+static inline int spl_begin_method_call_this(zval **ce, zend_function **fn_proxy, char *function_name, int fname_len, zval *retval TSRMLS_DC)
+{
+       zval *local_retval;
+       int ret = spl_call_method(ce, fn_proxy, function_name, fname_len, &local_retval, NULL TSRMLS_CC, 0);
+       if (local_retval) {
+               COPY_PZVAL_TO_ZVAL(*retval, local_retval);
+       } else {
+               INIT_ZVAL(*retval);
+       }
+       return ret;
+}
+/* }}} */
+
+/* {{{ spl_begin_method_call_ex */
+static inline int spl_begin_method_call_ex(zval **ce, zend_function **fn_proxy, char *function_name, int fname_len, zval **retval TSRMLS_DC)
+{
+       return spl_call_method(ce, fn_proxy, function_name, fname_len, retval, NULL TSRMLS_CC, 0);
+}
+/* }}} */
+
+/* {{{ spl_begin_method_call_arg_ex1 */
+static inline int spl_begin_method_call_arg_ex1(zval **ce, zend_function **fn_proxy, char *function_name, int fname_len, zval **retval, zval *arg1 TSRMLS_DC)
+{
+       return spl_call_method(ce, fn_proxy, function_name, fname_len, retval, NULL TSRMLS_CC, 1, arg1);
+}
+/* }}} */
+
+/* {{{ spl_begin_method_call_arg_ex2 */
+static inline int spl_begin_method_call_arg_ex2(zval **ce, zend_function **fn_proxy, char *function_name, int fname_len, zval **retval, zval *arg1, zval *arg2 TSRMLS_DC)
+{
+       return spl_call_method(ce, fn_proxy, function_name, fname_len, retval, NULL TSRMLS_CC, 2, arg1, arg2);
+}
+/* }}} */
 
 void spl_instanciate(zend_class_entry *pce, zval **object TSRMLS_DC);
-int spl_instanciate_arg_ex2(zend_class_entry *pce, zval **retval, zval **arg1, zval **arg2, int no_separation, HashTable *symbol_table TSRMLS_DC);
+int spl_instanciate_arg_ex2(zend_class_entry *pce, zval **retval, zval *arg1, zval *arg2, HashTable *symbol_table TSRMLS_DC);
 
 zval ** spl_get_zval_ptr_ptr(znode *node, temp_variable *Ts TSRMLS_DC);
 void spl_unlock_zval_ptr_ptr(znode *node, temp_variable *Ts TSRMLS_DC);
index cbe7dfd1e2b9c536303cb3e400adb8d8fa22ee27..ee77b031750e586b4001e29352339425445f412d 100755 (executable)
 #include "spl_engine.h"
 #include "spl_foreach.h"
 
+#define ezalloc(size) \
+       memset(emalloc(size), 0, size)
+
+typedef struct {
+       zend_uint     index;
+       zend_function *f_next;
+       zend_function *f_rewind;
+       zend_function *f_more;
+       zend_function *f_current;
+       zend_function *f_key;
+} spl_foreach_proxy;
+
 /* {{{ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_RESET) */
 ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_RESET)
 {
@@ -41,10 +53,10 @@ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_RESET)
                if (spl_implements(obj, spl_ce_iterator TSRMLS_CC)) {
                        spl_unlock_zval_ptr_ptr(&EX(opline)->op1, EX(Ts) TSRMLS_CC);
                        MAKE_STD_ZVAL(retval);
-                       spl_begin_method_call_this(obj, "new_iterator", retval TSRMLS_CC);
+                       spl_begin_method_call_this(obj, NULL, "new_iterator", sizeof("new_iterator")-1, retval TSRMLS_CC);
                        EX_T(EX(opline)->result.u.var).var.ptr = retval;
                        EX_T(EX(opline)->result.u.var).var.ptr_ptr = &EX_T(EX(opline)->result.u.var).var.ptr;   
-                       EX(opline)->op2.u.EA.type = 0; /* missuse as index */
+                       /* EX(opline)->result.u.EA.type = 0; */
 
                        PZVAL_LOCK(retval);
 
@@ -54,7 +66,7 @@ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_RESET)
 
                        EX_T(EX(opline)->result.u.var).var.ptr = *obj;
                        EX_T(EX(opline)->result.u.var).var.ptr_ptr = &EX_T(EX(opline)->result.u.var).var.ptr;   
-                       EX(opline)->op2.u.EA.type = 0; /* missuse as index */
+                       /* EX(opline)->result.u.EA.type = 0; */
 
                        (*obj)->refcount++;
                        PZVAL_LOCK(*obj);
@@ -71,38 +83,43 @@ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_FETCH)
 {
        zval **obj = spl_get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts) TSRMLS_CC);
        zval more, tmp, *value, *key, *result;
+       spl_foreach_proxy *proxy;
 
        if (spl_implements(obj, spl_ce_forward TSRMLS_CC)) {
-               zend_uint index = EX(opline)->op2.u.EA.type++;
+               proxy = (spl_foreach_proxy*)EX(opline)->op1.u.EA.type;
+               
+               if (!proxy) {
+                       (spl_foreach_proxy*)EX(opline)->op1.u.EA.type = proxy = ezalloc(sizeof(spl_foreach_proxy));
+               }
                
                spl_unlock_zval_ptr_ptr(&EX(opline)->op1, EX(Ts) TSRMLS_CC);
                PZVAL_LOCK(*obj);
 
-               if (index) {
-                       spl_begin_method_call_this(obj, "next", &more TSRMLS_CC);
+               if (proxy->index++) {
+                       spl_begin_method_call_this(obj, &proxy->f_next, "next", sizeof("next")-1, &tmp TSRMLS_CC);
                } else if (spl_implements(obj, spl_ce_sequence TSRMLS_CC)) {
-                       spl_begin_method_call_this(obj, "rewind", &more TSRMLS_CC);
+                       spl_begin_method_call_this(obj, &proxy->f_rewind, "rewind", sizeof("rewind")-1, &tmp TSRMLS_CC);
                }
 
-               spl_begin_method_call_this(obj, "has_more", &more TSRMLS_CC);
+               spl_begin_method_call_this(obj, &proxy->f_more, "has_more", sizeof("has_more")-1, &more TSRMLS_CC);
                if (zend_is_true(&more)) {
                        result = &EX_T(EX(opline)->result.u.var).tmp_var;
                        array_init(result);
                        ALLOC_ZVAL(value);
 
-                       spl_begin_method_call_this(obj, "current", value TSRMLS_CC);
+                       spl_begin_method_call_this(obj, &proxy->f_current, "current", sizeof("current")-1, value TSRMLS_CC);
 
                        zend_hash_index_update(result->value.ht, 0, &value, sizeof(zval *), NULL);
                
                        if (spl_implements(obj, spl_ce_assoc TSRMLS_CC)) {
                                ALLOC_ZVAL(key);
-                               spl_begin_method_call_this(obj, "key", key TSRMLS_CC);
+                               spl_begin_method_call_this(obj, &proxy->f_key, "key", sizeof("key")-1, key TSRMLS_CC);
                        } else {
                                /* If someone makes a reference to this value then there is
                                 * a real problem. And the only way to avoid it is to alloc
                                 * dealloc this temporary zval then.
                                 */
-                               tmp.value.lval = index;
+                               tmp.value.lval = proxy->index;
                                tmp.type = IS_LONG;
                                tmp.refcount = 0;
                                tmp.is_ref = 0;
@@ -111,6 +128,9 @@ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_FETCH)
                        zend_hash_index_update(result->value.ht, 1, &key, sizeof(zval *), NULL);
 
                        NEXT_OPCODE();
+               } else {
+                       efree(proxy);
+                       EX(opline)->op1.u.EA.type = 0;
                }
                EX(opline) = op_array->opcodes+EX(opline)->op2.u.opline_num;
                return 0;
index 1977db1ae904283ade1996374d98d51b049902f2..e6b2573b9dc16d79ed1ca7817f823d519a619f03 100755 (executable)
@@ -50,12 +50,10 @@ void spl_register_interface(zend_class_entry ** ppce, zend_namespace * namespace
        zend_class_entry ce;
        
        INIT_CLASS_ENTRY(ce, class_name, NULL);
-       ce.num_interfaces = 0;
        *ppce = zend_register_internal_ns_class(&ce, NULL, namespace_entry, NULL TSRMLS_CC);
 
        /* entries changed by initialize */
        (*ppce)->ce_flags = ZEND_ACC_ABSTRACT | ZEND_ACC_INTERFACE;
-       (*ppce)->ns = namespace_entry;
 }
 /* }}} */
 
@@ -66,15 +64,11 @@ void spl_register_std_class(zend_class_entry ** ppce, zend_namespace * namespace
        memset(&ce, 0, sizeof(zend_class_entry));
        
        INIT_CLASS_ENTRY(ce, class_name, NULL);
-
-       ce.num_interfaces = 0;
-
        *ppce = zend_register_internal_ns_class(&ce, NULL, namespace_entry, NULL TSRMLS_CC);
 
        /* entries changed by initialize */
        (*ppce)->ce_flags = ZEND_ACC_ABSTRACT | ZEND_ACC_INTERFACE;
        (*ppce)->create_object = obj_ctor;
-       (*ppce)->ns = namespace_entry;
 }
 /* }}} */
 
index 6803e44c273f0b614388296fda91129f800a4aab..fdef242028087a5d670952ced4986fee6515b031 100755 (executable)
@@ -21,8 +21,9 @@ class c_iter implements spl::forward_assoc {
                $this->num++;
        }
        function has_more() {
-               echo __CLASS__ . '::' . __FUNCTION__ . "\n";
-               return $this->num < $this->obj->max;
+               $more = $this->num < $this->obj->max;
+               echo __CLASS__ . '::' . __FUNCTION__ . ' = ' .($more ? 'true' : 'false') . "\n";
+               return $more;
        }
        function key() {
                echo __CLASS__ . '::' . __FUNCTION__ . "\n";
@@ -74,111 +75,119 @@ print "Done\n";
 ?>
 --EXPECT--
 c::new_iterator
-c_iter::has_more
+c_iter::has_more = true
 c_iter::current
 0
 c_iter::next
-c_iter::has_more
+c_iter::has_more = true
 c_iter::current
 1
 c_iter::next
-c_iter::has_more
+c_iter::has_more = true
 c_iter::current
 2
 c_iter::next
-c_iter::has_more
+c_iter::has_more = false
 array:0
 array:1
 array:2
 c::new_iterator
-c_iter::has_more
+c_iter::has_more = true
 c_iter::current
 c_iter::key
 object:0
 c_iter::next
-c_iter::has_more
+c_iter::has_more = true
 c_iter::current
 c_iter::key
 object:1
 c_iter::next
-c_iter::has_more
+c_iter::has_more = true
 c_iter::current
 c_iter::key
 object:2
 c_iter::next
-c_iter::has_more
+c_iter::has_more = false
 c::new_iterator
-c_iter::has_more
+c_iter::has_more = true
 c_iter::current
 c_iter::key
 c::new_iterator
-c_iter::has_more
+c_iter::has_more = true
 c_iter::current
 c_iter::key
 double:0:0
 c_iter::next
-c_iter::has_more
+c_iter::has_more = true
 c_iter::current
 c_iter::key
 double:0:1
 c_iter::next
-c_iter::has_more
+c_iter::has_more = true
 c_iter::current
 c_iter::key
 double:0:2
 c_iter::next
-c_iter::has_more
+c_iter::has_more = false
 c_iter::next
-c_iter::has_more
+c_iter::has_more = true
 c_iter::current
 c_iter::key
 c::new_iterator
+c_iter::has_more = true
+c_iter::current
+c_iter::key
+double:1:0
 c_iter::next
-c_iter::has_more
+c_iter::has_more = true
 c_iter::current
 c_iter::key
 double:1:1
 c_iter::next
-c_iter::has_more
+c_iter::has_more = true
 c_iter::current
 c_iter::key
 double:1:2
 c_iter::next
-c_iter::has_more
+c_iter::has_more = false
 c_iter::next
-c_iter::has_more
+c_iter::has_more = true
 c_iter::current
 c_iter::key
 c::new_iterator
+c_iter::has_more = true
+c_iter::current
+c_iter::key
+double:2:0
 c_iter::next
-c_iter::has_more
+c_iter::has_more = true
 c_iter::current
 c_iter::key
 double:2:1
 c_iter::next
-c_iter::has_more
+c_iter::has_more = true
 c_iter::current
 c_iter::key
 double:2:2
 c_iter::next
-c_iter::has_more
+c_iter::has_more = false
 c_iter::next
-c_iter::has_more
+c_iter::has_more = false
 c::new_iterator
-c_iter::has_more
+c_iter::has_more = true
 c_iter::current
 c_iter::key
 object:1st=>0
 c_iter::next
-c_iter::has_more
+c_iter::has_more = true
 c_iter::current
 c_iter::key
 object:2nd=>1
 c_iter::next
-c_iter::has_more
+c_iter::has_more = true
 c_iter::current
 c_iter::key
 object:3rd=>2
 c_iter::next
-c_iter::has_more
+c_iter::has_more = false
 Done
\ No newline at end of file