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.c853
1 files changed, 428 insertions, 425 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 0cc255f8f7..c5a4a471c5 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -45,6 +45,46 @@
/* Virtual current working directory support */
#include "zend_virtual_cwd.h"
+#ifdef HAVE_GCC_GLOBAL_REGS
+# if defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(i386)
+# define ZEND_VM_FP_GLOBAL_REG "%esi"
+# define ZEND_VM_IP_GLOBAL_REG "%edi"
+# elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__x86_64__)
+# define ZEND_VM_FP_GLOBAL_REG "%r14"
+# define ZEND_VM_IP_GLOBAL_REG "%r15"
+# elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__powerpc64__)
+# define ZEND_VM_FP_GLOBAL_REG "r28"
+# define ZEND_VM_IP_GLOBAL_REG "r29"
+# elif defined(__IBMC__) && ZEND_GCC_VERSION >= 4002 && defined(__powerpc64__)
+# define ZEND_VM_FP_GLOBAL_REG "r28"
+# define ZEND_VM_IP_GLOBAL_REG "r29"
+# endif
+#endif
+
+#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
+# pragma GCC diagnostic ignored "-Wvolatile-register-var"
+ register zend_execute_data* volatile execute_data __asm__(ZEND_VM_FP_GLOBAL_REG);
+# pragma GCC diagnostic warning "-Wvolatile-register-var"
+# define EXECUTE_DATA_D void
+# define EXECUTE_DATA_C
+# define EXECUTE_DATA_DC
+# define EXECUTE_DATA_CC
+# define NO_EXECUTE_DATA_CC
+#else
+# define EXECUTE_DATA_D zend_execute_data* execute_data
+# define EXECUTE_DATA_C execute_data
+# define EXECUTE_DATA_DC , EXECUTE_DATA_D
+# define EXECUTE_DATA_CC , EXECUTE_DATA_C
+# define NO_EXECUTE_DATA_CC , NULL
+#endif
+
+#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
+# pragma GCC diagnostic ignored "-Wvolatile-register-var"
+ register const zend_op* volatile opline __asm__(ZEND_VM_IP_GLOBAL_REG);
+# pragma GCC diagnostic warning "-Wvolatile-register-var"
+#else
+#endif
+
#define _CONST_CODE 0
#define _TMP_CODE 1
#define _VAR_CODE 2
@@ -53,21 +93,16 @@
typedef int (ZEND_FASTCALL *incdec_t)(zval *);
-#define get_zval_ptr(op_type, node, ex, should_free, type) _get_zval_ptr(op_type, node, ex, should_free, type)
-#define get_zval_ptr_deref(op_type, node, ex, should_free, type) _get_zval_ptr_deref(op_type, node, ex, should_free, type)
-#define get_zval_ptr_r(op_type, node, ex, should_free) _get_zval_ptr_r(op_type, node, ex, should_free)
-#define get_zval_ptr_r_deref(op_type, node, ex, should_free) _get_zval_ptr_r_deref(op_type, node, ex, should_free)
-#define get_zval_ptr_undef(op_type, node, ex, should_free, type) _get_zval_ptr_undef(op_type, node, ex, should_free, type)
-#define get_zval_ptr_ptr(op_type, node, ex, should_free, type) _get_zval_ptr_ptr(op_type, node, ex, should_free, type)
-#define get_zval_ptr_ptr_undef(op_type, node, ex, should_free, type) _get_zval_ptr_ptr(op_type, node, ex, should_free, type)
-#define get_obj_zval_ptr(op_type, node, ex, should_free, type) _get_obj_zval_ptr(op_type, node, ex, should_free, type)
-#define get_obj_zval_ptr_undef(op_type, node, ex, should_free, type) _get_obj_zval_ptr_undef(op_type, node, ex, should_free, type)
-#define get_obj_zval_ptr_ptr(op_type, node, ex, should_free, type) _get_obj_zval_ptr_ptr(op_type, node, ex, should_free, type)
-
-/* Prototypes */
-static void zend_extension_statement_handler(const zend_extension *extension, zend_execute_data *frame);
-static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_execute_data *frame);
-static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_execute_data *frame);
+#define get_zval_ptr(op_type, node, should_free, type) _get_zval_ptr(op_type, node, should_free, type EXECUTE_DATA_CC)
+#define get_zval_ptr_deref(op_type, node, should_free, type) _get_zval_ptr_deref(op_type, node, should_free, type EXECUTE_DATA_CC)
+#define get_zval_ptr_r(op_type, node, should_free) _get_zval_ptr_r(op_type, node, should_free EXECUTE_DATA_CC)
+#define get_zval_ptr_r_deref(op_type, node, should_free) _get_zval_ptr_r_deref(op_type, node, should_free EXECUTE_DATA_CC)
+#define get_zval_ptr_undef(op_type, node, should_free, type) _get_zval_ptr_undef(op_type, node, should_free, type EXECUTE_DATA_CC)
+#define get_zval_ptr_ptr(op_type, node, should_free, type) _get_zval_ptr_ptr(op_type, node, should_free, type EXECUTE_DATA_CC)
+#define get_zval_ptr_ptr_undef(op_type, node, should_free, type) _get_zval_ptr_ptr(op_type, node, should_free, type EXECUTE_DATA_CC)
+#define get_obj_zval_ptr(op_type, node, should_free, type) _get_obj_zval_ptr(op_type, node, should_free, type EXECUTE_DATA_CC)
+#define get_obj_zval_ptr_undef(op_type, node, should_free, type) _get_obj_zval_ptr_undef(op_type, node, should_free, type EXECUTE_DATA_CC)
+#define get_obj_zval_ptr_ptr(op_type, node, should_free, type) _get_obj_zval_ptr_ptr(op_type, node, should_free, type EXECUTE_DATA_CC)
#define RETURN_VALUE_USED(opline) ((opline)->result_type != IS_UNUSED)
@@ -120,19 +155,16 @@ ZEND_API const zend_internal_function zend_pass_function = {
#define CV_DEF_OF(i) (EX(func)->op_array.vars[i])
-#define ZEND_VM_MAIN_STACK_PAGE_SLOTS (16 * 1024) /* should be a power of 2 */
-#define ZEND_VM_GENERATOR_STACK_PAGE_SLOTS (256)
+#define ZEND_VM_STACK_PAGE_SLOTS (16 * 1024) /* should be a power of 2 */
-#define ZEND_VM_STACK_PAGE_SLOTS(gen) ((gen) ? ZEND_VM_GENERATOR_STACK_PAGE_SLOTS : ZEND_VM_MAIN_STACK_PAGE_SLOTS)
+#define ZEND_VM_STACK_PAGE_SIZE (ZEND_VM_STACK_PAGE_SLOTS * sizeof(zval))
-#define ZEND_VM_STACK_PAGE_SIZE(gen) (ZEND_VM_STACK_PAGE_SLOTS(gen) * 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_FREE_PAGE_SIZE(gen) \
- ((ZEND_VM_STACK_PAGE_SLOTS(gen) - ZEND_VM_STACK_HEADER_SLOTS) * sizeof(zval))
-
-#define ZEND_VM_STACK_PAGE_ALIGNED_SIZE(gen, size) \
+#define ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size) \
(((size) + ZEND_VM_STACK_HEADER_SLOTS * sizeof(zval) \
- + (ZEND_VM_STACK_PAGE_SIZE(gen) - 1)) & ~(ZEND_VM_STACK_PAGE_SIZE(gen) - 1))
+ + (ZEND_VM_STACK_PAGE_SIZE - 1)) & ~(ZEND_VM_STACK_PAGE_SIZE - 1))
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);
@@ -145,7 +177,7 @@ static zend_always_inline zend_vm_stack zend_vm_stack_new_page(size_t size, zend
ZEND_API void zend_vm_stack_init(void)
{
- EG(vm_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE(0 /* main stack */), NULL);
+ 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;
@@ -170,8 +202,8 @@ ZEND_API void* zend_vm_stack_extend(size_t size)
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(0)) ?
- ZEND_VM_STACK_PAGE_SIZE(0) : ZEND_VM_STACK_PAGE_ALIGNED_SIZE(0, size),
+ 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);
@@ -184,7 +216,7 @@ 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)
+static zend_always_inline zval *_get_zval_ptr_tmp(uint32_t var, zend_free_op *should_free EXECUTE_DATA_DC)
{
zval *ret = EX_VAR(var);
*should_free = ret;
@@ -194,7 +226,7 @@ static zend_always_inline zval *_get_zval_ptr_tmp(uint32_t var, const zend_execu
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)
+static zend_always_inline zval *_get_zval_ptr_var(uint32_t var, zend_free_op *should_free EXECUTE_DATA_DC)
{
zval *ret = EX_VAR(var);
@@ -202,7 +234,7 @@ static zend_always_inline zval *_get_zval_ptr_var(uint32_t var, const zend_execu
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)
+static zend_always_inline zval *_get_zval_ptr_var_deref(uint32_t var, zend_free_op *should_free EXECUTE_DATA_DC)
{
zval *ret = EX_VAR(var);
@@ -211,25 +243,25 @@ static zend_always_inline zval *_get_zval_ptr_var_deref(uint32_t var, const zend
return ret;
}
-static zend_never_inline ZEND_COLD void zval_undefined_cv(uint32_t var, const zend_execute_data *execute_data)
+static zend_never_inline ZEND_COLD void zval_undefined_cv(uint32_t var EXECUTE_DATA_DC)
{
zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
zend_error(E_NOTICE, "Undefined variable: %s", ZSTR_VAL(cv));
}
-static zend_never_inline zval *_get_zval_cv_lookup(zval *ptr, uint32_t var, int type, const zend_execute_data *execute_data)
+static zend_never_inline zval *_get_zval_cv_lookup(zval *ptr, uint32_t var, int type EXECUTE_DATA_DC)
{
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
- zval_undefined_cv(var, execute_data);
+ zval_undefined_cv(var EXECUTE_DATA_CC);
/* break missing intentionally */
case BP_VAR_IS:
ptr = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
- zval_undefined_cv(var, execute_data);
+ zval_undefined_cv(var EXECUTE_DATA_CC);
/* break missing intentionally */
case BP_VAR_W:
ZVAL_NULL(ptr);
@@ -238,107 +270,107 @@ static zend_never_inline zval *_get_zval_cv_lookup(zval *ptr, uint32_t var, int
return ptr;
}
-static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, uint32_t var, const zend_execute_data *execute_data)
+static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, uint32_t var EXECUTE_DATA_DC)
{
- zval_undefined_cv(var, execute_data);
+ zval_undefined_cv(var EXECUTE_DATA_CC);
return &EG(uninitialized_zval);
}
-static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, uint32_t var, const zend_execute_data *execute_data)
+static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, uint32_t var EXECUTE_DATA_DC)
{
- zval_undefined_cv(var, execute_data);
+ zval_undefined_cv(var EXECUTE_DATA_CC);
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)
+static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_RW(zval *ptr, uint32_t var EXECUTE_DATA_DC)
{
ZVAL_NULL(ptr);
- zval_undefined_cv(var, execute_data);
+ zval_undefined_cv(var EXECUTE_DATA_CC);
return ptr;
}
-static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_W(zval *ptr, uint32_t var, const zend_execute_data *execute_data)
+static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_W(zval *ptr, uint32_t var EXECUTE_DATA_DC)
{
ZVAL_NULL(ptr);
return ptr;
}
-static zend_always_inline zval *_get_zval_ptr_cv(const zend_execute_data *execute_data, uint32_t var, int type)
+static zend_always_inline zval *_get_zval_ptr_cv(uint32_t var, int type EXECUTE_DATA_DC)
{
zval *ret = EX_VAR(var);
if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
- return _get_zval_cv_lookup(ret, var, type, execute_data);
+ return _get_zval_cv_lookup(ret, var, type EXECUTE_DATA_CC);
}
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_undef(const zend_execute_data *execute_data, uint32_t var)
+static zend_always_inline zval *_get_zval_ptr_cv_undef(uint32_t var EXECUTE_DATA_DC)
{
return EX_VAR(var);
}
-static zend_always_inline zval *_get_zval_ptr_cv_deref(const zend_execute_data *execute_data, uint32_t var, int type)
+static zend_always_inline zval *_get_zval_ptr_cv_deref(uint32_t var, int type EXECUTE_DATA_DC)
{
zval *ret = EX_VAR(var);
if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
- return _get_zval_cv_lookup(ret, var, type, execute_data);
+ return _get_zval_cv_lookup(ret, var, type EXECUTE_DATA_CC);
}
ZVAL_DEREF(ret);
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(const zend_execute_data *execute_data, uint32_t var)
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(uint32_t var EXECUTE_DATA_DC)
{
zval *ret = EX_VAR(var);
if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
- return _get_zval_cv_lookup_BP_VAR_R(ret, var, execute_data);
+ return _get_zval_cv_lookup_BP_VAR_R(ret, var EXECUTE_DATA_CC);
}
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_R(const zend_execute_data *execute_data, uint32_t var)
+static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_R(uint32_t var EXECUTE_DATA_DC)
{
zval *ret = EX_VAR(var);
if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
- return _get_zval_cv_lookup_BP_VAR_R(ret, var, execute_data);
+ return _get_zval_cv_lookup_BP_VAR_R(ret, var EXECUTE_DATA_CC);
}
ZVAL_DEREF(ret);
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(const zend_execute_data *execute_data, uint32_t var)
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(uint32_t var EXECUTE_DATA_DC)
{
zval *ret = EX_VAR(var);
if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
- return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var, execute_data);
+ return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var EXECUTE_DATA_CC);
}
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_UNSET(const zend_execute_data *execute_data, uint32_t var)
+static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_UNSET(uint32_t var EXECUTE_DATA_DC)
{
zval *ret = EX_VAR(var);
if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
- return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var, execute_data);
+ return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var EXECUTE_DATA_CC);
}
ZVAL_DEREF(ret);
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(const zend_execute_data *execute_data, uint32_t var)
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(uint32_t var EXECUTE_DATA_DC)
{
zval *ret = EX_VAR(var);
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_IS(const zend_execute_data *execute_data, uint32_t var)
+static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_IS(uint32_t var EXECUTE_DATA_DC)
{
zval *ret = EX_VAR(var);
@@ -346,169 +378,169 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_IS(const zend_exec
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(const zend_execute_data *execute_data, uint32_t var)
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(uint32_t var EXECUTE_DATA_DC)
{
zval *ret = EX_VAR(var);
if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
- return _get_zval_cv_lookup_BP_VAR_RW(ret, var, execute_data);
+ return _get_zval_cv_lookup_BP_VAR_RW(ret, var EXECUTE_DATA_CC);
}
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_RW(const zend_execute_data *execute_data, uint32_t var)
+static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_RW(uint32_t var EXECUTE_DATA_DC)
{
zval *ret = EX_VAR(var);
if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
- return _get_zval_cv_lookup_BP_VAR_RW(ret, var, execute_data);
+ return _get_zval_cv_lookup_BP_VAR_RW(ret, var EXECUTE_DATA_CC);
}
ZVAL_DEREF(ret);
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var)
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(uint32_t var EXECUTE_DATA_DC)
{
zval *ret = EX_VAR(var);
if (Z_TYPE_P(ret) == IS_UNDEF) {
- return _get_zval_cv_lookup_BP_VAR_W(ret, var, execute_data);
+ return _get_zval_cv_lookup_BP_VAR_W(ret, var EXECUTE_DATA_CC);
}
return ret;
}
-static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var)
+static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_W(uint32_t var EXECUTE_DATA_DC)
{
return EX_VAR(var);
}
-static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_RW(const zend_execute_data *execute_data, uint32_t var)
+static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_RW(uint32_t var EXECUTE_DATA_DC)
{
return EX_VAR(var);
}
-static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_UNSET(const zend_execute_data *execute_data, uint32_t var)
+static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_UNSET(uint32_t var EXECUTE_DATA_DC)
{
return EX_VAR(var);
}
-static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var)
+static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_W(uint32_t var EXECUTE_DATA_DC)
{
zval *ret = EX_VAR(var);
if (Z_TYPE_P(ret) == IS_UNDEF) {
- return _get_zval_cv_lookup_BP_VAR_W(ret, var, execute_data);
+ return _get_zval_cv_lookup_BP_VAR_W(ret, var EXECUTE_DATA_CC);
}
ZVAL_DEREF(ret);
return ret;
}
-static zend_always_inline zval *_get_zval_ptr(int op_type, znode_op node, const zend_execute_data *execute_data, zend_free_op *should_free, int type)
+static zend_always_inline zval *_get_zval_ptr(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC)
{
if (op_type & (IS_TMP_VAR|IS_VAR)) {
if (op_type == IS_TMP_VAR) {
- return _get_zval_ptr_tmp(node.var, execute_data, should_free);
+ return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC);
} else {
ZEND_ASSERT(op_type == IS_VAR);
- return _get_zval_ptr_var(node.var, execute_data, should_free);
+ return _get_zval_ptr_var(node.var, should_free EXECUTE_DATA_CC);
}
} else {
*should_free = NULL;
if (op_type == IS_CONST) {
return EX_CONSTANT(node);
} else if (op_type == IS_CV) {
- return _get_zval_ptr_cv(execute_data, node.var, type);
+ return _get_zval_ptr_cv(node.var, type EXECUTE_DATA_CC);
} else {
return NULL;
}
}
}
-static zend_always_inline zval *_get_zval_ptr_r(int op_type, znode_op node, const zend_execute_data *execute_data, zend_free_op *should_free)
+static zend_always_inline zval *_get_zval_ptr_r(int op_type, znode_op node, zend_free_op *should_free EXECUTE_DATA_DC)
{
if (op_type & (IS_TMP_VAR|IS_VAR)) {
if (op_type == IS_TMP_VAR) {
- return _get_zval_ptr_tmp(node.var, execute_data, should_free);
+ return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC);
} else {
ZEND_ASSERT(op_type == IS_VAR);
- return _get_zval_ptr_var(node.var, execute_data, should_free);
+ return _get_zval_ptr_var(node.var, should_free EXECUTE_DATA_CC);
}
} else {
*should_free = NULL;
if (op_type == IS_CONST) {
return EX_CONSTANT(node);
} else if (op_type == IS_CV) {
- return _get_zval_ptr_cv_BP_VAR_R(execute_data, node.var);
+ return _get_zval_ptr_cv_BP_VAR_R(node.var EXECUTE_DATA_CC);
} else {
return NULL;
}
}
}
-static zend_always_inline zval *_get_zval_ptr_deref(int op_type, znode_op node, const zend_execute_data *execute_data, zend_free_op *should_free, int type)
+static zend_always_inline zval *_get_zval_ptr_deref(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC)
{
if (op_type & (IS_TMP_VAR|IS_VAR)) {
if (op_type == IS_TMP_VAR) {
- return _get_zval_ptr_tmp(node.var, execute_data, should_free);
+ return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC);
} else {
ZEND_ASSERT(op_type == IS_VAR);
- return _get_zval_ptr_var_deref(node.var, execute_data, should_free);
+ return _get_zval_ptr_var_deref(node.var, should_free EXECUTE_DATA_CC);
}
} else {
*should_free = NULL;
if (op_type == IS_CONST) {
return EX_CONSTANT(node);
} else if (op_type == IS_CV) {
- return _get_zval_ptr_cv_deref(execute_data, node.var, type);
+ return _get_zval_ptr_cv_deref(node.var, type EXECUTE_DATA_CC);
} else {
return NULL;
}
}
}
-static zend_always_inline zval *_get_zval_ptr_r_deref(int op_type, znode_op node, const zend_execute_data *execute_data, zend_free_op *should_free)
+static zend_always_inline zval *_get_zval_ptr_r_deref(int op_type, znode_op node, zend_free_op *should_free EXECUTE_DATA_DC)
{
if (op_type & (IS_TMP_VAR|IS_VAR)) {
if (op_type == IS_TMP_VAR) {
- return _get_zval_ptr_tmp(node.var, execute_data, should_free);
+ return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC);
} else {
ZEND_ASSERT(op_type == IS_VAR);
- return _get_zval_ptr_var_deref(node.var, execute_data, should_free);
+ return _get_zval_ptr_var_deref(node.var, should_free EXECUTE_DATA_CC);
}
} else {
*should_free = NULL;
if (op_type == IS_CONST) {
return EX_CONSTANT(node);
} else if (op_type == IS_CV) {
- return _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, node.var);
+ return _get_zval_ptr_cv_deref_BP_VAR_R(node.var EXECUTE_DATA_CC);
} else {
return NULL;
}
}
}
-static zend_always_inline zval *_get_zval_ptr_undef(int op_type, znode_op node, const zend_execute_data *execute_data, zend_free_op *should_free, int type)
+static zend_always_inline zval *_get_zval_ptr_undef(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC)
{
if (op_type & (IS_TMP_VAR|IS_VAR)) {
if (op_type == IS_TMP_VAR) {
- return _get_zval_ptr_tmp(node.var, execute_data, should_free);
+ return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC);
} else {
ZEND_ASSERT(op_type == IS_VAR);
- return _get_zval_ptr_var(node.var, execute_data, should_free);
+ return _get_zval_ptr_var(node.var, should_free EXECUTE_DATA_CC);
}
} else {
*should_free = NULL;
if (op_type == IS_CONST) {
return EX_CONSTANT(node);
} else if (op_type == IS_CV) {
- return _get_zval_ptr_cv_undef(execute_data, node.var);
+ return _get_zval_ptr_cv_undef(node.var EXECUTE_DATA_CC);
} else {
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)
+static zend_always_inline zval *_get_zval_ptr_ptr_var(uint32_t var, zend_free_op *should_free EXECUTE_DATA_DC)
{
zval *ret = EX_VAR(var);
@@ -521,47 +553,47 @@ static zend_always_inline zval *_get_zval_ptr_ptr_var(uint32_t var, const zend_e
return ret;
}
-static inline zval *_get_zval_ptr_ptr(int op_type, znode_op node, const zend_execute_data *execute_data, zend_free_op *should_free, int type)
+static inline zval *_get_zval_ptr_ptr(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC)
{
if (op_type == IS_CV) {
*should_free = NULL;
- return _get_zval_ptr_cv(execute_data, node.var, type);
+ return _get_zval_ptr_cv(node.var, type EXECUTE_DATA_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);
+ return _get_zval_ptr_ptr_var(node.var, should_free EXECUTE_DATA_CC);
}
}
-static zend_always_inline zval *_get_obj_zval_ptr_unused(zend_execute_data *execute_data)
+static zend_always_inline zval *_get_obj_zval_ptr_unused(EXECUTE_DATA_D)
{
return &EX(This);
}
-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)
+static inline zval *_get_obj_zval_ptr(int op_type, znode_op op, zend_free_op *should_free, int type EXECUTE_DATA_DC)
{
if (op_type == IS_UNUSED) {
*should_free = NULL;
return &EX(This);
}
- return get_zval_ptr(op_type, op, execute_data, should_free, type);
+ return get_zval_ptr(op_type, op, should_free, type);
}
-static inline zval *_get_obj_zval_ptr_undef(int op_type, znode_op op, zend_execute_data *execute_data, zend_free_op *should_free, int type)
+static inline zval *_get_obj_zval_ptr_undef(int op_type, znode_op op, zend_free_op *should_free, int type EXECUTE_DATA_DC)
{
if (op_type == IS_UNUSED) {
*should_free = NULL;
return &EX(This);
}
- return get_zval_ptr_undef(op_type, op, execute_data, should_free, type);
+ return get_zval_ptr_undef(op_type, op, should_free, type);
}
-static inline zval *_get_obj_zval_ptr_ptr(int op_type, znode_op node, zend_execute_data *execute_data, zend_free_op *should_free, int type)
+static inline zval *_get_obj_zval_ptr_ptr(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC)
{
if (op_type == IS_UNUSED) {
*should_free = NULL;
return &EX(This);
}
- return get_zval_ptr_ptr(op_type, node, execute_data, should_free, type);
+ return get_zval_ptr_ptr(op_type, node, should_free, type);
}
static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr)
@@ -584,7 +616,7 @@ static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *v
zval_dtor_func(garbage);
return;
} else {
- GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
+ gc_check_possible_root(garbage);
}
}
ZVAL_REF(variable_ptr, ref);
@@ -607,25 +639,6 @@ static inline int make_real_object(zval *object)
return 1;
}
-static zend_class_entry *zend_verify_internal_arg_class_kind(
- const zend_internal_arg_info *cur_arg_info)
-{
- zend_string *key;
- zend_class_entry *ce;
- ALLOCA_FLAG(use_heap);
-
- ZSTR_ALLOCA_INIT(key, cur_arg_info->class_name, strlen(cur_arg_info->class_name), use_heap);
- ce = zend_fetch_class(key, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
- ZSTR_ALLOCA_FREE(key, use_heap);
-
- return ce;
-}
-
-static zend_always_inline zend_class_entry* zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info)
-{
- return zend_fetch_class(cur_arg_info->class_name, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
-}
-
static ZEND_COLD void zend_verify_type_error_common(
const zend_function *zf, const zend_arg_info *arg_info,
const zend_class_entry *ce, zval *value,
@@ -635,7 +648,6 @@ static ZEND_COLD void zend_verify_type_error_common(
{
zend_bool is_interface = 0;
*fname = ZSTR_VAL(zf->common.function_name);
-
if (zf->common.scope) {
*fsep = "::";
*fclass = ZSTR_VAL(zf->common.scope->name);
@@ -644,46 +656,50 @@ static ZEND_COLD void zend_verify_type_error_common(
*fclass = "";
}
- switch (arg_info->type_hint) {
- case IS_OBJECT:
- if (ce) {
- if (ce->ce_flags & ZEND_ACC_INTERFACE) {
- *need_msg = "implement interface ";
- is_interface = 1;
- } else {
- *need_msg = "be an instance of ";
- }
- *need_kind = ZSTR_VAL(ce->name);
+ if (ZEND_TYPE_IS_CLASS(arg_info->type)) {
+ if (ce) {
+ if (ce->ce_flags & ZEND_ACC_INTERFACE) {
+ *need_msg = "implement interface ";
+ is_interface = 1;
} else {
- /* We don't know whether it's a class or interface, assume it's a class */
*need_msg = "be an instance of ";
- *need_kind = zf->common.type == ZEND_INTERNAL_FUNCTION
- ? ((zend_internal_arg_info *) arg_info)->class_name
- : ZSTR_VAL(arg_info->class_name);
}
- break;
- case IS_CALLABLE:
- *need_msg = "be callable";
- *need_kind = "";
- break;
- case IS_ITERABLE:
- *need_msg = "be iterable";
- *need_kind = "";
- break;
- default:
- *need_msg = "be of the type ";
- *need_kind = zend_get_type_by_const(arg_info->type_hint);
- break;
+ *need_kind = ZSTR_VAL(ce->name);
+ } else {
+ /* We don't know whether it's a class or interface, assume it's a class */
+
+ *need_msg = "be an instance of ";
+ *need_kind = ZSTR_VAL(ZEND_TYPE_NAME(arg_info->type));
+ }
+ } else {
+ switch (ZEND_TYPE_CODE(arg_info->type)) {
+ case IS_OBJECT:
+ *need_msg = "be an ";
+ *need_kind = "object";
+ break;
+ case IS_CALLABLE:
+ *need_msg = "be callable";
+ *need_kind = "";
+ break;
+ case IS_ITERABLE:
+ *need_msg = "be iterable";
+ *need_kind = "";
+ break;
+ default:
+ *need_msg = "be of the type ";
+ *need_kind = zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type));
+ break;
+ }
}
- if (arg_info->allow_null) {
+ if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) {
*need_or_null = is_interface ? " or be null" : " or null";
} else {
*need_or_null = "";
}
if (value) {
- if (arg_info->type_hint == IS_OBJECT && Z_TYPE_P(value) == IS_OBJECT) {
+ if (ZEND_TYPE_IS_CLASS(arg_info->type) && Z_TYPE_P(value) == IS_OBJECT) {
*given_msg = "instance of ";
*given_kind = ZSTR_VAL(Z_OBJCE_P(value)->name);
} else {
@@ -803,137 +819,48 @@ static zend_bool zend_verify_scalar_type_hint(zend_uchar type_hint, zval *arg, z
return zend_verify_weak_scalar_type_hint(type_hint, arg);
}
-static zend_always_inline zend_bool zend_check_internal_type(
- const zend_function *zf, const zend_internal_arg_info *arg_info,
- zval *arg, zend_class_entry **ce, zend_bool is_return_type)
-{
- if (!arg_info->type_hint) {
- return 1;
- }
-
- ZVAL_DEREF(arg);
- if (EXPECTED(arg_info->type_hint == Z_TYPE_P(arg))) {
- if (arg_info->class_name) {
- *ce = zend_verify_internal_arg_class_kind(arg_info);
- return *ce && instanceof_function(Z_OBJCE_P(arg), *ce);
- }
- return 1;
- }
-
- if (Z_TYPE_P(arg) == IS_NULL && arg_info->allow_null) {
- return 1;
- }
-
- if (arg_info->class_name) {
- *ce = zend_verify_internal_arg_class_kind(arg_info);
- return 0;
- } else if (arg_info->type_hint == IS_CALLABLE) {
- return zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL);
- } else if (arg_info->type_hint == IS_ITERABLE) {
- return zend_is_iterable(arg);
- } else if (arg_info->type_hint == _IS_BOOL &&
- EXPECTED(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE)) {
- return 1;
- } else if (is_return_type) {
- /* Internal return types are always strict */
- return 0;
- } else {
- /* Internal parameter types honor strict_types */
- return zend_verify_scalar_type_hint(arg_info->type_hint, arg, ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data)));
- }
-}
-
-static int zend_verify_internal_arg_type(zend_function *zf, uint32_t arg_num, zval *arg)
-{
- const zend_internal_arg_info *cur_arg_info;
- zend_class_entry *ce = NULL;
-
- if (EXPECTED(arg_num <= zf->internal_function.num_args)) {
- cur_arg_info = &zf->internal_function.arg_info[arg_num-1];
- } else if (zf->internal_function.fn_flags & ZEND_ACC_VARIADIC) {
- cur_arg_info = &zf->internal_function.arg_info[zf->internal_function.num_args];
- } else {
- return 1;
- }
-
- if (UNEXPECTED(!zend_check_internal_type(zf, cur_arg_info, arg, &ce, 0))) {
- zend_verify_arg_error(zf, (const zend_arg_info *) cur_arg_info, arg_num, ce, arg);
- return 0;
- }
-
- return 1;
-}
-
-static zend_never_inline int zend_verify_internal_arg_types(zend_function *fbc, zend_execute_data *call)
-{
- uint32_t i;
- uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
- zval *p = ZEND_CALL_ARG(call, 1);
-
- for (i = 0; i < num_args; ++i) {
- if (UNEXPECTED(!zend_verify_internal_arg_type(fbc, i + 1, p))) {
- EG(current_execute_data) = call->prev_execute_data;
- zend_vm_stack_free_args(call);
- return 0;
- }
- p++;
- }
- return 1;
-}
-
static zend_always_inline zend_bool zend_check_type(
- const zend_function *zf, const zend_arg_info *arg_info,
+ zend_type type,
zval *arg, zend_class_entry **ce, void **cache_slot,
- zval *default_value, zend_bool is_return_type)
+ zval *default_value, zend_class_entry *scope,
+ zend_bool is_return_type)
{
- if (!arg_info->type_hint) {
+ if (!ZEND_TYPE_IS_SET(type)) {
return 1;
}
ZVAL_DEREF(arg);
- if (EXPECTED(arg_info->type_hint == Z_TYPE_P(arg))) {
- if (arg_info->class_name) {
- if (EXPECTED(*cache_slot)) {
- *ce = (zend_class_entry *) *cache_slot;
- } else {
- *ce = zend_verify_arg_class_kind(arg_info);
- if (UNEXPECTED(!*ce)) {
- return 0;
- }
- *cache_slot = (void *) *ce;
- }
- if (UNEXPECTED(!instanceof_function(Z_OBJCE_P(arg), *ce))) {
- return 0;
+ if (ZEND_TYPE_IS_CLASS(type)) {
+ if (EXPECTED(*cache_slot)) {
+ *ce = (zend_class_entry *) *cache_slot;
+ } else {
+ *ce = zend_fetch_class(ZEND_TYPE_NAME(type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
+ if (UNEXPECTED(!*ce)) {
+ return Z_TYPE_P(arg) == IS_NULL && (ZEND_TYPE_ALLOW_NULL(type) || (default_value && is_null_constant(scope, default_value)));
}
+ *cache_slot = (void *) *ce;
}
+ if (EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
+ return instanceof_function(Z_OBJCE_P(arg), *ce);
+ }
+ } else if (EXPECTED(ZEND_TYPE_CODE(type) == Z_TYPE_P(arg))) {
return 1;
}
- if (Z_TYPE_P(arg) == IS_NULL && (arg_info->allow_null || (default_value && is_null_constant(zf->common.scope, default_value)))) {
+ if (Z_TYPE_P(arg) == IS_NULL && (ZEND_TYPE_ALLOW_NULL(type) || (default_value && is_null_constant(scope, default_value)))) {
/* Null passed to nullable type */
return 1;
}
- if (UNEXPECTED(arg_info->class_name)) {
- /* This is always an error - we fetch the class name for the error message here */
- if (EXPECTED(*cache_slot)) {
- *ce = (zend_class_entry *) *cache_slot;
- } else {
- *ce = zend_verify_arg_class_kind(arg_info);
- if (*ce) {
- *cache_slot = (void *) *ce;
- }
- }
- return 0;
- } else if (arg_info->type_hint == IS_CALLABLE) {
+ if (ZEND_TYPE_CODE(type) == IS_CALLABLE) {
return zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL);
- } else if (arg_info->type_hint == IS_ITERABLE) {
+ } else if (ZEND_TYPE_CODE(type) == IS_ITERABLE) {
return zend_is_iterable(arg);
- } else if (arg_info->type_hint == _IS_BOOL &&
+ } else if (ZEND_TYPE_CODE(type) == _IS_BOOL &&
EXPECTED(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE)) {
return 1;
} else {
- return zend_verify_scalar_type_hint(arg_info->type_hint, arg,
+ return zend_verify_scalar_type_hint(ZEND_TYPE_CODE(type), arg,
is_return_type ? ZEND_RET_USES_STRICT_TYPES() : ZEND_ARG_USES_STRICT_TYPES());
}
@@ -954,7 +881,7 @@ static zend_always_inline int zend_verify_arg_type(zend_function *zf, uint32_t a
return 1;
}
- if (UNEXPECTED(!zend_check_type(zf, cur_arg_info, arg, &ce, cache_slot, default_value, 0))) {
+ if (UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, &ce, cache_slot, default_value, zf->common.scope, 0))) {
zend_verify_arg_error(zf, cur_arg_info, arg_num, ce, arg);
return 0;
}
@@ -962,6 +889,25 @@ static zend_always_inline int zend_verify_arg_type(zend_function *zf, uint32_t a
return 1;
}
+static zend_never_inline int zend_verify_internal_arg_types(zend_function *fbc, zend_execute_data *call)
+{
+ uint32_t i;
+ uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
+ zval *p = ZEND_CALL_ARG(call, 1);
+ void *dummy_cache_slot;
+
+ for (i = 0; i < num_args; ++i) {
+ dummy_cache_slot = NULL;
+ if (UNEXPECTED(!zend_verify_arg_type(fbc, i + 1, p, NULL, &dummy_cache_slot))) {
+ EG(current_execute_data) = call->prev_execute_data;
+ zend_vm_stack_free_args(call);
+ return 0;
+ }
+ p++;
+ }
+ return 1;
+}
+
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_missing_arg_error(zend_execute_data *execute_data)
{
zend_execute_data *ptr = EX(prev_execute_data);
@@ -1040,13 +986,14 @@ static int zend_verify_internal_return_type(zend_function *zf, zval *ret)
{
zend_internal_arg_info *ret_info = zf->internal_function.arg_info - 1;
zend_class_entry *ce = NULL;
+ void *dummy_cache_slot = NULL;
- if (UNEXPECTED(ret_info->type_hint == IS_VOID && Z_TYPE_P(ret) != IS_NULL)) {
+ if (UNEXPECTED(ZEND_TYPE_CODE(ret_info->type) == IS_VOID && Z_TYPE_P(ret) != IS_NULL)) {
zend_verify_void_return_error(zf, zend_zval_type_name(ret), "");
return 0;
}
- if (UNEXPECTED(!zend_check_internal_type(zf, ret_info, ret, &ce, 1))) {
+ if (UNEXPECTED(!zend_check_type(ret_info->type, ret, &ce, &dummy_cache_slot, NULL, NULL, 1))) {
zend_verify_internal_return_error(zf, ce, ret);
return 0;
}
@@ -1060,7 +1007,7 @@ static zend_always_inline void zend_verify_return_type(zend_function *zf, zval *
zend_arg_info *ret_info = zf->common.arg_info - 1;
zend_class_entry *ce = NULL;
- if (UNEXPECTED(!zend_check_type(zf, ret_info, ret, &ce, cache_slot, NULL, 1))) {
+ if (UNEXPECTED(!zend_check_type(ret_info->type, ret, &ce, cache_slot, NULL, NULL, 1))) {
zend_verify_return_error(zf, ce, ret);
}
}
@@ -1069,13 +1016,13 @@ static ZEND_COLD int zend_verify_missing_return_type(zend_function *zf, void **c
{
zend_arg_info *ret_info = zf->common.arg_info - 1;
- if (ret_info->type_hint && UNEXPECTED(ret_info->type_hint != IS_VOID)) {
+ if (ZEND_TYPE_IS_SET(ret_info->type) && UNEXPECTED(ZEND_TYPE_CODE(ret_info->type) != IS_VOID)) {
zend_class_entry *ce = NULL;
- if (ret_info->class_name) {
+ if (ZEND_TYPE_IS_CLASS(ret_info->type)) {
if (EXPECTED(*cache_slot)) {
ce = (zend_class_entry*) *cache_slot;
} else {
- ce = zend_verify_arg_class_kind(ret_info);
+ ce = zend_fetch_class(ZEND_TYPE_NAME(ret_info->type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
if (ce) {
*cache_slot = (void*)ce;
}
@@ -1097,7 +1044,7 @@ static zend_never_inline void zend_assign_to_object_dim(zval *object, zval *dim,
Z_OBJ_HT_P(object)->write_dimension(object, dim, value);
}
-static zend_never_inline void zend_binary_assign_op_obj_dim(zval *object, zval *property, zval *value, zval *retval, binary_op_type binary_op)
+static zend_never_inline void zend_binary_assign_op_obj_dim(zval *object, zval *property, zval *value, zval *retval, binary_op_type binary_op EXECUTE_DATA_DC)
{
zval *z;
zval rv, res;
@@ -1131,7 +1078,7 @@ static zend_never_inline void zend_binary_assign_op_obj_dim(zval *object, zval *
}
}
-static zend_never_inline zend_long zend_check_string_offset(zval *dim, int type)
+static zend_never_inline zend_long zend_check_string_offset(zval *dim, int type EXECUTE_DATA_DC)
{
zend_long offset;
@@ -1147,7 +1094,7 @@ try_again:
}
break;
case IS_UNDEF:
- zval_undefined_cv(EG(current_execute_data)->opline->op2.var, EG(current_execute_data));
+ zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
case IS_DOUBLE:
case IS_NULL:
case IS_FALSE:
@@ -1170,10 +1117,10 @@ try_again:
return offset;
}
-static zend_never_inline ZEND_COLD void zend_wrong_string_offset(void)
+static zend_never_inline ZEND_COLD void zend_wrong_string_offset(EXECUTE_DATA_D)
{
const char *msg = NULL;
- const zend_op *opline = EG(current_execute_data)->opline;
+ const zend_op *opline = EX(opline);
const zend_op *end;
uint32_t var;
@@ -1289,15 +1236,15 @@ static zend_never_inline ZEND_COLD void zend_wrong_string_offset(void)
zend_throw_error(NULL, msg);
}
-static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim, zval *value, zval *result)
+static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim, zval *value, zval *result EXECUTE_DATA_DC)
{
zend_string *old_str;
zend_uchar c;
size_t string_len;
zend_long offset;
- offset = zend_check_string_offset(dim, BP_VAR_W);
- if (offset < (zend_long)(-Z_STRLEN_P(str))) {
+ offset = zend_check_string_offset(dim, BP_VAR_W EXECUTE_DATA_CC);
+ if (offset < -(zend_long)Z_STRLEN_P(str)) {
/* Error on negative offset */
zend_error(E_WARNING, "Illegal string offset: " ZEND_LONG_FMT, offset);
if (result) {
@@ -1352,11 +1299,7 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
if (result) {
/* Return the new character */
- if (CG(one_char_string)[c]) {
- ZVAL_INTERNED_STR(result, CG(one_char_string)[c]);
- } else {
- ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(str) + offset, 1, 0));
- }
+ ZVAL_INTERNED_STR(result, ZSTR_CHAR(c));
}
}
@@ -1372,6 +1315,7 @@ static zend_never_inline void zend_post_incdec_overloaded_property(zval *object,
z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
if (UNEXPECTED(EG(exception))) {
OBJ_RELEASE(Z_OBJ(obj));
+ ZVAL_UNDEF(result);
return;
}
@@ -1417,6 +1361,9 @@ static zend_never_inline void zend_pre_incdec_overloaded_property(zval *object,
zptr = z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
if (UNEXPECTED(EG(exception))) {
OBJ_RELEASE(Z_OBJ(obj));
+ if (result) {
+ ZVAL_UNDEF(result);
+ }
return;
}
@@ -1462,6 +1409,9 @@ static zend_never_inline void zend_assign_op_overloaded_property(zval *object, z
z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
if (UNEXPECTED(EG(exception))) {
OBJ_RELEASE(Z_OBJ(obj));
+ if (result) {
+ ZVAL_UNDEF(result);
+ }
return;
}
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
@@ -1516,7 +1466,7 @@ static void zend_extension_fcall_end_handler(const zend_extension *extension, ze
}
-static zend_always_inline HashTable *zend_get_target_symbol_table(zend_execute_data *execute_data, int fetch_type)
+static zend_always_inline HashTable *zend_get_target_symbol_table(int fetch_type EXECUTE_DATA_DC)
{
HashTable *ht;
@@ -1533,7 +1483,7 @@ static zend_always_inline HashTable *zend_get_target_symbol_table(zend_execute_d
return ht;
}
-static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int dim_type, int type)
+static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int dim_type, int type EXECUTE_DATA_DC)
{
zval *retval;
zend_string *offset_key;
@@ -1614,7 +1564,7 @@ str_index:
} else {
switch (Z_TYPE_P(dim)) {
case IS_UNDEF:
- zval_undefined_cv(EG(current_execute_data)->opline->op2.var, EG(current_execute_data));
+ zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
/* break missing intentionally */
case IS_NULL:
offset_key = ZSTR_EMPTY_ALLOC();
@@ -1644,27 +1594,27 @@ str_index:
return retval;
}
-static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_W(HashTable *ht, const zval *dim)
+static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_W(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
{
- return zend_fetch_dimension_address_inner(ht, dim, IS_TMP_VAR, BP_VAR_W);
+ return zend_fetch_dimension_address_inner(ht, dim, IS_TMP_VAR, BP_VAR_W EXECUTE_DATA_CC);
}
-static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_W_CONST(HashTable *ht, const zval *dim)
+static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_W_CONST(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
{
- return zend_fetch_dimension_address_inner(ht, dim, IS_CONST, BP_VAR_W);
+ return zend_fetch_dimension_address_inner(ht, dim, IS_CONST, BP_VAR_W EXECUTE_DATA_CC);
}
-static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_RW(HashTable *ht, const zval *dim)
+static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_RW(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
{
- return zend_fetch_dimension_address_inner(ht, dim, IS_TMP_VAR, BP_VAR_RW);
+ return zend_fetch_dimension_address_inner(ht, dim, IS_TMP_VAR, BP_VAR_RW EXECUTE_DATA_CC);
}
-static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_RW_CONST(HashTable *ht, const zval *dim)
+static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_RW_CONST(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
{
- return zend_fetch_dimension_address_inner(ht, dim, IS_CONST, BP_VAR_RW);
+ return zend_fetch_dimension_address_inner(ht, dim, IS_CONST, BP_VAR_RW EXECUTE_DATA_CC);
}
-static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *container, zval *dim, int dim_type, int type)
+static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *container, zval *dim, int dim_type, int type EXECUTE_DATA_DC)
{
zval *retval;
@@ -1680,7 +1630,7 @@ fetch_from_array:
return;
}
} else {
- retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type);
+ retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type EXECUTE_DATA_CC);
if (UNEXPECTED(!retval)) {
ZVAL_ERROR(result);
return;
@@ -1698,13 +1648,13 @@ fetch_from_array:
if (dim == NULL) {
zend_throw_error(NULL, "[] operator not supported for strings");
} else {
- zend_check_string_offset(dim, type);
- zend_wrong_string_offset();
+ zend_check_string_offset(dim, type EXECUTE_DATA_CC);
+ zend_wrong_string_offset(EXECUTE_DATA_C);
}
ZVAL_ERROR(result);
} else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (/*dim_type == IS_CV &&*/ dim && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
- zval_undefined_cv(EG(current_execute_data)->opline->op2.var, EG(current_execute_data));
+ zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
dim = &EG(uninitialized_zval);
}
if (!Z_OBJ_HT_P(container)->read_dimension) {
@@ -1740,10 +1690,10 @@ fetch_from_array:
}
} else {
if (type != BP_VAR_W && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
- zval_undefined_cv(EG(current_execute_data)->opline->op1.var, EG(current_execute_data));
+ zval_undefined_cv(EX(opline)->op1.var EXECUTE_DATA_CC);
}
if (/*dim_type == IS_CV &&*/ dim && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
- zval_undefined_cv(EG(current_execute_data)->opline->op2.var, EG(current_execute_data));
+ zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
}
if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
if (type != BP_VAR_UNSET) {
@@ -1768,29 +1718,29 @@ fetch_from_array:
}
}
-static zend_never_inline void zend_fetch_dimension_address_W(zval *result, zval *container_ptr, zval *dim, int dim_type)
+static zend_never_inline void zend_fetch_dimension_address_W(zval *result, zval *container_ptr, zval *dim, int dim_type EXECUTE_DATA_DC)
{
- zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W);
+ zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W EXECUTE_DATA_CC);
}
-static zend_never_inline void zend_fetch_dimension_address_RW(zval *result, zval *container_ptr, zval *dim, int dim_type)
+static zend_never_inline void zend_fetch_dimension_address_RW(zval *result, zval *container_ptr, zval *dim, int dim_type EXECUTE_DATA_DC)
{
- zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW);
+ zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW EXECUTE_DATA_CC);
}
-static zend_never_inline void zend_fetch_dimension_address_UNSET(zval *result, zval *container_ptr, zval *dim, int dim_type)
+static zend_never_inline void zend_fetch_dimension_address_UNSET(zval *result, zval *container_ptr, zval *dim, int dim_type EXECUTE_DATA_DC)
{
- zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET);
+ zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET EXECUTE_DATA_CC);
}
-static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type, int support_strings, int slow)
+static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type, int support_strings, int slow EXECUTE_DATA_DC)
{
zval *retval;
if (!slow) {
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
try_array:
- retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type);
+ retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type EXECUTE_DATA_CC);
ZVAL_COPY(result, retval);
return;
} else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
@@ -1818,7 +1768,7 @@ try_string_offset:
zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim));
break;
case IS_UNDEF:
- zval_undefined_cv(EG(current_execute_data)->opline->op2.var, EG(current_execute_data));
+ zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
case IS_DOUBLE:
case IS_NULL:
case IS_FALSE:
@@ -1855,15 +1805,11 @@ try_string_offset:
? (zend_long)Z_STRLEN_P(container) + offset : offset;
c = (zend_uchar)Z_STRVAL_P(container)[real_offset];
- if (CG(one_char_string)[c]) {
- ZVAL_INTERNED_STR(result, CG(one_char_string)[c]);
- } else {
- ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(container) + real_offset, 1, 0));
- }
+ ZVAL_INTERNED_STR(result, ZSTR_CHAR(c));
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (/*dim_type == IS_CV &&*/ UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
- zval_undefined_cv(EG(current_execute_data)->opline->op2.var, EG(current_execute_data));
+ zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
dim = &EG(uninitialized_zval);
}
if (!Z_OBJ_HT_P(container)->read_dimension) {
@@ -1883,46 +1829,44 @@ try_string_offset:
}
} else {
if (type != BP_VAR_IS && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
- zval_undefined_cv(EG(current_execute_data)->opline->op1.var, EG(current_execute_data));
+ zval_undefined_cv(EX(opline)->op1.var EXECUTE_DATA_CC);
}
if (/*dim_type == IS_CV &&*/ UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
- zval_undefined_cv(EG(current_execute_data)->opline->op2.var, EG(current_execute_data));
+ zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
}
ZVAL_NULL(result);
}
}
-static zend_never_inline void zend_fetch_dimension_address_read_R(zval *result, zval *container, zval *dim, int dim_type)
-{
- zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_R, 1, 0);
-}
-
-static zend_never_inline void zend_fetch_dimension_address_read_R_slow(zval *result, zval *container, zval *dim)
+static zend_never_inline void zend_fetch_dimension_address_read_R(zval *result, zval *container, zval *dim, int dim_type EXECUTE_DATA_DC)
{
- zend_fetch_dimension_address_read(result, container, dim, IS_CV, BP_VAR_R, 1, 1);
+ zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_R, 1, 0 EXECUTE_DATA_CC);
}
-static zend_never_inline void zend_fetch_dimension_address_read_IS(zval *result, zval *container, zval *dim, int dim_type)
+static zend_never_inline void zend_fetch_dimension_address_read_R_slow(zval *result, zval *container, zval *dim EXECUTE_DATA_DC)
{
- zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS, 1, 0);
+ zend_fetch_dimension_address_read(result, container, dim, IS_CV, BP_VAR_R, 1, 1 EXECUTE_DATA_CC);
}
-static zend_never_inline void zend_fetch_dimension_address_read_LIST(zval *result, zval *container, zval *dim)
+static zend_never_inline void zend_fetch_dimension_address_read_IS(zval *result, zval *container, zval *dim, int dim_type EXECUTE_DATA_DC)
{
- zend_fetch_dimension_address_read(result, container, dim, IS_TMP_VAR, BP_VAR_R, 0, 0);
+ zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS, 1, 0 EXECUTE_DATA_CC);
}
-ZEND_API void zend_fetch_dimension_by_zval(zval *result, zval *container, zval *dim)
+static zend_never_inline void zend_fetch_dimension_address_read_LIST(zval *result, zval *container, zval *dim EXECUTE_DATA_DC)
{
- zend_fetch_dimension_address_read_R(result, container, dim, IS_TMP_VAR);
+ zend_fetch_dimension_address_read(result, container, dim, IS_TMP_VAR, BP_VAR_R, 0, 0 EXECUTE_DATA_CC);
}
-ZEND_API void zend_fetch_dimension_by_zval_is(zval *result, zval *container, zval *dim, int dim_type)
+ZEND_API void zend_fetch_dimension_const(zval *result, zval *container, zval *dim, int type)
{
- zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS, 1, 0);
+ if (type == BP_VAR_IS) {
+ zend_fetch_dimension_address_read_IS(result, container, dim, IS_CONST NO_EXECUTE_DATA_CC);
+ } else {
+ zend_fetch_dimension_address_read_R(result, container, dim, IS_CONST NO_EXECUTE_DATA_CC);
+ }
}
-
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)
{
if (container_op_type != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -2001,6 +1945,96 @@ use_read_property:
}
}
+static zend_always_inline zval* zend_fetch_static_property_address(zval *varname, zend_uchar varname_type, znode_op op2, zend_uchar op2_type, int type EXECUTE_DATA_DC)
+{
+ zval *retval;
+ zend_string *name;
+ zend_class_entry *ce;
+
+ if (varname_type == IS_CONST) {
+ name = Z_STR_P(varname);
+ } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
+ name = Z_STR_P(varname);
+ zend_string_addref(name);
+ } else {
+ if (varname_type == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
+ zval_undefined_cv(EX(opline)->op1.var EXECUTE_DATA_CC);
+ }
+ name = zval_get_string(varname);
+ }
+
+ if (op2_type == IS_CONST) {
+ if (varname_type == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(varname))) != NULL)) {
+ retval = CACHED_PTR(Z_CACHE_SLOT_P(varname) + sizeof(void*));
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ if (type != BP_VAR_IS) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+ }
+ return NULL;
+ }
+
+ return retval;
+ } else {
+ zval *class_name = EX_CONSTANT(op2);
+
+ if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(class_name))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(class_name), class_name + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if (varname_type != IS_CONST) {
+ zend_string_release(name);
+ }
+ return NULL;
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(class_name), ce);
+ }
+ }
+ } else {
+ if (op2_type == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ if (varname_type != IS_CONST) {
+ zend_string_release(name);
+ }
+ return NULL;
+ }
+ } else {
+ ce = Z_CE_P(EX_VAR(op2.var));
+ }
+ if (varname_type == IS_CONST &&
+ EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(varname)) == ce)) {
+ retval = CACHED_PTR(Z_CACHE_SLOT_P(varname) + sizeof(void*));
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ if (type != BP_VAR_IS) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+ }
+ return NULL;
+ }
+
+ return retval;
+ }
+ }
+
+ retval = zend_std_get_static_property(ce, name, type == BP_VAR_IS);
+
+ if (varname_type != IS_CONST) {
+ zend_string_release(name);
+ }
+
+ if (UNEXPECTED(retval == NULL)) {
+ return NULL;
+ }
+
+ if (varname_type == IS_CONST) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(varname), ce, retval);
+ }
+
+ return retval;
+}
+
#if ZEND_INTENSIVE_DEBUGGING
#define CHECK_SYMBOL_TABLES() \
@@ -2059,12 +2093,12 @@ static zend_always_inline void i_free_compiled_variables(zend_execute_data *exec
zval *end = cv + EX(func)->op_array.last_var;
while (EXPECTED(cv != end)) {
if (Z_REFCOUNTED_P(cv)) {
- if (!Z_DELREF_P(cv)) {
- zend_refcounted *r = Z_COUNTED_P(cv);
+ zend_refcounted *r = Z_COUNTED_P(cv);
+ if (!--GC_REFCOUNT(r)) {
ZVAL_NULL(cv);
zval_dtor_func(r);
} else {
- GC_ZVAL_CHECK_POSSIBLE_ROOT(cv);
+ gc_check_possible_root(r);
}
}
cv++;
@@ -2204,88 +2238,35 @@ 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) /* {{{ */
+ZEND_API void zend_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
{
- ZEND_ASSERT(EX(func) == (zend_function*)op_array);
-
- EX(opline) = op_array->opcodes;
- EX(call) = NULL;
- EX(return_value) = return_value;
-
- if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) {
- zend_attach_symbol_table(execute_data);
- } else {
- uint32_t first_extra_arg, num_args;
-
- /* Handle arguments */
- first_extra_arg = op_array->num_args;
- num_args = EX_NUM_ARGS();
- if (UNEXPECTED(num_args > first_extra_arg)) {
- if (EXPECTED(!(op_array->fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))) {
- zval *end, *src, *dst;
- uint32_t type_flags = 0;
-
- 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 {
- type_flags |= Z_TYPE_INFO_P(src);
- ZVAL_COPY_VALUE(dst, src);
- ZVAL_UNDEF(src);
- src--;
- dst--;
- } while (src != end);
- } else {
- do {
- type_flags |= Z_TYPE_INFO_P(src);
- src--;
- } while (src != end);
- }
- ZEND_ADD_CALL_FLAG(execute_data, ((type_flags >> Z_TYPE_FLAGS_SHIFT) & IS_TYPE_REFCOUNTED));
- }
- } 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((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);
- }
+ EX(prev_execute_data) = EG(current_execute_data);
+ if (!op_array->run_time_cache) {
+ op_array->run_time_cache = zend_arena_alloc(&CG(arena), op_array->cache_size);
+ memset(op_array->run_time_cache, 0, op_array->cache_size);
}
+ i_init_func_execute_data(execute_data, op_array, return_value);
+}
+/* }}} */
+ZEND_API void zend_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
+{
+ EX(prev_execute_data) = EG(current_execute_data);
if (!op_array->run_time_cache) {
- if (op_array->function_name) {
- op_array->run_time_cache = zend_arena_alloc(&CG(arena), op_array->cache_size);
- } else {
- op_array->run_time_cache = emalloc(op_array->cache_size);
- }
+ op_array->run_time_cache = emalloc(op_array->cache_size);
memset(op_array->run_time_cache, 0, op_array->cache_size);
}
- EX_LOAD_RUN_TIME_CACHE(op_array);
- EX_LOAD_LITERALS(op_array);
-
- EG(current_execute_data) = execute_data;
+ i_init_code_execute_data(execute_data, op_array, return_value);
}
/* }}} */
ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
{
- EX(prev_execute_data) = EG(current_execute_data);
- i_init_execute_data(execute_data, op_array, return_value);
+ if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) {
+ zend_init_code_execute_data(execute_data, op_array, return_value);
+ } else {
+ zend_init_func_execute_data(execute_data, op_array, return_value);
+ }
}
/* }}} */
@@ -2346,7 +2327,7 @@ static zend_always_inline void zend_vm_stack_extend_call_frame(zend_execute_data
}
/* }}} */
-static zend_always_inline zend_generator *zend_get_running_generator(zend_execute_data *execute_data) /* {{{ */
+static zend_always_inline zend_generator *zend_get_running_generator(EXECUTE_DATA_D) /* {{{ */
{
/* The generator object is stored in EX(return_value) */
zend_generator *generator = (zend_generator *) EX(return_value);
@@ -2655,6 +2636,9 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zval *
ZEND_ASSERT(GC_TYPE((zend_object*)fbc->common.prototype) == IS_OBJECT);
GC_REFCOUNT((zend_object*)fbc->common.prototype)++;
call_info |= ZEND_CALL_CLOSURE;
+ if (fbc->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
+ call_info |= ZEND_CALL_FAKE_CLOSURE;
+ }
} else if (object) {
call_info |= ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(object)++; /* For $this pointer */
@@ -2854,8 +2838,9 @@ already_compiled:
}
/* }}} */
-static zend_never_inline int zend_do_fcall_overloaded(zend_function *fbc, zend_execute_data *call, zval *ret) /* {{{ */
+ZEND_API int ZEND_FASTCALL zend_do_fcall_overloaded(zend_execute_data *call, zval *ret) /* {{{ */
{
+ zend_function *fbc = call->func;
zend_object *object;
/* Not sure what should be done here if it's a static method */
@@ -2890,22 +2875,6 @@ static zend_never_inline int zend_do_fcall_overloaded(zend_function *fbc, zend_e
}
/* }}} */
-#ifdef HAVE_GCC_GLOBAL_REGS
-# if defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(i386)
-# define ZEND_VM_FP_GLOBAL_REG "%esi"
-# define ZEND_VM_IP_GLOBAL_REG "%edi"
-# elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__x86_64__)
-# define ZEND_VM_FP_GLOBAL_REG "%r14"
-# define ZEND_VM_IP_GLOBAL_REG "%r15"
-# elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__powerpc64__)
-# define ZEND_VM_FP_GLOBAL_REG "r28"
-# define ZEND_VM_IP_GLOBAL_REG "r29"
-# elif defined(__IBMC__) && ZEND_GCC_VERSION >= 4002 && defined(__powerpc64__)
-# define ZEND_VM_FP_GLOBAL_REG "r28"
-# define ZEND_VM_IP_GLOBAL_REG "r29"
-# endif
-#endif
-
#define ZEND_VM_NEXT_OPCODE_EX(check_exception, skip) \
CHECK_SYMBOL_TABLES() \
if (check_exception) { \
@@ -2966,6 +2935,7 @@ static zend_never_inline int zend_do_fcall_overloaded(zend_function *fbc, zend_e
break; \
} \
if ((_check) && UNEXPECTED(EG(exception))) { \
+ ZVAL_UNDEF(EX_VAR(opline->result.var)); \
HANDLE_EXCEPTION(); \
} \
if (__result) { \
@@ -2977,6 +2947,7 @@ static zend_never_inline int zend_do_fcall_overloaded(zend_function *fbc, zend_e
} while (0)
# define ZEND_VM_SMART_BRANCH_JMPZ(_result, _check) do { \
if ((_check) && UNEXPECTED(EG(exception))) { \
+ ZVAL_UNDEF(EX_VAR(opline->result.var)); \
HANDLE_EXCEPTION(); \
} \
if (_result) { \
@@ -2988,6 +2959,7 @@ static zend_never_inline int zend_do_fcall_overloaded(zend_function *fbc, zend_e
} while (0)
# define ZEND_VM_SMART_BRANCH_JMPNZ(_result, _check) do { \
if ((_check) && UNEXPECTED(EG(exception))) { \
+ ZVAL_UNDEF(EX_VAR(opline->result.var)); \
HANDLE_EXCEPTION(); \
} \
if (!(_result)) { \
@@ -3012,9 +2984,15 @@ static zend_never_inline int zend_do_fcall_overloaded(zend_function *fbc, zend_e
#endif
#define GET_OP1_UNDEF_CV(ptr, type) \
- _get_zval_cv_lookup_ ## type(ptr, opline->op1.var, execute_data)
+ _get_zval_cv_lookup_ ## type(ptr, opline->op1.var EXECUTE_DATA_CC)
#define GET_OP2_UNDEF_CV(ptr, type) \
- _get_zval_cv_lookup_ ## type(ptr, opline->op2.var, execute_data)
+ _get_zval_cv_lookup_ ## type(ptr, opline->op2.var EXECUTE_DATA_CC)
+
+#define UNDEF_RESULT() do { \
+ if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { \
+ ZVAL_UNDEF(EX_VAR(opline->result.var)); \
+ } \
+ } while (0)
#include "zend_vm_execute.h"
@@ -3040,12 +3018,35 @@ ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode)
ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type)
{
- return get_zval_ptr(op_type, *node, execute_data, should_free, type);
+ zval *ret;
+
+ switch (op_type) {
+ case IS_CONST:
+ ret = EX_CONSTANT(*node);
+ *should_free = NULL;
+ break;
+ case IS_TMP_VAR:
+ case IS_VAR:
+ ret = EX_VAR(node->var);
+ *should_free = ret;
+ break;
+ case IS_CV:
+ ret = EX_VAR(node->var);
+ *should_free = NULL;
+ break;
+ default:
+ ret = NULL;
+ *should_free = ret;
+ break;
+ }
+ return ret;
}
ZEND_API void ZEND_FASTCALL zend_check_internal_arg_type(zend_function *zf, uint32_t arg_num, zval *arg)
{
- zend_verify_internal_arg_type(zf, arg_num, arg);
+ void *dummy_cache_slot = NULL;
+
+ zend_verify_arg_type(zf, arg_num, arg, NULL, &dummy_cache_slot);
}
ZEND_API int ZEND_FASTCALL zend_check_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value, void **cache_slot)
@@ -3059,4 +3060,6 @@ ZEND_API int ZEND_FASTCALL zend_check_arg_type(zend_function *zf, uint32_t arg_n
* c-basic-offset: 4
* indent-tabs-mode: t
* End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
*/