summaryrefslogtreecommitdiff
path: root/Zend/zend_execute.c
diff options
context:
space:
mode:
authorFlorian MARGAINE <florian@margaine.com>2014-09-20 10:09:21 +0200
committerFlorian MARGAINE <florian@margaine.com>2014-09-20 10:09:21 +0200
commit8eb7e7bf7f63f49e97f112871df47c6d6213e715 (patch)
tree24b9059118cf6abb5fe0837eaa477b4668b18435 /Zend/zend_execute.c
parent58ed832fc99d5c5aeac7849819bbc4e0dc90d698 (diff)
parent95836a350420cabc2e8e5f5c45131fba46504a3b (diff)
downloadphp-git-8eb7e7bf7f63f49e97f112871df47c6d6213e715.tar.gz
Merge branch 'master' into issue-67910
Conflicts: README.PARAMETER_PARSING_API ext/gmp/tests/001.phpt
Diffstat (limited to 'Zend/zend_execute.c')
-rw-r--r--Zend/zend_execute.c402
1 files changed, 168 insertions, 234 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 9237e97415..700b986d61 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -38,6 +38,7 @@
#include "zend_generators.h"
#include "zend_vm.h"
#include "zend_dtrace.h"
+#include "zend_inheritance.h"
/* Virtual current working directory support */
#include "zend_virtual_cwd.h"
@@ -83,7 +84,6 @@ static const zend_internal_function zend_pass_function = {
#undef zval_ptr_dtor
#define zval_ptr_dtor(zv) i_zval_ptr_dtor(zv ZEND_FILE_LINE_CC TSRMLS_CC)
-#define zval_ptr_dtor_nogc(zv) i_zval_ptr_dtor_nogc(zv ZEND_FILE_LINE_CC TSRMLS_CC)
#define PZVAL_LOCK(z) if (Z_REFCOUNTED_P(z)) Z_ADDREF_P((z))
#define SELECTIVE_PZVAL_LOCK(pzv, opline) if (RETURN_VALUE_USED(opline)) { PZVAL_LOCK(pzv); }
@@ -211,11 +211,6 @@ static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, uint
return &EG(uninitialized_zval);
}
-static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_IS(zval *ptr, uint32_t var, const zend_execute_data *execute_data TSRMLS_DC)
-{
- return &EG(uninitialized_zval);
-}
-
static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_RW(zval *ptr, uint32_t var, const zend_execute_data *execute_data TSRMLS_DC)
{
zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
@@ -298,9 +293,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(const zend_execute_da
{
zval *ret = EX_VAR(var);
- if (Z_TYPE_P(ret) == IS_UNDEF) {
- return _get_zval_cv_lookup_BP_VAR_IS(ret, var, execute_data TSRMLS_CC);
- }
return ret;
}
@@ -308,9 +300,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_IS(const zend_exec
{
zval *ret = EX_VAR(var);
- if (Z_TYPE_P(ret) == IS_UNDEF) {
- return _get_zval_cv_lookup_BP_VAR_IS(ret, var, execute_data TSRMLS_CC);
- }
ZVAL_DEREF(ret);
return ret;
}
@@ -637,6 +626,7 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_n
need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "none", "", NULL TSRMLS_CC);
+ return 0;
} else if (cur_arg_info->type_hint) {
if (cur_arg_info->type_hint == IS_ARRAY) {
zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", "none", "", NULL TSRMLS_CC);
@@ -647,8 +637,9 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_n
zend_error(E_ERROR, "Unknown typehint");
#endif
}
+ return 0;
}
- return 0;
+ return 1;
}
static void zend_verify_missing_arg(zend_execute_data *execute_data, uint32_t arg_num TSRMLS_DC)
@@ -756,17 +747,12 @@ static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *p
FREE_OP_IF_VAR(free_value);
}
-static void zend_assign_to_string_offset(zval *str_offset, zval *value, int value_type, zval *result TSRMLS_DC)
+static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *value, int value_type, zval *result TSRMLS_DC)
{
- zval *str = Z_STR_OFFSET_STR_P(str_offset);
- /* XXX String offset is uint32_t in _zval_struct, so can address only 2^32+1 space.
- To make the offset get over that barier, we need to make str_offset size_t and that
- would grow zval size by 8 bytes (currently from 16 to 24) on 64 bit build. */
- uint32_t offset = Z_STR_OFFSET_IDX_P(str_offset);
zend_string *old_str;
- if ((int)offset < 0) {
- zend_error(E_WARNING, "Illegal string offset: %d", offset);
+ if (offset < 0) {
+ zend_error(E_WARNING, "Illegal string offset: " ZEND_LONG_FMT, offset);
zend_string_release(Z_STR_P(str));
if (result) {
ZVAL_NULL(result);
@@ -775,13 +761,13 @@ static void zend_assign_to_string_offset(zval *str_offset, zval *value, int valu
}
old_str = Z_STR_P(str);
- if (offset >= Z_STRLEN_P(str)) {
- int old_len = Z_STRLEN_P(str);
+ if ((size_t)offset >= Z_STRLEN_P(str)) {
+ zend_long old_len = Z_STRLEN_P(str);
Z_STR_P(str) = zend_string_realloc(Z_STR_P(str), offset + 1, 0);
Z_TYPE_INFO_P(str) = IS_STRING_EX;
memset(Z_STRVAL_P(str) + old_len, ' ', offset - old_len);
Z_STRVAL_P(str)[offset+1] = 0;
- } else if (IS_INTERNED(Z_STR_P(str))) {
+ } else if (!Z_REFCOUNTED_P(str)) {
Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
Z_TYPE_INFO_P(str) = IS_STRING_EX;
}
@@ -817,144 +803,61 @@ static void zend_assign_to_string_offset(zval *str_offset, zval *value, int valu
}
}
-static inline zval* zend_assign_tmp_to_variable(zval *variable_ptr, zval *value TSRMLS_DC)
+static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type TSRMLS_DC)
{
- ZVAL_DEREF(variable_ptr);
-
- if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
- zend_refcounted *garbage;
-
- if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
- UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
- Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr, value TSRMLS_CC);
- return variable_ptr;
- }
+ do {
+ if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
+ zend_refcounted *garbage;
- garbage = Z_COUNTED_P(variable_ptr);
- if (UNEXPECTED(GC_REFCOUNT(garbage) > 1)) {
- /* we need to split */
- GC_REFCOUNT(garbage)--;
- /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */
- if ((Z_COLLECTABLE_P(variable_ptr)) &&
- UNEXPECTED(!GC_INFO(garbage))) {
- gc_possible_root(garbage TSRMLS_CC);
+ if (Z_ISREF_P(variable_ptr)) {
+ variable_ptr = Z_REFVAL_P(variable_ptr);
+ if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) {
+ break;
+ }
}
- } else {
- ZVAL_COPY_VALUE(variable_ptr, value);
- _zval_dtor_func(garbage ZEND_FILE_LINE_CC);
- return variable_ptr;
- }
- }
-
- ZVAL_COPY_VALUE(variable_ptr, value);
-
- return variable_ptr;
-}
-
-static inline zval* zend_assign_const_to_variable(zval *variable_ptr, zval *value TSRMLS_DC)
-{
- ZVAL_DEREF(variable_ptr);
-
- if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
- zend_refcounted *garbage;
-
- if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
- UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
- Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr, value TSRMLS_CC);
- return variable_ptr;
- }
-
- garbage = Z_COUNTED_P(variable_ptr);
- if (UNEXPECTED(GC_REFCOUNT(garbage) > 1)) {
- /* we need to split */
- GC_REFCOUNT(garbage)--;
- /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */
- if (Z_COLLECTABLE_P(variable_ptr) &&
- UNEXPECTED(!GC_INFO(garbage))) {
- gc_possible_root(garbage TSRMLS_CC);
+ if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
+ UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
+ Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr, value TSRMLS_CC);
+ return variable_ptr;
}
- } else {
- ZVAL_COPY_VALUE(variable_ptr, value);
- /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
- if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) {
- zval_copy_ctor_func(variable_ptr);
+ if ((value_type & (IS_VAR|IS_CV)) && variable_ptr == value) {
+ return variable_ptr;
}
- _zval_dtor_func(garbage ZEND_FILE_LINE_CC);
- return variable_ptr;
- }
- }
-
- ZVAL_COPY_VALUE(variable_ptr, value);
- /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
- if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) {
- zval_copy_ctor_func(variable_ptr);
- }
-
- return variable_ptr;
-}
-
-static inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value TSRMLS_DC)
-{
- zend_refcounted *garbage;
-
- if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) {
- goto assign_simple;
- } else if (UNEXPECTED(variable_ptr == value)) {
- return variable_ptr;
- }
- if (Z_ISREF_P(variable_ptr)) {
- variable_ptr = Z_REFVAL_P(variable_ptr);
- if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) {
- goto assign_simple;
- } else if (UNEXPECTED(variable_ptr == value)) {
- return variable_ptr;
- }
- }
-
- if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
- UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
- Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr, value TSRMLS_CC);
- } else {
- if (Z_REFCOUNT_P(variable_ptr)==1) {
garbage = Z_COUNTED_P(variable_ptr);
- if (UNEXPECTED(Z_REFCOUNTED_P(value))) {
- if (EXPECTED(!Z_ISREF_P(value))) {
- Z_ADDREF_P(value);
- } else {
- if (Z_REFCOUNT_P(value) == 1) {
- ZVAL_UNREF(value);
- } else {
- value = Z_REFVAL_P(value);
+ if (GC_REFCOUNT(garbage) == 1) {
+ ZVAL_COPY_VALUE(variable_ptr, value);
+ if (value_type == IS_CONST) {
+ /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) {
+ zval_copy_ctor_func(variable_ptr);
}
- if (Z_REFCOUNTED_P(value)) {
- if (UNEXPECTED(variable_ptr == value)) {
- return variable_ptr;
- }
- Z_ADDREF_P(value);
+ } else if (value_type != IS_TMP_VAR) {
+ if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) {
+ Z_ADDREF_P(variable_ptr);
}
}
- }
- ZVAL_COPY_VALUE(variable_ptr, value);
- _zval_dtor_func(garbage ZEND_FILE_LINE_CC);
- } else { /* we need to split */
- Z_DELREF_P(variable_ptr);
- GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
-assign_simple:
- if (UNEXPECTED(Z_REFCOUNTED_P(value))) {
- if (EXPECTED(!Z_ISREF_P(value))) {
- Z_ADDREF_P(value);
- } else {
- if (Z_REFCOUNT_P(value) == 1) {
- ZVAL_UNREF(value);
- } else {
- value = Z_REFVAL_P(value);
- }
- if (Z_REFCOUNTED_P(value)) {
- Z_ADDREF_P(value);
- }
+ _zval_dtor_func(garbage ZEND_FILE_LINE_CC);
+ return variable_ptr;
+ } else { /* we need to split */
+ GC_REFCOUNT(garbage)--;
+ /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */
+ if ((Z_COLLECTABLE_P(variable_ptr)) &&
+ UNEXPECTED(!GC_INFO(garbage))) {
+ gc_possible_root(garbage TSRMLS_CC);
}
}
- ZVAL_COPY_VALUE(variable_ptr, value);
+ }
+ } while (0);
+
+ ZVAL_COPY_VALUE(variable_ptr, value);
+ if (value_type == IS_CONST) {
+ /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) {
+ zval_copy_ctor_func(variable_ptr);
+ }
+ } else if (value_type != IS_TMP_VAR) {
+ if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) {
+ Z_ADDREF_P(variable_ptr);
}
}
return variable_ptr;
@@ -1107,7 +1010,7 @@ str_index:
return retval;
}
-static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *container_ptr, zval *dim, int dim_type, int type, int is_ref TSRMLS_DC)
+static zend_always_inline zval *zend_fetch_dimension_address(zval *result, zval *container_ptr, zval *dim, int dim_type, int type, int is_ref, int allow_str_offset TSRMLS_DC)
{
zval *retval;
zval *container = container_ptr;
@@ -1142,14 +1045,11 @@ convert_to_array:
zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
goto fetch_from_array;
}
+
if (dim == NULL) {
zend_error_noreturn(E_ERROR, "[] operator not supported for strings");
}
- if (type != BP_VAR_UNSET) {
- SEPARATE_STRING(container);
- }
-
if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
switch(Z_TYPE_P(dim)) {
case IS_STRING:
@@ -1176,8 +1076,19 @@ convert_to_array:
offset = Z_LVAL_P(dim);
}
- if (!IS_INTERNED(Z_STR_P(container))) zend_string_addref(Z_STR_P(container));
- ZVAL_STR_OFFSET(result, container, offset);
+ if (allow_str_offset) {
+ if (Z_REFCOUNTED_P(container)) {
+ if (Z_REFCOUNT_P(container) > 1) {
+ Z_DELREF_P(container);
+ zval_copy_ctor_func(container);
+ }
+ Z_ADDREF_P(container);
+ }
+ ZVAL_LONG(result, offset);
+ return container; /* assignment to string offset */
+ } else {
+ ZVAL_INDIRECT(result, NULL); /* wrong string offset */
+ }
} else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (!Z_OBJ_HT_P(container)->read_dimension) {
zend_error_noreturn(E_ERROR, "Cannot use object as array");
@@ -1242,26 +1153,32 @@ convert_to_array:
ZVAL_INDIRECT(result, &EG(error_zval));
}
}
+ return NULL; /* not an assignment to string offset */
}
static zend_never_inline void zend_fetch_dimension_address_W(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
{
- zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 0 TSRMLS_CC);
+ zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 0, 0 TSRMLS_CC);
+}
+
+static zend_never_inline zval *zend_fetch_dimension_address_W_str(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
+{
+ return zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 0, 1 TSRMLS_CC);
}
static zend_never_inline void zend_fetch_dimension_address_W_ref(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
{
- zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 1 TSRMLS_CC);
+ zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 1, 0 TSRMLS_CC);
}
static zend_never_inline void zend_fetch_dimension_address_RW(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
{
- zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW, 0 TSRMLS_CC);
+ zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW, 0, 0 TSRMLS_CC);
}
static zend_never_inline void zend_fetch_dimension_address_UNSET(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
{
- zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET, 0 TSRMLS_CC);
+ zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET, 0, 0 TSRMLS_CC);
}
static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type TSRMLS_DC)
@@ -1304,9 +1221,9 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z
offset = Z_LVAL_P(dim);
}
- if (UNEXPECTED(offset < 0) || UNEXPECTED(Z_STRLEN_P(container) <= offset)) {
+ if (UNEXPECTED(offset < 0) || UNEXPECTED(Z_STRLEN_P(container) <= (size_t)offset)) {
if (type != BP_VAR_IS) {
- zend_error(E_NOTICE, "Uninitialized string offset: %ld", offset);
+ zend_error(E_NOTICE, "Uninitialized string offset: %pd", offset);
}
ZVAL_EMPTY_STRING(result);
} else {
@@ -1546,49 +1463,59 @@ void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /*
static zend_always_inline void i_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
{
- uint32_t first_extra_arg;
+ uint32_t first_extra_arg, num_args;
ZEND_ASSERT(EX(func) == (zend_function*)op_array);
ZEND_ASSERT(EX(object) == Z_OBJ(EG(This)));
- EX(return_value) = return_value;
- EX(frame_kind) = frame_kind;
- ZVAL_UNDEF(&EX(old_error_reporting));
- EX(delayed_exception) = NULL;
- EX(call) = NULL;
-
EX(opline) = op_array->opcodes;
- if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
- /* Skip useless ZEND_RECV opcodes */
- EX(opline) += MIN(EX(num_args), op_array->required_num_args);
- }
+ EX(call) = NULL;
+ EX(frame_kind) = frame_kind;
+ EX(return_value) = return_value;
EX(scope) = EG(scope);
+ EX(delayed_exception) = NULL;
+ ZVAL_UNDEF(&EX(old_error_reporting));
+ /* Handle arguments */
first_extra_arg = op_array->num_args;
-
if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_VARIADIC) != 0)) {
first_extra_arg--;
}
- if (UNEXPECTED(EX(num_args) > first_extra_arg)) {
- /* move extra args into separate array after all CV and TMP vars */
- zval *extra_args = EX_VAR_NUM(op_array->last_var + op_array->T);
-
- memmove(extra_args, EX_VAR_NUM(first_extra_arg), sizeof(zval) * (EX(num_args) - first_extra_arg));
- }
-
- do {
- /* Initialize CV variables (skip arguments) */
- int num_args = MIN(op_array->num_args, EX(num_args));
+ num_args = EX(num_args);
+ if (UNEXPECTED(num_args > first_extra_arg)) {
+ zval *end, *src, *dst;
- if (EXPECTED(num_args < op_array->last_var)) {
- zval *var = EX_VAR_NUM(num_args);
- zval *end = EX_VAR_NUM(op_array->last_var);
+ if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
+ /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
+ EX(opline) += first_extra_arg;
+ }
+ /* move extra args into separate array after all CV and TMP vars */
+ end = EX_VAR_NUM(first_extra_arg - 1);
+ src = end + (num_args - first_extra_arg);
+ dst = src + (op_array->last_var + op_array->T - first_extra_arg);
+ if (EXPECTED(src != dst)) {
do {
- ZVAL_UNDEF(var);
- var++;
- } while (var != end);
+ ZVAL_COPY_VALUE(dst, src);
+ ZVAL_UNDEF(src);
+ src--;
+ dst--;
+ } while (src != end);
}
- } while (0);
+ } else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
+ /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
+ EX(opline) += num_args;
+ }
+
+ /* Initialize CV variables (skip arguments) */
+ if (EXPECTED(num_args < op_array->last_var)) {
+ zval *var = EX_VAR_NUM(num_args);
+ zval *end = EX_VAR_NUM(op_array->last_var);
+
+ do {
+ ZVAL_UNDEF(var);
+ var++;
+ } while (var != end);
+ }
if (op_array->this_var != -1 && EX(object)) {
ZVAL_OBJ(EX_VAR(op_array->this_var), EX(object));
@@ -1596,11 +1523,7 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu
}
if (!op_array->run_time_cache && op_array->last_cache_slot) {
- if (op_array->function_name) {
- op_array->run_time_cache = zend_arena_calloc(&CG(arena), op_array->last_cache_slot, sizeof(void*));
- } else {
- op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
- }
+ op_array->run_time_cache = zend_arena_calloc(&CG(arena), op_array->last_cache_slot, sizeof(void*));
}
EX(run_time_cache) = op_array->run_time_cache;
@@ -1613,23 +1536,18 @@ static zend_always_inline void i_init_code_execute_data(zend_execute_data *execu
ZEND_ASSERT(EX(func) == (zend_function*)op_array);
ZEND_ASSERT(EX(object) == Z_OBJ(EG(This)));
- EX(return_value) = return_value;
- EX(frame_kind) = frame_kind;
- ZVAL_UNDEF(&EX(old_error_reporting));
- EX(delayed_exception) = NULL;
- EX(call) = NULL;
-
EX(opline) = op_array->opcodes;
+ EX(call) = NULL;
+ EX(frame_kind) = frame_kind;
+ EX(return_value) = return_value;
EX(scope) = EG(scope);
+ EX(delayed_exception) = NULL;
+ ZVAL_UNDEF(&EX(old_error_reporting));
zend_attach_symbol_table(execute_data);
if (!op_array->run_time_cache && op_array->last_cache_slot) {
- if (op_array->function_name) {
- op_array->run_time_cache = zend_arena_calloc(&CG(arena), op_array->last_cache_slot, sizeof(void*));
- } else {
- op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
- }
+ op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
}
EX(run_time_cache) = op_array->run_time_cache;
@@ -1642,44 +1560,60 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da
ZEND_ASSERT(EX(func) == (zend_function*)op_array);
ZEND_ASSERT(EX(object) == Z_OBJ(EG(This)));
- EX(return_value) = return_value;
- EX(frame_kind) = frame_kind;
- ZVAL_UNDEF(&EX(old_error_reporting));
- EX(delayed_exception) = NULL;
- EX(call) = NULL;
-
EX(opline) = op_array->opcodes;
+ EX(call) = NULL;
+ EX(frame_kind) = frame_kind;
+ EX(return_value) = return_value;
EX(scope) = EG(scope);
+ EX(delayed_exception) = NULL;
+ ZVAL_UNDEF(&EX(old_error_reporting));
if (UNEXPECTED(EX(symbol_table) != NULL)) {
zend_attach_symbol_table(execute_data);
} else {
- uint32_t first_extra_arg = op_array->num_args;
+ uint32_t first_extra_arg, num_args;
+ /* Handle arguments */
+ first_extra_arg = op_array->num_args;
if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_VARIADIC) != 0)) {
first_extra_arg--;
}
- if (UNEXPECTED(EX(num_args) > first_extra_arg)) {
- /* move extra args into separate array after all CV and TMP vars */
- zval *extra_args = EX_VAR_NUM(op_array->last_var + op_array->T);
+ num_args = EX(num_args);
+ if (UNEXPECTED(num_args > first_extra_arg)) {
+ zval *end, *src, *dst;
- memmove(extra_args, EX_VAR_NUM(first_extra_arg), sizeof(zval) * (EX(num_args) - first_extra_arg));
- }
-
- do {
- /* Initialize CV variables (skip arguments) */
- int num_args = MIN(op_array->num_args, EX(num_args));
-
- if (EXPECTED(num_args < op_array->last_var)) {
- zval *var = EX_VAR_NUM(num_args);
- zval *end = EX_VAR_NUM(op_array->last_var);
+ if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
+ /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
+ EX(opline) += first_extra_arg;
+ }
+ /* move extra args into separate array after all CV and TMP vars */
+ end = EX_VAR_NUM(first_extra_arg - 1);
+ src = end + (num_args - first_extra_arg);
+ dst = src + (op_array->last_var + op_array->T - first_extra_arg);
+ if (EXPECTED(src != dst)) {
do {
- ZVAL_UNDEF(var);
- var++;
- } while (var != end);
+ ZVAL_COPY_VALUE(dst, src);
+ ZVAL_UNDEF(src);
+ src--;
+ dst--;
+ } while (src != end);
}
- } while (0);
+ } else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
+ /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
+ EX(opline) += num_args;
+ }
+
+ /* Initialize CV variables (skip arguments) */
+ if (EXPECTED(num_args < op_array->last_var)) {
+ zval *var = EX_VAR_NUM(num_args);
+ zval *end = EX_VAR_NUM(op_array->last_var);
+
+ do {
+ ZVAL_UNDEF(var);
+ var++;
+ } while (var != end);
+ }
if (op_array->this_var != -1 && EX(object)) {
ZVAL_OBJ(EX_VAR(op_array->this_var), EX(object));
@@ -1732,7 +1666,7 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data
if (num_args > 0) {
zval *arg_src = ZEND_CALL_ARG(call, 1);
zval *arg_dst = ZEND_CALL_ARG(execute_data, 1);
- int i;
+ uint32_t i;
for (i = 0; i < num_args; i++) {
ZVAL_COPY_VALUE(arg_dst + i, arg_src + i);