mirror of
https://github.com/php/php-src.git
synced 2026-03-27 17:52:16 +01:00
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.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user