summaryrefslogtreecommitdiff
path: root/Zend/zend_execute.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_execute.c')
-rw-r--r--Zend/zend_execute.c120
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) {