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.c885
1 files changed, 416 insertions, 469 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 54397153c1..58038c94a4 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"
@@ -64,27 +65,15 @@ static void zend_extension_fcall_end_handler(const zend_extension *extension, ze
#define RETURN_VALUE_USED(opline) (!((opline)->result_type & EXT_TYPE_UNUSED))
-#define TEMP_VAR_STACK_LIMIT 2000
-
-static zend_always_inline void zend_pzval_unlock_func(zval *z, zend_free_op *should_free)
-{
- should_free->var = NULL;
- if (Z_REFCOUNTED_P(z) && !Z_DELREF_P(z)) {
- Z_SET_REFCOUNT_P(z, 1);
- should_free->var = z;
- /* should_free->is_var = 1; */
- }
-}
-
static ZEND_FUNCTION(pass)
{
}
static const zend_internal_function zend_pass_function = {
ZEND_INTERNAL_FUNCTION, /* type */
+ 0, /* fn_flags */
NULL, /* name */
NULL, /* scope */
- 0, /* fn_flags */
NULL, /* prototype */
0, /* num_args */
0, /* required_num_args */
@@ -95,12 +84,13 @@ 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_UNLOCK(z, f) zend_pzval_unlock_func(z, f)
#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); }
+#define READY_TO_DESTROY(zv) \
+ (zv && Z_REFCOUNTED_P(zv) && Z_REFCOUNT_P(zv) == 1)
+
#define EXTRACT_ZVAL_PTR(zv) do { \
zval *__zv = (zv); \
if (Z_TYPE_P(__zv) == IS_INDIRECT) { \
@@ -110,15 +100,6 @@ static const zend_internal_function zend_pass_function = {
#define FREE_OP(should_free) \
if (should_free.var) { \
- if ((zend_uintptr_t)should_free.var & 1L) { \
- zval_dtor((zval*)((zend_uintptr_t)should_free.var & ~1L)); \
- } else { \
- zval_ptr_dtor_nogc(should_free.var); \
- } \
- }
-
-#define FREE_OP_IF_VAR(should_free) \
- if (should_free.var != NULL && (((zend_uintptr_t)should_free.var & 1L) == 0)) { \
zval_ptr_dtor_nogc(should_free.var); \
}
@@ -127,10 +108,6 @@ static const zend_internal_function zend_pass_function = {
zval_ptr_dtor_nogc(should_free.var); \
}
-#define TMP_FREE(z) (zval*)(((zend_uintptr_t)(z)) | 1L)
-
-#define IS_TMP_FREE(should_free) ((zend_uintptr_t)should_free.var & 1L)
-
/* End of zend_execute_locks.h */
#define CV_DEF_OF(i) (EX(func)->op_array.vars[i])
@@ -146,15 +123,67 @@ static const zend_internal_function zend_pass_function = {
#define DECODE_CTOR(ce) \
((zend_class_entry*)(((zend_uintptr_t)(ce)) & ~(CTOR_CALL_BIT|CTOR_USED_BIT)))
-#undef EX
-#define EX(element) execute_data->element
+#define ZEND_VM_STACK_PAGE_SLOTS (16 * 1024) /* should be a power of 2 */
+
+#define ZEND_VM_STACK_PAGE_SIZE (ZEND_VM_STACK_PAGE_SLOTS * sizeof(zval))
+
+#define ZEND_VM_STACK_FREE_PAGE_SIZE \
+ ((ZEND_VM_STACK_PAGE_SLOTS - ZEND_VM_STACK_HEADER_SLOTS) * sizeof(zval))
+
+#define ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size) \
+ (((size) + (ZEND_VM_STACK_FREE_PAGE_SIZE - 1)) & ~ZEND_VM_STACK_PAGE_SIZE)
+
+static zend_always_inline zend_vm_stack zend_vm_stack_new_page(size_t size, zend_vm_stack prev) {
+ zend_vm_stack page = (zend_vm_stack)emalloc(size);
+
+ page->top = ZEND_VM_STACK_ELEMETS(page);
+ page->end = (zval*)((char*)page + size);
+ page->prev = prev;
+ return page;
+}
+
+ZEND_API void zend_vm_stack_init(TSRMLS_D)
+{
+ EG(vm_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE, NULL);
+ EG(vm_stack)->top++;
+ EG(vm_stack_top) = EG(vm_stack)->top;
+ EG(vm_stack_end) = EG(vm_stack)->end;
+}
+
+ZEND_API void zend_vm_stack_destroy(TSRMLS_D)
+{
+ zend_vm_stack stack = EG(vm_stack);
+
+ while (stack != NULL) {
+ zend_vm_stack p = stack->prev;
+ efree(stack);
+ stack = p;
+ }
+}
+
+ZEND_API void* zend_vm_stack_extend(size_t size TSRMLS_DC)
+{
+ zend_vm_stack stack;
+ void *ptr;
+
+ stack = EG(vm_stack);
+ stack->top = EG(vm_stack_top);
+ EG(vm_stack) = stack = zend_vm_stack_new_page(
+ EXPECTED(size < ZEND_VM_STACK_FREE_PAGE_SIZE) ?
+ ZEND_VM_STACK_PAGE_SIZE : ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size),
+ stack);
+ ptr = stack->top;
+ EG(vm_stack_top) = (void*)(((char*)ptr) + size);
+ EG(vm_stack_end) = stack->end;
+ return ptr;
+}
-ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data, zend_uint var)
+ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data, uint32_t var)
{
return EX_VAR(var);
}
-static zend_always_inline zval *_get_zval_ptr_tmp(zend_uint 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 TSRMLS_DC)
{
zval *ret = EX_VAR(var);
should_free->var = ret;
@@ -164,7 +193,7 @@ static zend_always_inline zval *_get_zval_ptr_tmp(zend_uint var, const zend_exec
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_var(zend_uint 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 TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -172,7 +201,7 @@ static zend_always_inline zval *_get_zval_ptr_var(zend_uint var, const zend_exec
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_var_deref(zend_uint 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 TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -181,7 +210,7 @@ static zend_always_inline zval *_get_zval_ptr_var_deref(zend_uint var, const zen
return ret;
}
-static zend_never_inline zval *_get_zval_cv_lookup(zval *ptr, zend_uint var, int type, const zend_execute_data *execute_data TSRMLS_DC)
+static zend_never_inline zval *_get_zval_cv_lookup(zval *ptr, uint32_t var, int type, const zend_execute_data *execute_data TSRMLS_DC)
{
zend_string *cv;
@@ -205,7 +234,7 @@ static zend_never_inline zval *_get_zval_cv_lookup(zval *ptr, zend_uint var, int
return ptr;
}
-static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, zend_uint var, const zend_execute_data *execute_data TSRMLS_DC)
+static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, uint32_t var, const zend_execute_data *execute_data TSRMLS_DC)
{
zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
@@ -213,7 +242,7 @@ static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, zend_uin
return &EG(uninitialized_zval);
}
-static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, zend_uint var, const zend_execute_data *execute_data TSRMLS_DC)
+static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, uint32_t var, const zend_execute_data *execute_data TSRMLS_DC)
{
zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
@@ -221,12 +250,7 @@ static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, zend
return &EG(uninitialized_zval);
}
-static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_IS(zval *ptr, zend_uint 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, zend_uint var, const zend_execute_data *execute_data TSRMLS_DC)
+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));
@@ -235,13 +259,13 @@ static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_RW(zval *ptr, zend_ui
return ptr;
}
-static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_W(zval *ptr, zend_uint var, const zend_execute_data *execute_data TSRMLS_DC)
+static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_W(zval *ptr, uint32_t var, const zend_execute_data *execute_data TSRMLS_DC)
{
ZVAL_NULL(ptr);
return ptr;
}
-static zend_always_inline zval *_get_zval_ptr_cv(const zend_execute_data *execute_data, zend_uint var, int type TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv(const zend_execute_data *execute_data, uint32_t var, int type TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -251,7 +275,7 @@ static zend_always_inline zval *_get_zval_ptr_cv(const zend_execute_data *execut
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_deref(const zend_execute_data *execute_data, zend_uint var, int type TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_deref(const zend_execute_data *execute_data, uint32_t var, int type TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -262,7 +286,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref(const zend_execute_data *
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -272,7 +296,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(const zend_execute_dat
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_R(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_R(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -283,7 +307,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_R(const zend_execu
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -293,7 +317,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(const zend_execute
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_UNSET(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_UNSET(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -304,28 +328,22 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_UNSET(const zend_e
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
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;
}
-static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_IS(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_IS(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
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;
}
-static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -335,7 +353,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(const zend_execute_da
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_RW(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_RW(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -346,7 +364,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_RW(const zend_exec
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -356,12 +374,12 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(const zend_execute_dat
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_W(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
return EX_VAR(var);
}
-static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_W(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var TSRMLS_DC)
{
zval *ret = EX_VAR(var);
@@ -383,7 +401,7 @@ static inline zval *_get_zval_ptr(int op_type, const znode_op *node, const zend_
break;
case IS_TMP_VAR:
ret = EX_VAR(node->var);
- should_free->var = TMP_FREE(ret);
+ should_free->var = ret;
return ret;
break;
case IS_VAR:
@@ -413,7 +431,7 @@ static inline zval *_get_zval_ptr_deref(int op_type, const znode_op *node, const
break;
case IS_TMP_VAR:
ret = EX_VAR(node->var);
- should_free->var = TMP_FREE(ret);
+ should_free->var = ret;
return ret;
break;
case IS_VAR:
@@ -432,18 +450,19 @@ static inline zval *_get_zval_ptr_deref(int op_type, const znode_op *node, const
return NULL;
}
-static zend_always_inline zval *_get_zval_ptr_ptr_var(zend_uint 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 TSRMLS_DC)
{
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)) {
- should_free->var = ret; //???
+ } else if (!Z_REFCOUNTED_P(ret) || Z_REFCOUNT_P(ret) == 1) {
+ should_free->var = ret;
return ret;
} else {
- PZVAL_UNLOCK(ret, should_free);
+ Z_DELREF_P(ret);
+ should_free->var = NULL;
return ret;
}
}
@@ -459,22 +478,22 @@ static inline zval *_get_zval_ptr_ptr(int op_type, const znode_op *node, const z
}
}
-static zend_always_inline zval *_get_obj_zval_ptr_unused(TSRMLS_D)
+static zend_always_inline zval *_get_obj_zval_ptr_unused(zend_execute_data *execute_data TSRMLS_DC)
{
- if (EXPECTED(Z_OBJ(EG(This)) != NULL)) {
- return &EG(This);
+ if (EXPECTED(Z_OBJ(EX(This)) != NULL)) {
+ return &EX(This);
} else {
zend_error_noreturn(E_ERROR, "Using $this when not in object context");
return NULL;
}
}
-static inline zval *_get_obj_zval_ptr(int op_type, znode_op *op, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC)
+static inline zval *_get_obj_zval_ptr(int op_type, znode_op *op, zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC)
{
if (op_type == IS_UNUSED) {
- if (EXPECTED(Z_OBJ(EG(This)) != NULL)) {
+ if (EXPECTED(Z_OBJ(EX(This)) != NULL)) {
should_free->var = NULL;
- return &EG(This);
+ return &EX(This);
} else {
zend_error_noreturn(E_ERROR, "Using $this when not in object context");
}
@@ -482,12 +501,12 @@ static inline zval *_get_obj_zval_ptr(int op_type, znode_op *op, const zend_exec
return get_zval_ptr(op_type, op, execute_data, should_free, type);
}
-static inline zval *_get_obj_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)
+static inline zval *_get_obj_zval_ptr_ptr(int op_type, const znode_op *node, zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC)
{
if (op_type == IS_UNUSED) {
- if (EXPECTED(Z_OBJ(EG(This)) != NULL)) {
+ if (EXPECTED(Z_OBJ(EX(This)) != NULL)) {
should_free->var = NULL;
- return &EG(This);
+ return &EX(This);
} else {
zend_error_noreturn(E_ERROR, "Using $this when not in object context");
}
@@ -498,10 +517,13 @@ static inline zval *_get_obj_zval_ptr_ptr(int op_type, const znode_op *node, con
static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr TSRMLS_DC)
{
if (EXPECTED(variable_ptr != value_ptr)) {
+ zend_reference *ref;
ZVAL_MAKE_REF(value_ptr);
Z_ADDREF_P(value_ptr);
+ ref = Z_REF_P(value_ptr);
+
zval_ptr_dtor(variable_ptr);
- ZVAL_REF(variable_ptr, Z_REF_P(value_ptr));
+ ZVAL_REF(variable_ptr, ref);
} else {
ZVAL_MAKE_REF(variable_ptr);
}
@@ -516,7 +538,7 @@ static inline zval* make_real_object(zval *object_ptr TSRMLS_DC)
if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if (Z_TYPE_P(object) == IS_NULL
|| Z_TYPE_P(object) == IS_FALSE
- || (Z_TYPE_P(object) == IS_STRING && Z_STRSIZE_P(object) == 0)) {
+ || (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0)) {
zval_ptr_dtor_nogc(object);
object_init(object);
zend_error(E_WARNING, "Creating default object from empty value");
@@ -525,7 +547,7 @@ static inline zval* make_real_object(zval *object_ptr TSRMLS_DC)
return object;
}
-ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, zend_uint_t fetch_type, char **class_name, zend_class_entry **pce TSRMLS_DC)
+ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, zend_ulong fetch_type, char **class_name, zend_class_entry **pce TSRMLS_DC)
{
zend_string *key;
ALLOCA_FLAG(use_heap);
@@ -542,7 +564,7 @@ ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ze
}
}
-ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC)
+ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, uint32_t arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC)
{
zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
const char *fname = zf->common.function_name->val;
@@ -574,7 +596,7 @@ ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zen
}
}
-static void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg, zend_uint_t fetch_type TSRMLS_DC)
+static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zend_ulong fetch_type TSRMLS_DC)
{
zend_arg_info *cur_arg_info;
char *need_msg;
@@ -623,7 +645,7 @@ static void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg
}
}
-static inline int zend_verify_missing_arg_type(zend_function *zf, zend_uint arg_num, zend_uint_t fetch_type TSRMLS_DC)
+static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_num, zend_ulong fetch_type TSRMLS_DC)
{
zend_arg_info *cur_arg_info;
char *need_msg;
@@ -646,6 +668,7 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, zend_uint arg_
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);
@@ -656,11 +679,12 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, zend_uint arg_
zend_error(E_ERROR, "Unknown typehint");
#endif
}
+ return 0;
}
- return 0;
+ return 1;
}
-static void zend_verify_missing_arg(zend_execute_data *execute_data, zend_uint arg_num TSRMLS_DC)
+static void zend_verify_missing_arg(zend_execute_data *execute_data, uint32_t arg_num TSRMLS_DC)
{
if (EXPECTED(!(EX(func)->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) ||
zend_verify_missing_arg_type(EX(func), arg_num, EX(opline)->extended_value TSRMLS_CC)) {
@@ -677,49 +701,50 @@ static void zend_verify_missing_arg(zend_execute_data *execute_data, zend_uint a
}
}
-static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *property_name, int value_type, znode_op *value_op, const zend_execute_data *execute_data, int opcode, void **cache_slot TSRMLS_DC)
+static zend_always_inline void zend_assign_to_object(zval *retval, zval *object, uint32_t object_op_type, zval *property_name, int value_type, const znode_op *value_op, const zend_execute_data *execute_data, int opcode, void **cache_slot TSRMLS_DC)
{
zend_free_op free_value;
zval *value = get_zval_ptr(value_type, value_op, execute_data, &free_value, BP_VAR_R);
zval tmp;
- zval *object = object_ptr;
- ZVAL_DEREF(object);
- if (Z_TYPE_P(object) != IS_OBJECT) {
- if (object == &EG(error_zval)) {
- if (retval) {
- ZVAL_NULL(retval);
+ if (object_op_type != IS_UNUSED) {
+ ZVAL_DEREF(object);
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (UNEXPECTED(object == &EG(error_zval))) {
+ if (retval) {
+ ZVAL_NULL(retval);
+ }
+ FREE_OP(free_value);
+ return;
}
- FREE_OP(free_value);
- return;
- }
- if (Z_TYPE_P(object) == IS_NULL ||
- Z_TYPE_P(object) == IS_FALSE ||
- (Z_TYPE_P(object) == IS_STRING && Z_STRSIZE_P(object) == 0)) {
- zend_object *obj;
-
- zval_ptr_dtor(object);
- object_init(object);
- Z_ADDREF_P(object);
- obj = Z_OBJ_P(object);
- zend_error(E_WARNING, "Creating default object from empty value");
- if (GC_REFCOUNT(obj) == 1) {
- /* the enclosing container was deleted, obj is unreferenced */
+ if (EXPECTED(Z_TYPE_P(object) == IS_NULL ||
+ Z_TYPE_P(object) == IS_FALSE ||
+ (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) {
+ zend_object *obj;
+
+ zval_ptr_dtor(object);
+ object_init(object);
+ Z_ADDREF_P(object);
+ obj = Z_OBJ_P(object);
+ zend_error(E_WARNING, "Creating default object from empty value");
+ if (GC_REFCOUNT(obj) == 1) {
+ /* the enclosing container was deleted, obj is unreferenced */
+ if (retval) {
+ ZVAL_NULL(retval);
+ }
+ FREE_OP(free_value);
+ OBJ_RELEASE(obj);
+ return;
+ }
+ Z_DELREF_P(object);
+ } else {
+ zend_error(E_WARNING, "Attempt to assign property of non-object");
if (retval) {
ZVAL_NULL(retval);
}
FREE_OP(free_value);
- OBJ_RELEASE(obj);
return;
}
- Z_DELREF_P(object);
- } else {
- zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (retval) {
- ZVAL_NULL(retval);
- }
- FREE_OP(free_value);
- return;
}
}
@@ -762,18 +787,18 @@ static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *p
ZVAL_COPY(retval, value);
}
zval_ptr_dtor(value);
- FREE_OP_IF_VAR(free_value);
+ if (value_type == IS_VAR) {
+ FREE_OP(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, zval *result TSRMLS_DC)
{
- zval *str = Z_STR_OFFSET_STR_P(str_offset);
- zend_uint 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);
- STR_RELEASE(Z_STR_P(str));
+ 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);
}
@@ -781,14 +806,14 @@ static void zend_assign_to_string_offset(zval *str_offset, zval *value, int valu
}
old_str = Z_STR_P(str);
- if (offset >= Z_STRSIZE_P(str)) {
- int old_len = Z_STRSIZE_P(str);
- Z_STR_P(str) = STR_REALLOC(Z_STR_P(str), offset + 1, 0);
+ 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))) {
- Z_STR_P(str) = STR_INIT(Z_STRVAL_P(str), Z_STRSIZE_P(str), 0);
+ } 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;
}
@@ -796,171 +821,81 @@ static void zend_assign_to_string_offset(zval *str_offset, zval *value, int valu
zend_string *tmp = zval_get_string(value);
Z_STRVAL_P(str)[offset] = tmp->val[0];
- STR_RELEASE(tmp);
+ zend_string_release(tmp);
} else {
Z_STRVAL_P(str)[offset] = Z_STRVAL_P(value)[0];
- if (value_type == IS_TMP_VAR) {
- /* we can safely free final_value here
- * because separation is done only
- * in case value_type == IS_VAR */
- zval_dtor(value);
- }
}
/*
* the value of an assignment to a string offset is undefined
T(result->u.var).var = &T->str_offset.str;
*/
- STR_RELEASE(old_str);
+ zend_string_release(old_str);
if (result) {
zend_uchar c = (zend_uchar)Z_STRVAL_P(str)[offset];
if (CG(one_char_string)[c]) {
- ZVAL_INT_STR(result, CG(one_char_string)[c]);
+ ZVAL_INTERNED_STR(result, CG(one_char_string)[c]);
} else {
- ZVAL_NEW_STR(result, STR_INIT(Z_STRVAL_P(str) + offset, 1, 0));
+ ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(str) + offset, 1, 0));
}
}
}
-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) == 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);
}
- 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_for_ptr(garbage ZEND_FILE_LINE_CC);
+ return variable_ptr;
+ } else { /* we need to split */
+ /* 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;
@@ -1015,23 +950,23 @@ static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht
{
zval *retval;
zend_string *offset_key;
- zend_uint_t hval;
+ zend_ulong hval;
- if (EXPECTED(Z_TYPE_P(dim) == IS_INT)) {
- hval = Z_IVAL_P(dim);
+ if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) {
+ hval = Z_LVAL_P(dim);
num_index:
retval = zend_hash_index_find(ht, hval);
if (retval == NULL) {
switch (type) {
case BP_VAR_R:
- zend_error(E_NOTICE,"Undefined offset: " ZEND_UINT_FMT, hval);
+ zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, hval);
/* break missing intentionally */
case BP_VAR_UNSET:
case BP_VAR_IS:
retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined offset: " ZEND_UINT_FMT, hval);
+ zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, hval);
/* break missing intentionally */
case BP_VAR_W:
retval = zend_hash_index_add_new(ht, hval, &EG(uninitialized_zval));
@@ -1092,10 +1027,10 @@ str_index:
offset_key = STR_EMPTY_ALLOC();
goto str_index;
case IS_DOUBLE:
- hval = zend_dval_to_ival(Z_DVAL_P(dim));
+ hval = zend_dval_to_lval(Z_DVAL_P(dim));
goto num_index;
case IS_RESOURCE:
- zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_RES_HANDLE_P(dim), Z_RES_HANDLE_P(dim));
+ zend_error(E_STRICT, "Resource ID#%pd used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(dim), Z_RES_HANDLE_P(dim));
hval = Z_RES_HANDLE_P(dim);
goto num_index;
case IS_FALSE:
@@ -1113,7 +1048,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;
@@ -1124,7 +1059,7 @@ static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *
fetch_from_array:
if (dim == NULL) {
retval = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
- if (retval == NULL) {
+ if (UNEXPECTED(retval == NULL)) {
zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
retval = &EG(error_zval);
}
@@ -1133,33 +1068,27 @@ fetch_from_array:
}
if (is_ref) {
ZVAL_MAKE_REF(retval);
- Z_ADDREF_P(retval);
- ZVAL_REF(result, Z_REF_P(retval));
- } else {
- ZVAL_INDIRECT(result, retval);
}
+ ZVAL_INDIRECT(result, retval);
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
- zend_int_t offset;
+ zend_long offset;
- if (type != BP_VAR_UNSET && UNEXPECTED(Z_STRSIZE_P(container) == 0)) {
- zval_dtor(container);
+ if (type != BP_VAR_UNSET && UNEXPECTED(Z_STRLEN_P(container) == 0)) {
+ zval_ptr_dtor_nogc(container);
convert_to_array:
ZVAL_NEW_ARR(container);
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_INT)) {
+ if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
switch(Z_TYPE_P(dim)) {
case IS_STRING:
- if (IS_INT == is_numeric_string(Z_STRVAL_P(dim), Z_STRSIZE_P(dim), NULL, NULL, -1)) {
+ if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
break;
}
if (type != BP_VAR_UNSET) {
@@ -1177,13 +1106,24 @@ convert_to_array:
break;
}
- offset = zval_get_int(dim);
+ offset = zval_get_long(dim);
} else {
- offset = Z_IVAL_P(dim);
+ offset = Z_LVAL_P(dim);
}
- if (!IS_INTERNED(Z_STR_P(container))) STR_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");
@@ -1195,7 +1135,7 @@ convert_to_array:
ZVAL_NULL(result);
zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ce->name->val);
- } else if (retval && Z_TYPE_P(retval) != IS_UNDEF) {
+ } else if (EXPECTED(retval && Z_TYPE_P(retval) != IS_UNDEF)) {
if (!Z_ISREF_P(retval)) {
if (Z_REFCOUNTED_P(retval) &&
Z_REFCOUNT_P(retval) > 1) {
@@ -1216,18 +1156,15 @@ convert_to_array:
if (result != retval) {
if (is_ref) {
ZVAL_MAKE_REF(retval);
- Z_ADDREF_P(retval);
- ZVAL_REF(result, Z_REF_P(retval));
- } else {
- ZVAL_INDIRECT(result, retval);
}
+ ZVAL_INDIRECT(result, retval);
}
} else {
ZVAL_INDIRECT(result, &EG(error_zval));
}
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_NULL)) {
- if (container == &EG(error_zval)) {
+ if (UNEXPECTED(container == &EG(error_zval))) {
ZVAL_INDIRECT(result, &EG(error_zval));
} else if (type != BP_VAR_UNSET) {
goto convert_to_array;
@@ -1248,26 +1185,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)
@@ -1279,13 +1222,13 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z
retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type TSRMLS_CC);
ZVAL_COPY(result, retval);
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
- zend_int_t offset;
+ zend_long offset;
- if (UNEXPECTED(Z_TYPE_P(dim) != IS_INT)) {
+ if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
switch(Z_TYPE_P(dim)) {
- /* case IS_INT: */
+ /* case IS_LONG: */
case IS_STRING:
- if (IS_INT == is_numeric_string(Z_STRVAL_P(dim), Z_STRSIZE_P(dim), NULL, NULL, -1)) {
+ if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
break;
}
if (type != BP_VAR_IS) {
@@ -1305,23 +1248,23 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z
break;
}
- offset = zval_get_int(dim);
+ offset = zval_get_long(dim);
} else {
- offset = Z_IVAL_P(dim);
+ offset = Z_LVAL_P(dim);
}
- if (UNEXPECTED(offset < 0) || UNEXPECTED(Z_STRSIZE_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 {
zend_uchar c = (zend_uchar)Z_STRVAL_P(container)[offset];
if (CG(one_char_string)[c]) {
- ZVAL_INT_STR(result, CG(one_char_string)[c]);
+ ZVAL_INTERNED_STR(result, CG(one_char_string)[c]);
} else {
- ZVAL_NEW_STR(result, STR_INIT(Z_STRVAL_P(container) + offset, 1, 0));
+ ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(container) + offset, 1, 0));
}
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
@@ -1330,14 +1273,13 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z
} else {
retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result TSRMLS_CC);
- if (result) {
- if (retval) {
- if (result != retval) {
- ZVAL_COPY(result, retval);
- }
- } else {
- ZVAL_NULL(result);
+ ZEND_ASSERT(result != NULL);
+ if (retval) {
+ if (result != retval) {
+ ZVAL_COPY(result, retval);
}
+ } else {
+ ZVAL_NULL(result);
}
}
} else {
@@ -1360,32 +1302,31 @@ 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 void zend_fetch_property_address(zval *result, zval *container_ptr, zval *prop_ptr, void **cache_slot, int type, int is_ref TSRMLS_DC)
+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, int is_ref TSRMLS_DC)
{
- zval *container = container_ptr;
-
- ZVAL_DEREF(container);
- if (Z_TYPE_P(container) != IS_OBJECT) {
- if (container == &EG(error_zval)) {
- ZVAL_INDIRECT(result, &EG(error_zval));
- return;
- }
+ if (container_op_type != IS_UNUSED) {
+ ZVAL_DEREF(container);
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (UNEXPECTED(container == &EG(error_zval))) {
+ ZVAL_INDIRECT(result, &EG(error_zval));
+ return;
+ }
- /* this should modify object only if it's empty */
- if (type != BP_VAR_UNSET &&
- ((Z_TYPE_P(container) == IS_NULL ||
- Z_TYPE_P(container) == IS_FALSE ||
- (Z_TYPE_P(container) == IS_STRING && Z_STRSIZE_P(container)==0)))) {
- zval_ptr_dtor_nogc(container);
- object_init(container);
- } else {
- zend_error(E_WARNING, "Attempt to modify property of non-object");
- ZVAL_INDIRECT(result, &EG(error_zval));
- return;
+ /* this should modify object only if it's empty */
+ if (type != BP_VAR_UNSET &&
+ EXPECTED((Z_TYPE_P(container) == IS_NULL ||
+ Z_TYPE_P(container) == IS_FALSE ||
+ (Z_TYPE_P(container) == IS_STRING && Z_STRLEN_P(container)==0)))) {
+ zval_ptr_dtor_nogc(container);
+ object_init(container);
+ } else {
+ zend_error(E_WARNING, "Attempt to modify property of non-object");
+ ZVAL_INDIRECT(result, &EG(error_zval));
+ return;
+ }
}
}
-
- if (Z_OBJ_HT_P(container)->get_property_ptr_ptr) {
+ 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) {
if (Z_OBJ_HT_P(container)->read_property &&
@@ -1393,11 +1334,8 @@ static void zend_fetch_property_address(zval *result, zval *container_ptr, zval
if (ptr != result) {
if (is_ref && ptr != &EG(uninitialized_zval)) {
ZVAL_MAKE_REF(ptr);
- Z_ADDREF_P(ptr);
- ZVAL_REF(result, Z_REF_P(ptr));
- } else {
- ZVAL_INDIRECT(result, ptr);
}
+ ZVAL_INDIRECT(result, ptr);
}
} else {
zend_error_noreturn(E_ERROR, "Cannot access undefined property for object with overloaded property access");
@@ -1405,22 +1343,16 @@ static void zend_fetch_property_address(zval *result, zval *container_ptr, zval
} else {
if (is_ref) {
ZVAL_MAKE_REF(ptr);
- Z_ADDREF_P(ptr);
- ZVAL_REF(result, Z_REF_P(ptr));
- } else {
- ZVAL_INDIRECT(result, ptr);
}
+ ZVAL_INDIRECT(result, ptr);
}
- } else if (Z_OBJ_HT_P(container)->read_property) {
+ } else if (EXPECTED(Z_OBJ_HT_P(container)->read_property)) {
zval *ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result TSRMLS_CC);
if (ptr != result) {
if (is_ref && ptr != &EG(uninitialized_zval)) {
ZVAL_MAKE_REF(ptr);
- Z_ADDREF_P(ptr);
- ZVAL_REF(result, Z_REF_P(ptr));
- } else {
- ZVAL_INDIRECT(result, ptr);
}
+ ZVAL_INDIRECT(result, ptr);
}
} else {
zend_error(E_WARNING, "This object doesn't support property references");
@@ -1441,13 +1373,9 @@ static inline zend_brk_cont_element* zend_brk_cont(int nest_levels, int array_of
if (nest_levels>1) {
zend_op *brk_opline = &op_array->opcodes[jmp_to->brk];
- if (brk_opline->opcode == ZEND_SWITCH_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
- zval_ptr_dtor(EX_VAR(brk_opline->op1.var));
- }
- } else if (brk_opline->opcode == ZEND_FREE) {
+ if (brk_opline->opcode == ZEND_FREE) {
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
- zval_dtor(EX_VAR(brk_opline->op1.var));
+ zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
}
}
}
@@ -1494,14 +1422,14 @@ ZEND_API opcode_handler_t *zend_opcode_handlers;
ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value TSRMLS_DC)
{
- execute_data->func->internal_function.handler(execute_data->num_args, return_value TSRMLS_CC);
+ execute_data->func->internal_function.handler(execute_data, return_value TSRMLS_CC);
}
-void zend_clean_and_cache_symbol_table(zend_array *symbol_table TSRMLS_DC) /* {{{ */
+ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table TSRMLS_DC) /* {{{ */
{
if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) {
zend_hash_destroy(&symbol_table->ht);
- FREE_HASHTABLE(symbol_table);
+ efree_size(symbol_table, sizeof(zend_array));
} else {
/* clean before putting into the cache, since clean
could call dtors, which could use cached hash */
@@ -1550,63 +1478,67 @@ 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) /* {{{ */
+static zend_always_inline void i_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
{
- zend_uint 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)));
+ ZEND_ASSERT(EX(scope) == EG(scope));
+ EX(opline) = op_array->opcodes;
+ EX(call) = NULL;
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(scope) = EG(scope);
+ EX(silence_op_num) = -1;
+ /* 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;
+ }
- if (op_array->this_var != -1 && EX(object)) {
- ZVAL_OBJ(EX_VAR(op_array->this_var), EX(object));
- GC_REFCOUNT(EX(object))++;
+ /* Initialize CV variables (skip arguments) */
+ if (EXPECTED((int)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 && Z_OBJ(EX(This))) {
+ ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This)));
+ GC_REFCOUNT(Z_OBJ(EX(This)))++;
}
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;
@@ -1614,28 +1546,26 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu
}
/* }}} */
-static zend_always_inline void i_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
+static zend_always_inline void i_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
{
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(opline) = op_array->opcodes;
EX(call) = NULL;
-
- EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
+ EX(return_value) = return_value;
EX(scope) = EG(scope);
+ EX(delayed_exception) = NULL;
+ EX(silence_op_num) = -1;
zend_attach_symbol_table(execute_data);
+ if (op_array->this_var != -1 && Z_OBJ(EX(This))) {
+ ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This)));
+ GC_REFCOUNT(Z_OBJ(EX(This)))++;
+ }
+
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;
@@ -1643,56 +1573,70 @@ static zend_always_inline void i_init_code_execute_data(zend_execute_data *execu
}
/* }}} */
-static zend_always_inline void i_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
+static zend_always_inline void i_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
{
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(opline) = op_array->opcodes;
EX(call) = NULL;
-
- EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
+ EX(return_value) = return_value;
EX(scope) = EG(scope);
+ EX(delayed_exception) = NULL;
+ EX(silence_op_num) = -1;
if (UNEXPECTED(EX(symbol_table) != NULL)) {
zend_attach_symbol_table(execute_data);
} else {
- zend_uint 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);
-
- memmove(extra_args, EX_VAR_NUM(first_extra_arg), sizeof(zval) * (EX(num_args) - first_extra_arg));
- }
+ num_args = EX(num_args);
+ if (UNEXPECTED(num_args > first_extra_arg)) {
+ zval *end, *src, *dst;
- 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;
+ }
- if (op_array->this_var != -1 && EX(object)) {
- ZVAL_OBJ(EX_VAR(op_array->this_var), EX(object));
- GC_REFCOUNT(EX(object))++;
+ /* Initialize CV variables (skip arguments) */
+ if (EXPECTED((int)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 && Z_OBJ(EX(This))) {
+ ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This)));
+ GC_REFCOUNT(Z_OBJ(EX(This)))++;
+ }
+
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*));
@@ -1718,19 +1662,23 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data
* restore it simply by replacing a pointer.
*/
zend_execute_data *execute_data;
- zend_uint num_args = call->num_args;
+ uint32_t num_args = call->num_args;
+ size_t stack_size = (ZEND_CALL_FRAME_SLOT + MAX(op_array->last_var + op_array->T, num_args)) * sizeof(zval);
- EG(argument_stack) = zend_vm_stack_new_page(
- MAX(ZEND_VM_STACK_PAGE_SIZE,
- ZEND_CALL_FRAME_SLOT + MAX(op_array->last_var + op_array->T, num_args)));
- EG(argument_stack)->prev = NULL;
+ EG(vm_stack) = zend_vm_stack_new_page(
+ EXPECTED(stack_size < ZEND_VM_STACK_FREE_PAGE_SIZE) ?
+ ZEND_VM_STACK_PAGE_SIZE :
+ ZEND_VM_STACK_PAGE_ALIGNED_SIZE(stack_size),
+ NULL);
+ EG(vm_stack_top) = EG(vm_stack)->top;
+ EG(vm_stack_end) = EG(vm_stack)->end;
execute_data = zend_vm_stack_push_call_frame(
+ VM_FRAME_TOP_FUNCTION,
(zend_function*)op_array,
num_args,
- call->flags,
call->called_scope,
- call->object,
+ Z_OBJ(call->This),
NULL TSRMLS_CC);
EX(num_args) = num_args;
@@ -1738,7 +1686,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);
@@ -1746,36 +1694,35 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data
}
EX(symbol_table) = NULL;
+ EX(scope) = EG(scope);
- i_init_func_execute_data(execute_data, op_array, return_value, VM_FRAME_TOP_FUNCTION TSRMLS_CC);
+ i_init_func_execute_data(execute_data, op_array, return_value TSRMLS_CC);
return execute_data;
}
/* }}} */
-ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
+ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
{
EX(prev_execute_data) = EG(current_execute_data);
- i_init_execute_data(execute_data, op_array, return_value, frame_kind TSRMLS_CC);
+ i_init_execute_data(execute_data, op_array, return_value TSRMLS_CC);
}
/* }}} */
-static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(zend_op *opline, zend_execute_data *call TSRMLS_DC) /* {{{ */
+static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(const zend_op *opline, zend_execute_data *call TSRMLS_DC) /* {{{ */
{
- zend_uint arg_num = opline->extended_value & ZEND_FETCH_ARG_MASK;
+ uint32_t arg_num = opline->extended_value & ZEND_FETCH_ARG_MASK;
return ARG_SHOULD_BE_SENT_BY_REF(call->func, arg_num);
}
/* }}} */
-static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call, zend_uint passed_args, zend_uint additional_args TSRMLS_DC) /* {{{ */
+static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call, uint32_t passed_args, uint32_t additional_args TSRMLS_DC) /* {{{ */
{
zend_execute_data *new_call;
- int used_stack = (EG(argument_stack)->top - (zval*)call) + additional_args;
+ int used_stack = (EG(vm_stack_top) - (zval*)call) + additional_args;
/* copy call frame into new stack segment */
- zend_vm_stack_extend(used_stack TSRMLS_CC);
- new_call = (zend_execute_data*)EG(argument_stack)->top;
- EG(argument_stack)->top += used_stack;
+ new_call = zend_vm_stack_extend(used_stack * sizeof(zval) TSRMLS_CC);
*new_call = *call;
if (passed_args) {
zval *src = ZEND_CALL_ARG(call, 1);
@@ -1789,13 +1736,13 @@ static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call,
}
/* delete old call_frame from previous stack segment */
- EG(argument_stack)->prev->top = (zval*)call;
+ EG(vm_stack)->prev->top = (zval*)call;
/* delete previous stack segment if it becames empty */
- if (UNEXPECTED(EG(argument_stack)->prev->top == ZEND_VM_STACK_ELEMETS(EG(argument_stack)->prev))) {
- zend_vm_stack r = EG(argument_stack)->prev;
+ if (UNEXPECTED(EG(vm_stack)->prev->top == ZEND_VM_STACK_ELEMETS(EG(vm_stack)->prev))) {
+ zend_vm_stack r = EG(vm_stack)->prev;
- EG(argument_stack)->prev = r->prev;
+ EG(vm_stack)->prev = r->prev;
efree(r);
}
@@ -1803,10 +1750,10 @@ static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call,
}
/* }}} */
-static zend_always_inline void zend_vm_stack_extend_call_frame(zend_execute_data **call, zend_uint passed_args, zend_uint additional_args TSRMLS_DC) /* {{{ */
+static zend_always_inline void zend_vm_stack_extend_call_frame(zend_execute_data **call, uint32_t passed_args, uint32_t additional_args TSRMLS_DC) /* {{{ */
{
- if (EXPECTED(EG(argument_stack)->end - EG(argument_stack)->top > additional_args)) {
- EG(argument_stack)->top += additional_args;
+ if (EXPECTED(EG(vm_stack_end) - EG(vm_stack_top) > additional_args)) {
+ EG(vm_stack_top) += additional_args;
} else {
*call = zend_vm_stack_copy_call_frame(*call, passed_args, additional_args TSRMLS_CC);
}