diff options
Diffstat (limited to 'Zend/zend_execute.c')
-rw-r--r-- | Zend/zend_execute.c | 120 |
1 files changed, 59 insertions, 61 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 61a605971e..4fcd1de6b8 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -99,13 +99,13 @@ static const zend_internal_function zend_pass_function = { } while (0) #define FREE_OP(should_free) \ - if (should_free.var) { \ - zval_ptr_dtor_nogc(should_free.var); \ + if (should_free) { \ + zval_ptr_dtor_nogc(should_free); \ } #define FREE_OP_VAR_PTR(should_free) \ - if (should_free.var) { \ - zval_ptr_dtor_nogc(should_free.var); \ + if (should_free) { \ + zval_ptr_dtor_nogc(should_free); \ } /* End of zend_execute_locks.h */ @@ -183,29 +183,29 @@ ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute return EX_VAR(var); } -static zend_always_inline zval *_get_zval_ptr_tmp(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC) +static zend_always_inline zval *_get_zval_ptr_tmp(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free) { zval *ret = EX_VAR(var); - should_free->var = ret; + *should_free = ret; ZEND_ASSERT(Z_TYPE_P(ret) != IS_REFERENCE); return ret; } -static zend_always_inline zval *_get_zval_ptr_var(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC) +static zend_always_inline zval *_get_zval_ptr_var(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free) { zval *ret = EX_VAR(var); - should_free->var = ret; + *should_free = ret; return ret; } -static zend_always_inline zval *_get_zval_ptr_var_deref(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC) +static zend_always_inline zval *_get_zval_ptr_var_deref(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free) { zval *ret = EX_VAR(var); - should_free->var = ret; + *should_free = ret; ZVAL_DEREF(ret); return ret; } @@ -392,93 +392,71 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_W(const zend_execu static inline zval *_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) { - zval *ret; - switch (op_type) { case IS_CONST: - should_free->var = NULL; + *should_free = NULL; return node->zv; - break; case IS_TMP_VAR: - ret = EX_VAR(node->var); - should_free->var = ret; - return ret; - break; + return _get_zval_ptr_tmp(node->var, execute_data, should_free); case IS_VAR: - return _get_zval_ptr_var(node->var, execute_data, should_free TSRMLS_CC); - break; - case IS_UNUSED: - should_free->var = NULL; - return NULL; - break; + return _get_zval_ptr_var(node->var, execute_data, should_free); case IS_CV: - default: - should_free->var = NULL; + *should_free = NULL; return _get_zval_ptr_cv(execute_data, node->var, type TSRMLS_CC); - break; + default: + *should_free = NULL; + return NULL; } - return NULL; } static inline zval *_get_zval_ptr_deref(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) { - zval *ret; - switch (op_type) { case IS_CONST: - should_free->var = NULL; + *should_free = NULL; return node->zv; - break; case IS_TMP_VAR: - ret = EX_VAR(node->var); - should_free->var = ret; - return ret; - break; + return _get_zval_ptr_tmp(node->var, execute_data, should_free); case IS_VAR: - return _get_zval_ptr_var_deref(node->var, execute_data, should_free TSRMLS_CC); - break; - case IS_UNUSED: - should_free->var = NULL; - return NULL; - break; + return _get_zval_ptr_var_deref(node->var, execute_data, should_free); case IS_CV: - default: - should_free->var = NULL; + *should_free = NULL; return _get_zval_ptr_cv_deref(execute_data, node->var, type TSRMLS_CC); - break; + default: + *should_free = NULL; + return NULL; } - return NULL; } -static zend_always_inline zval *_get_zval_ptr_ptr_var(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC) +static zend_always_inline zval *_get_zval_ptr_ptr_var(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free) { zval *ret = EX_VAR(var); if (EXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) { - should_free->var = NULL; - return Z_INDIRECT_P(ret); - } else if (!Z_REFCOUNTED_P(ret) || Z_REFCOUNT_P(ret) == 1) { - should_free->var = ret; - return ret; + *should_free = NULL; + ret = Z_INDIRECT_P(ret); } else { - Z_DELREF_P(ret); - should_free->var = NULL; - return ret; + *should_free = ret; + if (Z_REFCOUNTED_P(ret) && Z_REFCOUNT_P(ret) > 1) { + *should_free = NULL; + Z_DELREF_P(ret); + } } + return ret; } static inline zval *_get_zval_ptr_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) { if (op_type == IS_CV) { - should_free->var = NULL; + *should_free = NULL; return _get_zval_ptr_cv(execute_data, node->var, type TSRMLS_CC); } else /* if (op_type == IS_VAR) */ { ZEND_ASSERT(op_type == IS_VAR); - return _get_zval_ptr_ptr_var(node->var, execute_data, should_free TSRMLS_CC); + return _get_zval_ptr_ptr_var(node->var, execute_data, should_free); } } -static zend_always_inline zval *_get_obj_zval_ptr_unused(zend_execute_data *execute_data TSRMLS_DC) +static zend_always_inline zval *_get_obj_zval_ptr_unused(zend_execute_data *execute_data) { if (EXPECTED(Z_OBJ(EX(This)) != NULL)) { return &EX(This); @@ -492,7 +470,7 @@ static inline zval *_get_obj_zval_ptr(int op_type, znode_op *op, zend_execute_da { if (op_type == IS_UNUSED) { if (EXPECTED(Z_OBJ(EX(This)) != NULL)) { - should_free->var = NULL; + *should_free = NULL; return &EX(This); } else { zend_error_noreturn(E_ERROR, "Using $this when not in object context"); @@ -505,7 +483,7 @@ static inline zval *_get_obj_zval_ptr_ptr(int op_type, const znode_op *node, zen { if (op_type == IS_UNUSED) { if (EXPECTED(Z_OBJ(EX(This)) != NULL)) { - should_free->var = NULL; + *should_free = NULL; return &EX(This); } else { zend_error_noreturn(E_ERROR, "Using $this when not in object context"); @@ -1292,7 +1270,7 @@ ZEND_API void zend_fetch_dimension_by_zval(zval *result, zval *container, zval * zend_fetch_dimension_address_read_R(result, container, dim, IS_TMP_VAR TSRMLS_CC); } -static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, void **cache_slot, int type TSRMLS_DC) +static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, uint32_t prop_op_type, void **cache_slot, int type TSRMLS_DC) { if (container_op_type != IS_UNUSED) { ZVAL_DEREF(container); @@ -1316,6 +1294,26 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c } } } + if (prop_op_type == IS_CONST && + EXPECTED(Z_OBJCE_P(container) == CACHED_PTR_EX(cache_slot))) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 1); + zend_object *zobj = Z_OBJ_P(container); + zval *retval; + + if (EXPECTED(prop_info)) { + retval = OBJ_PROP(zobj, prop_info->offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + ZVAL_INDIRECT(result, retval); + return; + } + } else if (EXPECTED(zobj->properties != NULL)) { + retval = zend_hash_find(zobj->properties, Z_STR_P(prop_ptr)); + if (EXPECTED(retval)) { + ZVAL_INDIRECT(result, retval); + return; + } + } + } if (EXPECTED(Z_OBJ_HT_P(container)->get_property_ptr_ptr)) { zval *ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr, type, cache_slot TSRMLS_CC); if (NULL == ptr) { |