diff options
author | Marcus Boerger <helly@php.net> | 2003-05-24 21:02:33 +0000 |
---|---|---|
committer | Marcus Boerger <helly@php.net> | 2003-05-24 21:02:33 +0000 |
commit | 96034f390ba8136c8fb8ecbaec9d1adce2ecb2eb (patch) | |
tree | 073cd049ad7d007e263a661ccefe30607f5dcb3c | |
parent | 0b0e0e9511aa170b58e1d7421a40a404060e48b3 (diff) | |
download | php-git-96034f390ba8136c8fb8ecbaec9d1adce2ecb2eb.tar.gz |
Optimizing by caching class entries, too.
# The comment block inside ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_FETCH)
# is a tricky way to create result = array(key => value) very fast.
# But it is close to overoptimizing.
-rwxr-xr-x | ext/spl/spl_array.c | 10 | ||||
-rwxr-xr-x | ext/spl/spl_engine.c | 20 | ||||
-rwxr-xr-x | ext/spl/spl_engine.h | 33 | ||||
-rwxr-xr-x | ext/spl/spl_foreach.c | 115 |
4 files changed, 107 insertions, 71 deletions
diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 186cdb78a7..f78ad00c39 100755 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -122,7 +122,7 @@ void spl_array_writer_default_set(zval *object, zval *newval, zval **retval TSRM spl_array_writer_object *writer; writer = (spl_array_writer_object *) zend_object_store_get_object(object TSRMLS_CC); - spl_begin_method_call_arg_ex2(&writer->obj, NULL, "set", sizeof("set")-1, retval, writer->idx, newval TSRMLS_CC); + spl_begin_method_call_arg_ex2(&writer->obj, NULL, NULL, "set", sizeof("set")-1, retval, writer->idx, newval TSRMLS_CC); } /* }}} */ @@ -169,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, NULL, "exists", sizeof("exists")-1, &exists, dim TSRMLS_CC); + spl_begin_method_call_arg_ex1(container_ptr, NULL, 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); @@ -188,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, NULL, "get", sizeof("get")-1, retval, dim TSRMLS_CC); + spl_begin_method_call_arg_ex1(container_ptr, NULL, 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, NULL, "new_writer", sizeof("new_writer")-1, retval, dim TSRMLS_CC); + spl_begin_method_call_arg_ex1(container_ptr, NULL, 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); @@ -291,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, NULL, "set", sizeof("set")-1, &retval, newval TSRMLS_CC); + spl_begin_method_call_arg_ex1(writer, NULL, NULL, "set", sizeof("set")-1, &retval, newval TSRMLS_CC); } else { ZEND_EXECUTE_HOOK_ORIGINAL(ZEND_ASSIGN); } diff --git a/ext/spl/spl_engine.c b/ext/spl/spl_engine.c index aa72cfd9cd..02be8d000d 100755 --- a/ext/spl/spl_engine.c +++ b/ext/spl/spl_engine.c @@ -49,7 +49,7 @@ int spl_instanciate_arg_ex2(zend_class_entry *pce, zval **retval, zval *arg1, zv retval = &EG(uninitialized_zval_ptr); - spl_call_method(&object, NULL, pce->constructor->common.function_name, strlen(pce->constructor->common.function_name), retval, NULL TSRMLS_CC, 2, arg1, arg2); + spl_call_method(&object, pce, &pce->constructor, pce->constructor->common.function_name, strlen(pce->constructor->common.function_name), retval, NULL TSRMLS_CC, 2, arg1, arg2); *retval = object; return 0; } @@ -136,17 +136,6 @@ zval * spl_get_zval_ptr(znode *node, temp_variable *Ts, zval **should_free TSRML } /* }}} */ -/* {{{ */ -inline zend_class_entry *spl_get_class_entry(zval *obj TSRMLS_DC) -{ - if (obj && Z_TYPE_P(obj) == IS_OBJECT && Z_OBJ_HT_P(obj)->get_class_entry) { - return Z_OBJ_HT_P(obj)->get_class_entry(obj TSRMLS_CC); - } else { - return NULL; - } -} -/* }}} */ - /* {{{ spl_is_instance_of */ int spl_is_instance_of(zval **obj, zend_class_entry *ce TSRMLS_DC) { @@ -190,7 +179,7 @@ int spl_implements(zval **obj, zend_class_entry *ce TSRMLS_DC) #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 spl_call_method(zval **object_pp, zend_class_entry *obj_ce, 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; @@ -206,10 +195,9 @@ int spl_call_method(zval **object_pp, zend_function **fn_proxy, char *function_n 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) { + if (!object_pp || (!obj_ce && (obj_ce = spl_get_class_entry(*object_pp TSRMLS_CC)) == NULL)) { return FAILURE; } @@ -220,7 +208,7 @@ int spl_call_method(zval **object_pp, zend_function **fn_proxy, char *function_n EX(opline) = NULL; EX(object) = *object_pp; - calling_scope = Z_OBJCE_PP(object_pp); + calling_scope = obj_ce; original_function_state_ptr = EG(function_state_ptr); if (fn_proxy && *fn_proxy) { diff --git a/ext/spl/spl_engine.h b/ext/spl/spl_engine.h index 040862f8bf..90d2320734 100755 --- a/ext/spl/spl_engine.h +++ b/ext/spl/spl_engine.h @@ -36,13 +36,24 @@ int zend_do_fcall_common_helper(ZEND_OPCODE_HANDLER_ARGS); -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, ...); +int spl_call_method(zval **object_pp, zend_class_entry *obj_ce, zend_function **fn_proxy, char *function_name, int function_name_len, zval **retval_ptr, HashTable *symbol_table TSRMLS_DC, int param_count, ...); + +/* {{{ zend_class_entry */ +static inline zend_class_entry *spl_get_class_entry(zval *obj TSRMLS_DC) +{ + if (obj && Z_TYPE_P(obj) == IS_OBJECT && Z_OBJ_HT_P(obj)->get_class_entry) { + return Z_OBJ_HT_P(obj)->get_class_entry(obj TSRMLS_CC); + } else { + return NULL; + } +} +/* }}} */ /* {{{ 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) +static inline int spl_begin_method_call_arg(zval **ce, zend_class_entry *obj_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); + int ret = spl_call_method(ce, obj_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 { @@ -53,10 +64,10 @@ static inline int spl_begin_method_call_arg(zval **ce, zend_function **fn_proxy, /* }}} */ /* {{{ 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) +static inline int spl_begin_method_call_this(zval **ce, zend_class_entry *obj_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); + int ret = spl_call_method(ce, obj_ce, fn_proxy, function_name, fname_len, &local_retval, NULL TSRMLS_CC, 0); if (local_retval) { COPY_PZVAL_TO_ZVAL(*retval, local_retval); } else { @@ -67,23 +78,23 @@ static inline int spl_begin_method_call_this(zval **ce, zend_function **fn_proxy /* }}} */ /* {{{ 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) +static inline int spl_begin_method_call_ex(zval **ce, zend_class_entry *obj_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); + return spl_call_method(ce, obj_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) +static inline int spl_begin_method_call_arg_ex1(zval **ce, zend_class_entry *obj_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); + return spl_call_method(ce, obj_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) +static inline int spl_begin_method_call_arg_ex2(zval **ce, zend_class_entry *obj_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); + return spl_call_method(ce, obj_ce, fn_proxy, function_name, fname_len, retval, NULL TSRMLS_CC, 2, arg1, arg2); } /* }}} */ diff --git a/ext/spl/spl_foreach.c b/ext/spl/spl_foreach.c index ee77b03175..9e3ae387ab 100755 --- a/ext/spl/spl_foreach.c +++ b/ext/spl/spl_foreach.c @@ -35,12 +35,14 @@ 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; + zend_uint index; + zend_class_entry *obj_ce; + zend_uint is_ce_assoc; + 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) */ @@ -52,8 +54,7 @@ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_RESET) obj = spl_get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts) TSRMLS_CC); 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, NULL, "new_iterator", sizeof("new_iterator")-1, retval TSRMLS_CC); + spl_begin_method_call_ex(obj, NULL, 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)->result.u.EA.type = 0; */ @@ -78,60 +79,96 @@ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_RESET) } /* }}} */ +#define CONNECT_TO_BUCKET_DLLIST(element, list_head) \ + (element)->pNext = (list_head); \ + (element)->pLast = NULL; \ + if ((element)->pNext) { \ + (element)->pNext->pLast = (element); \ + } + +#define CONNECT_TO_GLOBAL_DLLIST(element, ht) \ + (element)->pListLast = (ht)->pListTail; \ + (ht)->pListTail = (element); \ + (element)->pListNext = NULL; \ + if ((element)->pListLast != NULL) { \ + (element)->pListLast->pListNext = (element); \ + } \ + if (!(ht)->pListHead) { \ + (ht)->pListHead = (element); \ + } \ + if ((ht)->pInternalPointer == NULL) { \ + (ht)->pInternalPointer = (element); \ + } + /* {{{ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_FETCH) */ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FE_FETCH) { - zval **obj = spl_get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts) TSRMLS_CC); + znode *op1 = &EX(opline)->op1; + zval **obj = spl_get_zval_ptr_ptr(op1, EX(Ts) TSRMLS_CC); zval more, tmp, *value, *key, *result; - spl_foreach_proxy *proxy; + spl_foreach_proxy *proxy = (spl_foreach_proxy*)op1->u.EA.type; - if (spl_implements(obj, spl_ce_forward TSRMLS_CC)) { - proxy = (spl_foreach_proxy*)EX(opline)->op1.u.EA.type; - + if (proxy || spl_implements(obj, spl_ce_forward TSRMLS_CC)) { if (!proxy) { - (spl_foreach_proxy*)EX(opline)->op1.u.EA.type = proxy = ezalloc(sizeof(spl_foreach_proxy)); + (spl_foreach_proxy*)op1->u.EA.type = proxy = ezalloc(sizeof(spl_foreach_proxy)); + proxy->obj_ce = spl_get_class_entry(*obj TSRMLS_CC); } - spl_unlock_zval_ptr_ptr(&EX(opline)->op1, EX(Ts) TSRMLS_CC); + spl_unlock_zval_ptr_ptr(op1, EX(Ts) TSRMLS_CC); PZVAL_LOCK(*obj); 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, &proxy->f_rewind, "rewind", sizeof("rewind")-1, &tmp TSRMLS_CC); + spl_begin_method_call_this(obj, proxy->obj_ce, &proxy->f_next, "next", sizeof("next")-1, &tmp TSRMLS_CC); + } else { + proxy->is_ce_assoc = spl_implements(obj, spl_ce_assoc TSRMLS_CC); + if (spl_implements(obj, spl_ce_sequence TSRMLS_CC)) { + spl_begin_method_call_this(obj, proxy->obj_ce, &proxy->f_rewind, "rewind", sizeof("rewind")-1, &tmp TSRMLS_CC); + } } - spl_begin_method_call_this(obj, &proxy->f_more, "has_more", sizeof("has_more")-1, &more TSRMLS_CC); + spl_begin_method_call_this(obj, proxy->obj_ce, &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, &proxy->f_current, "current", sizeof("current")-1, value TSRMLS_CC); + spl_begin_method_call_ex(obj, proxy->obj_ce, &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, &proxy->f_key, "key", sizeof("key")-1, key TSRMLS_CC); + if (proxy->is_ce_assoc) { + spl_begin_method_call_ex(obj, proxy->obj_ce, &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 = proxy->index; - tmp.type = IS_LONG; - tmp.refcount = 0; - tmp.is_ref = 0; - key = &tmp; + MAKE_STD_ZVAL(key); + key->value.lval = proxy->index; + key->type = IS_LONG; } + zend_hash_index_update(result->value.ht, 0, &value, sizeof(zval *), NULL); zend_hash_index_update(result->value.ht, 1, &key, sizeof(zval *), NULL); - +/* + { + Bucket *p; + + p = (Bucket*)emalloc(sizeof(Bucket)-1); + p->pDataPtr = value; + p->pData = &p->pDataPtr; + p->nKeyLength = 0; + p->h = 0; + CONNECT_TO_BUCKET_DLLIST(p, result->value.ht->arBuckets[0]); + result->value.ht->arBuckets[0] = p; + CONNECT_TO_GLOBAL_DLLIST(p, result->value.ht); + p = (Bucket*)emalloc(sizeof(Bucket)-1); + p->pDataPtr = key; + p->pData = &p->pDataPtr; + p->nKeyLength = 0; + p->h = 1; + CONNECT_TO_BUCKET_DLLIST(p, result->value.ht->arBuckets[1]); + result->value.ht->arBuckets[1] = p; + CONNECT_TO_GLOBAL_DLLIST(p, result->value.ht); + result->value.ht->nNumOfElements = 2; + } +*/ NEXT_OPCODE(); - } else { - efree(proxy); - EX(opline)->op1.u.EA.type = 0; } + efree(proxy); + op1->u.EA.type = 0; EX(opline) = op_array->opcodes+EX(opline)->op2.u.opline_num; return 0; } |